/ocr/worldreader/src/com/google/marvin/worldreader/CameraManager.java
Java | 231 lines | 159 code | 29 blank | 43 comment | 32 complexity | 64e2bc4dc37c1281b7324481c7a193d6 MD5 | raw file
1/* 2 * Copyright (C) 2009 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16package com.google.marvin.worldreader; 17 18import android.content.Context; 19import android.graphics.PixelFormat; 20import android.graphics.Point; 21import android.hardware.Camera; 22import android.os.Handler; 23import android.os.Message; 24import android.util.Log; 25import android.view.Display; 26import android.view.SurfaceHolder; 27import android.view.WindowManager; 28 29import java.io.IOException; 30 31/** 32 * This object wraps the Camera service object and expects to be the only one 33 * talking to it. The implementation encapsulates the steps needed to take 34 * preview-sized images, which are used for both preview and decoding. 35 * 36 * Based on code from ZXing licensed under Apache License, Version 2.0. 37 * 38 * @author alanv@google.com (Alan Viverette) 39 */ 40public class CameraManager { 41 private static final String TAG = "CameraManager"; 42 43 private static CameraManager mCameraManager; 44 45 private Camera mCamera; 46 private final Context mContext; 47 private Point mScreenResolution; 48 private Handler mPreviewHandler; 49 private int mPreviewMessage; 50 private Handler mAutoFocusHandler; 51 private int mAutoFocusMessage; 52 private Handler mTakePictureHandler; 53 private int mTakePictureMessage; 54 private boolean mInitialized; 55 private boolean mPreviewing; 56 private int mPictureWidth; 57 private int mPictureHeight; 58 59 public static CameraManager init(Context context) { 60 if (mCameraManager == null) { 61 mCameraManager = new CameraManager(context); 62 } 63 64 return mCameraManager; 65 } 66 67 public static CameraManager get() { 68 return mCameraManager; 69 } 70 71 private CameraManager(Context context) { 72 mContext = context; 73 mCamera = null; 74 mInitialized = false; 75 mPreviewing = false; 76 } 77 78 public void openDriver(SurfaceHolder holder) throws IOException { 79 Log.i(TAG, "Opening camera driver..."); 80 81 if (mCamera == null) { 82 mCamera = Camera.open(); 83 mCamera.setPreviewDisplay(holder); 84 85 if (!mInitialized) { 86 mInitialized = true; 87 getScreenResolution(); 88 } 89 90 setPreviewParameters(); 91 } 92 } 93 94 public void closeDriver() { 95 Log.i(TAG, "Closing camera driver..."); 96 97 if (mCamera != null) { 98 mCamera.release(); 99 mCamera = null; 100 mPreviewing = false; 101 } 102 } 103 104 public void startPreview() { 105 if (mCamera != null && !mPreviewing) { 106 mCamera.startPreview(); 107 mPreviewing = true; 108 } 109 } 110 111 public void stopPreview() { 112 if (mCamera != null && mPreviewing) { 113 mCamera.setPreviewCallback(null); 114 mCamera.stopPreview(); 115 mPreviewHandler = null; 116 mAutoFocusHandler = null; 117 mPreviewing = false; 118 } 119 } 120 121 /** 122 * A single preview frame will be returned to the handler supplied. The data 123 * will arrive as byte[] in the message.obj field, with width and height 124 * encoded as message.arg1 and message.arg2, respectively. 125 * 126 * @param handler The handler to send the message to. 127 * @param message The what field of the message to be sent. 128 */ 129 public void requestPreviewFrame(Handler handler, int message) { 130 if (mCamera != null && mPreviewing) { 131 mPreviewHandler = handler; 132 mPreviewMessage = message; 133 mCamera.setPreviewCallback(previewCallback); 134 } 135 } 136 137 public void requestTakePicture(Handler handler, int message) { 138 if (mCamera != null && mPreviewing) { 139 if (mPictureWidth > 0 && mPictureHeight > 0) { 140 Camera.Parameters parameters = mCamera.getParameters(); 141 parameters.setPictureFormat(PixelFormat.JPEG); 142 parameters.setPictureSize(mPictureWidth, mPictureHeight); 143 parameters.set("orientation", "landscape"); 144 mCamera.setParameters(parameters); 145 } 146 147 mTakePictureHandler = handler; 148 mTakePictureMessage = message; 149 mCamera.takePicture(null, null, takePictureCallback); 150 } 151 } 152 153 public void requestAutoFocus(Handler handler, int message) { 154 if (mCamera != null && mPreviewing) { 155 mAutoFocusHandler = handler; 156 mAutoFocusMessage = message; 157 mCamera.autoFocus(autoFocusCallback); 158 } 159 } 160 161 /** 162 * Preview frames are delivered here, which we pass on to the registered 163 * handler. Make sure to clear the handler so it will only receive one 164 * message. 165 */ 166 private final Camera.PreviewCallback previewCallback = new Camera.PreviewCallback() { 167 public void onPreviewFrame(byte[] data, Camera camera) { 168 camera.setPreviewCallback(null); 169 if (mPreviewHandler != null) { 170 Camera.Parameters parameters = camera.getParameters(); 171 Camera.Size size = parameters.getPreviewSize(); 172 Message message = 173 mPreviewHandler.obtainMessage(mPreviewMessage, size.width, size.height, data); 174 message.sendToTarget(); 175 mPreviewHandler = null; 176 } 177 } 178 }; 179 180 private final Camera.PictureCallback takePictureCallback = new Camera.PictureCallback() { 181 public void onPictureTaken(byte[] data, Camera camera) { 182 if (mTakePictureHandler != null) { 183 Camera.Parameters parameters = camera.getParameters(); 184 Camera.Size size = parameters.getPictureSize(); 185 Message message = 186 mTakePictureHandler.obtainMessage(mTakePictureMessage, size.width, size.height, data); 187 message.sendToTarget(); 188 mTakePictureHandler = null; 189 } 190 } 191 }; 192 193 private final Camera.AutoFocusCallback autoFocusCallback = new Camera.AutoFocusCallback() { 194 public void onAutoFocus(boolean success, Camera camera) { 195 if (mAutoFocusHandler != null) { 196 Message message = mAutoFocusHandler.obtainMessage(mAutoFocusMessage, success); 197 message.sendToTarget(); 198 199 mAutoFocusHandler = null; 200 } 201 } 202 }; 203 204 /** 205 * Sets the camera up to take preview images which are used for both preview 206 * and decoding. We're counting on the default YUV420 semi-planar data. If 207 * that changes in the future, we'll need to specify it explicitly with 208 * setPreviewFormat(). 209 */ 210 private void setPreviewParameters() { 211 Camera.Parameters parameters = mCamera.getParameters(); 212 parameters.setPreviewFormat(PixelFormat.YCbCr_420_SP); 213 parameters.setPreviewSize(mScreenResolution.x, mScreenResolution.y); 214 mCamera.setParameters(parameters); 215 } 216 217 public void setPictureSize(int width, int height) { 218 mPictureWidth = width; 219 mPictureHeight = height; 220 } 221 222 private Point getScreenResolution() { 223 if (mScreenResolution == null) { 224 WindowManager manager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); 225 Display display = manager.getDefaultDisplay(); 226 mScreenResolution = new Point(display.getWidth(), display.getHeight()); 227 } 228 229 return mScreenResolution; 230 } 231}