/ocr/worldreader/src/com/google/marvin/worldreader/CameraManager.java

http://eyes-free.googlecode.com/ · 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. */
  16. package com.google.marvin.worldreader;
  17. import android.content.Context;
  18. import android.graphics.PixelFormat;
  19. import android.graphics.Point;
  20. import android.hardware.Camera;
  21. import android.os.Handler;
  22. import android.os.Message;
  23. import android.util.Log;
  24. import android.view.Display;
  25. import android.view.SurfaceHolder;
  26. import android.view.WindowManager;
  27. import java.io.IOException;
  28. /**
  29. * This object wraps the Camera service object and expects to be the only one
  30. * talking to it. The implementation encapsulates the steps needed to take
  31. * preview-sized images, which are used for both preview and decoding.
  32. *
  33. * Based on code from ZXing licensed under Apache License, Version 2.0.
  34. *
  35. * @author alanv@google.com (Alan Viverette)
  36. */
  37. public class CameraManager {
  38. private static final String TAG = "CameraManager";
  39. private static CameraManager mCameraManager;
  40. private Camera mCamera;
  41. private final Context mContext;
  42. private Point mScreenResolution;
  43. private Handler mPreviewHandler;
  44. private int mPreviewMessage;
  45. private Handler mAutoFocusHandler;
  46. private int mAutoFocusMessage;
  47. private Handler mTakePictureHandler;
  48. private int mTakePictureMessage;
  49. private boolean mInitialized;
  50. private boolean mPreviewing;
  51. private int mPictureWidth;
  52. private int mPictureHeight;
  53. public static CameraManager init(Context context) {
  54. if (mCameraManager == null) {
  55. mCameraManager = new CameraManager(context);
  56. }
  57. return mCameraManager;
  58. }
  59. public static CameraManager get() {
  60. return mCameraManager;
  61. }
  62. private CameraManager(Context context) {
  63. mContext = context;
  64. mCamera = null;
  65. mInitialized = false;
  66. mPreviewing = false;
  67. }
  68. public void openDriver(SurfaceHolder holder) throws IOException {
  69. Log.i(TAG, "Opening camera driver...");
  70. if (mCamera == null) {
  71. mCamera = Camera.open();
  72. mCamera.setPreviewDisplay(holder);
  73. if (!mInitialized) {
  74. mInitialized = true;
  75. getScreenResolution();
  76. }
  77. setPreviewParameters();
  78. }
  79. }
  80. public void closeDriver() {
  81. Log.i(TAG, "Closing camera driver...");
  82. if (mCamera != null) {
  83. mCamera.release();
  84. mCamera = null;
  85. mPreviewing = false;
  86. }
  87. }
  88. public void startPreview() {
  89. if (mCamera != null && !mPreviewing) {
  90. mCamera.startPreview();
  91. mPreviewing = true;
  92. }
  93. }
  94. public void stopPreview() {
  95. if (mCamera != null && mPreviewing) {
  96. mCamera.setPreviewCallback(null);
  97. mCamera.stopPreview();
  98. mPreviewHandler = null;
  99. mAutoFocusHandler = null;
  100. mPreviewing = false;
  101. }
  102. }
  103. /**
  104. * A single preview frame will be returned to the handler supplied. The data
  105. * will arrive as byte[] in the message.obj field, with width and height
  106. * encoded as message.arg1 and message.arg2, respectively.
  107. *
  108. * @param handler The handler to send the message to.
  109. * @param message The what field of the message to be sent.
  110. */
  111. public void requestPreviewFrame(Handler handler, int message) {
  112. if (mCamera != null && mPreviewing) {
  113. mPreviewHandler = handler;
  114. mPreviewMessage = message;
  115. mCamera.setPreviewCallback(previewCallback);
  116. }
  117. }
  118. public void requestTakePicture(Handler handler, int message) {
  119. if (mCamera != null && mPreviewing) {
  120. if (mPictureWidth > 0 && mPictureHeight > 0) {
  121. Camera.Parameters parameters = mCamera.getParameters();
  122. parameters.setPictureFormat(PixelFormat.JPEG);
  123. parameters.setPictureSize(mPictureWidth, mPictureHeight);
  124. parameters.set("orientation", "landscape");
  125. mCamera.setParameters(parameters);
  126. }
  127. mTakePictureHandler = handler;
  128. mTakePictureMessage = message;
  129. mCamera.takePicture(null, null, takePictureCallback);
  130. }
  131. }
  132. public void requestAutoFocus(Handler handler, int message) {
  133. if (mCamera != null && mPreviewing) {
  134. mAutoFocusHandler = handler;
  135. mAutoFocusMessage = message;
  136. mCamera.autoFocus(autoFocusCallback);
  137. }
  138. }
  139. /**
  140. * Preview frames are delivered here, which we pass on to the registered
  141. * handler. Make sure to clear the handler so it will only receive one
  142. * message.
  143. */
  144. private final Camera.PreviewCallback previewCallback = new Camera.PreviewCallback() {
  145. public void onPreviewFrame(byte[] data, Camera camera) {
  146. camera.setPreviewCallback(null);
  147. if (mPreviewHandler != null) {
  148. Camera.Parameters parameters = camera.getParameters();
  149. Camera.Size size = parameters.getPreviewSize();
  150. Message message =
  151. mPreviewHandler.obtainMessage(mPreviewMessage, size.width, size.height, data);
  152. message.sendToTarget();
  153. mPreviewHandler = null;
  154. }
  155. }
  156. };
  157. private final Camera.PictureCallback takePictureCallback = new Camera.PictureCallback() {
  158. public void onPictureTaken(byte[] data, Camera camera) {
  159. if (mTakePictureHandler != null) {
  160. Camera.Parameters parameters = camera.getParameters();
  161. Camera.Size size = parameters.getPictureSize();
  162. Message message =
  163. mTakePictureHandler.obtainMessage(mTakePictureMessage, size.width, size.height, data);
  164. message.sendToTarget();
  165. mTakePictureHandler = null;
  166. }
  167. }
  168. };
  169. private final Camera.AutoFocusCallback autoFocusCallback = new Camera.AutoFocusCallback() {
  170. public void onAutoFocus(boolean success, Camera camera) {
  171. if (mAutoFocusHandler != null) {
  172. Message message = mAutoFocusHandler.obtainMessage(mAutoFocusMessage, success);
  173. message.sendToTarget();
  174. mAutoFocusHandler = null;
  175. }
  176. }
  177. };
  178. /**
  179. * Sets the camera up to take preview images which are used for both preview
  180. * and decoding. We're counting on the default YUV420 semi-planar data. If
  181. * that changes in the future, we'll need to specify it explicitly with
  182. * setPreviewFormat().
  183. */
  184. private void setPreviewParameters() {
  185. Camera.Parameters parameters = mCamera.getParameters();
  186. parameters.setPreviewFormat(PixelFormat.YCbCr_420_SP);
  187. parameters.setPreviewSize(mScreenResolution.x, mScreenResolution.y);
  188. mCamera.setParameters(parameters);
  189. }
  190. public void setPictureSize(int width, int height) {
  191. mPictureWidth = width;
  192. mPictureHeight = height;
  193. }
  194. private Point getScreenResolution() {
  195. if (mScreenResolution == null) {
  196. WindowManager manager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
  197. Display display = manager.getDefaultDisplay();
  198. mScreenResolution = new Point(display.getWidth(), display.getHeight());
  199. }
  200. return mScreenResolution;
  201. }
  202. }