2 * Copyright 2008 ZXing authors
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.google.zxing.client.android;
19 import android.content.Context;
20 import android.graphics.Canvas;
21 import android.graphics.Color;
22 import android.graphics.Paint;
23 import android.graphics.Point;
24 import android.graphics.Rect;
25 import android.view.SurfaceHolder;
26 import android.view.SurfaceView;
27 import com.google.zxing.ResultPoint;
30 * @author dswitkin@google.com (Daniel Switkin)
32 final class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
34 private static final int[] SCANNER_ALPHA = {0, 64, 128, 192, 255, 192, 128, 64};
36 private final CameraManager cameraManager;
37 private final SurfaceHolder surfaceHolder;
38 private boolean hasSurface;
39 private int scannerAlpha;
41 CameraSurfaceView(Context context, CameraManager cameraManager) {
43 this.cameraManager = cameraManager;
45 // Install a SurfaceHolder.Callback so we get notified when the underlying surface is created
47 surfaceHolder = getHolder();
48 surfaceHolder.addCallback(this);
51 surfaceHolder.setSizeFromLayout();
54 public void surfaceCreated(SurfaceHolder holder) {
58 public void surfaceDestroyed(SurfaceHolder holder) {
59 // FIXME(dswitkin): The docs say this surface will be destroyed when this method returns. In
60 // practice this has not been a problem so far. I need to investigate.
64 public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
65 // Surface size or format has changed. This won't happen because of the setFixedSize() call.
69 * This method is only called from the WorkerThread. It's job is to grab the next preview frame
70 * from the camera, draw the framing rectangle, and blit everything to the screen.
72 public void capturePreviewAndDraw() {
74 Canvas canvas = surfaceHolder.lockCanvas();
75 cameraManager.capturePreview(canvas);
76 Rect frame = cameraManager.getFramingRect();
77 int width = canvas.getBitmapWidth();
78 int height = canvas.getBitmapHeight();
80 // Draw the exterior (i.e. outside the framing rect) as half darkened
81 Paint paint = new Paint();
82 paint.setColor(Color.BLACK);
84 Rect box = new Rect(0, 0, width, frame.top);
85 canvas.drawRect(box, paint);
86 box.set(0, frame.top, frame.left, frame.bottom + 1);
87 canvas.drawRect(box, paint);
88 box.set(frame.right + 1, frame.top, width, frame.bottom + 1);
89 canvas.drawRect(box, paint);
90 box.set(0, frame.bottom + 1, width, height);
91 canvas.drawRect(box, paint);
93 // Draw a two pixel solid black border inside the framing rect
95 box.set(frame.left, frame.top, frame.right + 1, frame.top + 2);
96 canvas.drawRect(box, paint);
97 box.set(frame.left, frame.top + 2, frame.left + 2, frame.bottom - 1);
98 canvas.drawRect(box, paint);
99 box.set(frame.right - 1, frame.top, frame.right + 1, frame.bottom - 1);
100 canvas.drawRect(box, paint);
101 box.set(frame.left, frame.bottom - 1, frame.right + 1, frame.bottom + 1);
102 canvas.drawRect(box, paint);
104 // Draw a red "laser scanner" line through the middle
105 paint.setColor(Color.RED);
106 paint.setAlpha(SCANNER_ALPHA[scannerAlpha]);
107 int middle = frame.height() / 2 + frame.top;
108 box.set(frame.left + 2, middle - 1, frame.right - 1, middle + 2);
109 canvas.drawRect(box, paint);
111 surfaceHolder.unlockCanvasAndPost(canvas);
113 // This cheap animation is tied to the rate at which we pull previews from the camera.
114 scannerAlpha = (scannerAlpha + 1) % SCANNER_ALPHA.length;
119 * Draw a line for 1D barcodes (which return two points) or otherwise a set of points returned
120 * from the decoder to indicate what we found.
121 * TODO(dswitkin): It might be nice to clear the framing rect and zoom in on the actual still that
122 * was captured, then paint the green points on it. This would also clear the red scanner line
123 * which doesn't make sense after the capture.
125 * @param resultPoints An array of points from the decoder, whose coordinates are expressed
126 * relative to the still image from the camera.
128 public void drawResultPoints(ResultPoint[] resultPoints) {
130 Canvas canvas = surfaceHolder.lockCanvas();
131 Paint paint = new Paint();
132 paint.setColor(Color.GREEN);
135 Point[] points = cameraManager.convertResultPoints(resultPoints);
136 if (points.length == 2) {
137 paint.setStrokeWidth(4);
138 canvas.drawLine(points[0].x, points[0].y, points[1].x, points[1].y, paint);
140 paint.setStrokeWidth(10);
141 for (int x = 0; x < points.length; x++) {
142 canvas.drawPoint(points[x].x, points[x].y, paint);
146 surfaceHolder.unlockCanvasAndPost(canvas);