package com.google.zxing.client.android;
-import com.google.zxing.ResultPoint;
-
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
+import com.google.zxing.ResultPoint;
/**
* @author dswitkin@google.com (Daniel Switkin)
*/
final class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
- private static int[] SCANNER_ALPHA = { 0, 64, 128, 192, 255, 192, 128, 64 };
-
+ private static int[] SCANNER_ALPHA = {0, 64, 128, 192, 255, 192, 128, 64};
+
private CameraManager cameraManager;
private SurfaceHolder surfaceHolder;
private boolean hasSurface;
private int scannerAlpha;
-
- CameraSurfaceView(Context context, CameraManager cameraManager) {
- super(context);
- this.cameraManager = cameraManager;
-
- // Install a SurfaceHolder.Callback so we get notified when the underlying surface is created
- // and destroyed.
- surfaceHolder = getHolder();
- surfaceHolder.setCallback(this);
- hasSurface = false;
- scannerAlpha = 0;
-
- // FIXME(dswitkin): This resolution needs to be made dynamic to handle different devices and
- // orientations.
- surfaceHolder.setFixedSize(320, 240);
- }
- public boolean surfaceCreated(SurfaceHolder holder) {
- hasSurface = true;
+ CameraSurfaceView(Context context, CameraManager cameraManager) {
+ super(context);
+ this.cameraManager = cameraManager;
- // Tell the system that we filled the surface in this call. This is a lie to prevent the system
- // from filling the surface for us automatically. THIS IS REQUIRED because otherwise we'll
- // access the Surface object from 2 different threads which is not allowed.
- return true;
- }
+ // Install a SurfaceHolder.Callback so we get notified when the underlying surface is created
+ // and destroyed.
+ surfaceHolder = getHolder();
+ surfaceHolder.setCallback(this);
+ hasSurface = false;
+ scannerAlpha = 0;
- public void surfaceDestroyed(SurfaceHolder holder) {
- // FIXME(dswitkin): The docs say this surface will be destroyed when this method returns. In
- // practice this has not been a problem so far. I need to investigate.
- hasSurface = false;
- }
+ // FIXME(dswitkin): This resolution needs to be made dynamic to handle different devices and
+ // orientations.
+ surfaceHolder.setFixedSize(320, 240);
+ }
- public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
- // Surface size or format has changed. This won't happen because of the setFixedSize() call.
- }
-
- /**
- * This method is only called from the WorkerThread. It's job is to grab the next preview frame
- * from the camera, draw the framing rectangle, and blit everything to the screen.
- */
- public void capturePreviewAndDraw() {
+ public boolean surfaceCreated(SurfaceHolder holder) {
+ hasSurface = true;
+
+ // Tell the system that we filled the surface in this call. This is a lie to prevent the system
+ // from filling the surface for us automatically. THIS IS REQUIRED because otherwise we'll
+ // access the Surface object from 2 different threads which is not allowed.
+ return true;
+ }
+
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ // FIXME(dswitkin): The docs say this surface will be destroyed when this method returns. In
+ // practice this has not been a problem so far. I need to investigate.
+ hasSurface = false;
+ }
+
+ public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+ // Surface size or format has changed. This won't happen because of the setFixedSize() call.
+ }
+
+ /**
+ * This method is only called from the WorkerThread. It's job is to grab the next preview frame
+ * from the camera, draw the framing rectangle, and blit everything to the screen.
+ */
+ public void capturePreviewAndDraw() {
if (hasSurface) {
Canvas canvas = surfaceHolder.lockCanvas();
cameraManager.capturePreview(canvas);
Rect frame = cameraManager.getFramingRect();
int width = canvas.getBitmapWidth();
int height = canvas.getBitmapHeight();
-
+
// Draw the exterior (i.e. outside the framing rect) as half darkened
Paint paint = new Paint();
paint.setColor(Color.BLACK);
canvas.drawRect(box, paint);
box.set(0, frame.bottom + 1, width, height);
canvas.drawRect(box, paint);
-
+
// Draw a two pixel solid black border inside the framing rect
paint.setAlpha(255);
box.set(frame.left, frame.top, frame.right + 1, frame.top + 2);
canvas.drawRect(box, paint);
box.set(frame.left, frame.bottom - 1, frame.right + 1, frame.bottom + 1);
canvas.drawRect(box, paint);
-
+
// Draw a red "laser scanner" line through the middle
paint.setColor(Color.RED);
paint.setAlpha(SCANNER_ALPHA[scannerAlpha]);
int middle = frame.height() / 2 + frame.top;
box.set(frame.left + 2, middle - 1, frame.right - 1, middle + 2);
canvas.drawRect(box, paint);
-
+
surfaceHolder.unlockCanvasAndPost(canvas);
-
+
// This cheap animation is tied to the rate at which we pull previews from the camera.
scannerAlpha = (scannerAlpha + 1) % SCANNER_ALPHA.length;
}
- }
-
- /**
- * Draw a line for 1D barcodes (which return two points) or otherwise a set of points returned
- * from the decoder to indicate what we found.
- * TODO(dswitkin): It might be nice to clear the framing rect and zoom in on the actual still that
- * was captured, then paint the green points on it. This would also clear the red scanner line
- * which doesn't make sense after the capture.
- *
- * @param resultPoints An array of points from the decoder, whose coordinates are expressed
- * relative to the still image from the camera.
- */
- public void drawResultPoints(ResultPoint[] resultPoints) {
+ }
+
+ /**
+ * Draw a line for 1D barcodes (which return two points) or otherwise a set of points returned
+ * from the decoder to indicate what we found.
+ * TODO(dswitkin): It might be nice to clear the framing rect and zoom in on the actual still that
+ * was captured, then paint the green points on it. This would also clear the red scanner line
+ * which doesn't make sense after the capture.
+ *
+ * @param resultPoints An array of points from the decoder, whose coordinates are expressed
+ * relative to the still image from the camera.
+ */
+ public void drawResultPoints(ResultPoint[] resultPoints) {
if (hasSurface) {
Canvas canvas = surfaceHolder.lockCanvas();
Paint paint = new Paint();
paint.setColor(Color.GREEN);
paint.setAlpha(128);
-
+
Point[] points = cameraManager.convertResultPoints(resultPoints);
if (points.length == 2) {
paint.setStrokeWidth(4);
canvas.drawPoint(points[x].x, points[x].y, paint);
}
}
-
+
surfaceHolder.unlockCanvasAndPost(canvas);
}
}