PageRenderTime 39ms CodeModel.GetById 18ms app.highlight 16ms RepoModel.GetById 1ms app.codeStats 0ms

/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 */
 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}