PageRenderTime 26ms CodeModel.GetById 11ms app.highlight 12ms RepoModel.GetById 1ms app.codeStats 0ms

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

http://eyes-free.googlecode.com/
Java | 302 lines | 221 code | 53 blank | 28 comment | 27 complexity | eb73ff70f281c8f5b5e9eb17157becd1 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.app.Activity;
 19import android.content.Intent;
 20import android.content.res.Resources;
 21import android.os.Bundle;
 22import android.os.Handler;
 23import android.os.Message;
 24import android.speech.tts.TextToSpeech;
 25import android.util.Log;
 26import android.view.GestureDetector;
 27import android.view.KeyEvent;
 28import android.view.MotionEvent;
 29import android.view.SurfaceHolder;
 30import android.view.SurfaceView;
 31import android.view.View;
 32import android.view.Window;
 33import android.view.WindowManager;
 34import android.view.GestureDetector.SimpleOnGestureListener;
 35import android.view.View.OnTouchListener;
 36
 37import com.android.ocr.client.Config;
 38import com.android.ocr.client.Intents;
 39
 40import java.io.IOException;
 41
 42/**
 43 * Based on code from ZXing licensed under Apache License, Version 2.0.
 44 * 
 45 * Modified from com.google.marvin.ocr.intent.CaptureActivity to allow
 46 * swipe-based setting of the text enhancement mode.
 47 * 
 48 * @author alanv@google.com (Alan Viverette)
 49 */
 50public class CaptureActivity extends Activity implements SurfaceHolder.Callback, OnTouchListener {
 51  private static final String TAG = "CaptureActivity";
 52
 53  private static final int DEFAULT_WIDTH = 1024;
 54  private static final int DEFAULT_HEIGHT = 768;
 55
 56  private static final int MODE_DENSE = 0;
 57  private static final int MODE_SPARSE = 1;
 58
 59  private static final int ACTION_FOCUS = 0;
 60  private static final int ACTION_TAKE_PICTURE = 1;
 61
 62  private enum State {
 63    IDLE, FOCUSING, TAKING_PICTURE, COMPLETE
 64  }
 65
 66  private boolean mHasSurface;
 67  private int mMode;
 68
 69  private TextToSpeech mTts;
 70  private CameraManager mCameraManager;
 71  private GestureDetector mGestureDetector;
 72  private SimpleOnGestureListener mGestureListener;
 73  private State mState;
 74
 75  private String[] mModes;
 76
 77  private final Handler mHandler = new Handler() {
 78    @Override
 79    public void handleMessage(Message message) {
 80      switch (message.what) {
 81        case ACTION_FOCUS: {
 82          // Completed focusing, now attempt to take preview or picture
 83          onFocused();
 84          break;
 85        }
 86        case ACTION_TAKE_PICTURE: {
 87          // Obtained picture, now perform full text recognition
 88          if (message.obj == null || message.obj instanceof byte[]) {
 89            onPictureTaken((byte[]) message.obj, message.arg1, message.arg2);
 90          }
 91          break;
 92        }
 93      }
 94    }
 95  };
 96
 97  /** Called with the activity is first created. */
 98  @Override
 99  public void onCreate(Bundle savedInstanceState) {
100    Log.i(TAG, "Creating CaptureActivity");
101
102    super.onCreate(savedInstanceState);
103
104    Window window = getWindow();
105    window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
106
107    setContentView(R.layout.capture);
108
109    mTts = ReaderActivity.mTts;
110
111    Resources resources = getResources();
112    mModes = resources.getStringArray(R.array.modes);
113
114    mGestureListener = new CaptureGestureListener();
115    mGestureDetector = new GestureDetector(mGestureListener);
116
117    SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview);
118    surfaceView.setOnTouchListener(this);
119
120    mCameraManager = CameraManager.init(getApplication());
121    mCameraManager.setPictureSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
122    mHasSurface = false;
123  }
124
125  @Override
126  protected void onResume() {
127    super.onResume();
128
129    SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview);
130    SurfaceHolder surfaceHolder = surfaceView.getHolder();
131
132    if (mHasSurface) {
133      initCamera(surfaceHolder);
134    } else {
135      surfaceHolder.addCallback(this);
136      surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
137    }
138  }
139
140  @Override
141  protected void onPause() {
142    mCameraManager.closeDriver();
143
144    super.onPause();
145  }
146
147  @Override
148  protected void onDestroy() {
149
150    super.onDestroy();
151  }
152
153  @Override
154  public void surfaceCreated(SurfaceHolder holder) {
155    if (!mHasSurface) {
156      mHasSurface = true;
157      initCamera(holder);
158    }
159  }
160
161  @Override
162  public void surfaceDestroyed(SurfaceHolder holder) {
163    mHasSurface = false;
164  }
165
166  @Override
167  public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
168    // Do nothing
169  }
170
171  @Override
172  public boolean onKeyDown(int keyCode, KeyEvent event) {
173    switch (keyCode) {
174      case KeyEvent.KEYCODE_BACK:
175        if (mState != State.TAKING_PICTURE) {
176          setResult(RESULT_CANCELED);
177          finish();
178        }
179        return true;
180      case KeyEvent.KEYCODE_FOCUS:
181        if (event.getRepeatCount() == 0) {
182          mState = State.FOCUSING;
183          mCameraManager.requestAutoFocus(mHandler, ACTION_FOCUS);
184        }
185        return true;
186      case KeyEvent.KEYCODE_DPAD_CENTER:
187      case KeyEvent.KEYCODE_CAMERA:
188        if (event.getRepeatCount() == 0) {
189          mState = State.TAKING_PICTURE;
190          mCameraManager.requestAutoFocus(mHandler, ACTION_FOCUS);
191        }
192        return true;
193    }
194
195    return super.onKeyDown(keyCode, event);
196  }
197
198  @Override
199  public boolean onKeyUp(int keyCode, KeyEvent event) {
200    // TODO Is this necessary?
201    switch (keyCode) {
202      case KeyEvent.KEYCODE_FOCUS:
203        return true;
204    }
205
206    return super.onKeyUp(keyCode, event);
207  }
208
209  private void initCamera(SurfaceHolder surfaceHolder) {
210    try {
211      mCameraManager.openDriver(surfaceHolder);
212      mCameraManager.startPreview();
213
214      mTts.speak("ready", TextToSpeech.QUEUE_FLUSH, null);
215    } catch (IOException e) {
216      Log.e(TAG, e.toString());
217    }
218  }
219
220  private void onFocused() {
221    if (mState == State.TAKING_PICTURE) {
222      mCameraManager.requestTakePicture(mHandler, ACTION_TAKE_PICTURE);
223    } else {
224      mState = State.IDLE;
225    }
226  }
227
228  private void onPictureTaken(final byte[] data, int width, int height) {
229    mState = State.IDLE;
230
231    Config config = new Config();
232    config.image = data;
233    config.width = width;
234    config.height = height;
235    config.format = Config.FORMAT_JPEG;
236
237    switch (mMode) {
238      case MODE_DENSE: {
239        config.options |= Config.OPT_NORMALIZE_BG;
240        break;
241      }
242      case MODE_SPARSE: {
243        config.options |= Config.OPT_DETECT_TEXT;
244      }
245    }
246
247    Intent result = new Intent();
248    result.setAction(Intents.Capture.ACTION);
249    result.putExtra(Intents.Capture.CONFIG, config);
250
251    setResult(RESULT_OK, result);
252    finish();
253  }
254
255  @Override
256  public boolean onTouch(View v, MotionEvent event) {
257    mGestureDetector.onTouchEvent(event);
258
259    return true;
260  }
261
262  private void cycleMode(int direction) {
263    mMode = (mMode + direction) % mModes.length;
264
265    if (mMode < 0) {
266      mMode += mModes.length;
267    }
268
269    mTts.speak(mModes[mMode], TextToSpeech.QUEUE_FLUSH, null);
270  }
271
272  private class CaptureGestureListener extends SimpleOnGestureListener {
273    private static final int SWIPE_MIN_DISTANCE = 120;
274    private static final int SWIPE_THRESHOLD_VELOCITY = 200;
275
276    @Override
277    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
278      float distX = e1.getX() - e2.getX();
279      float distY = e1.getY() - e2.getY();
280
281      if (Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY
282          || Math.abs(velocityY) > SWIPE_THRESHOLD_VELOCITY) {
283        if (distX > SWIPE_MIN_DISTANCE || distY > SWIPE_MIN_DISTANCE) {
284          cycleMode(1);
285          return true;
286        } else if (distX < -1 * SWIPE_MIN_DISTANCE || distY < -1 * SWIPE_MIN_DISTANCE) {
287          cycleMode(-1);
288          return true;
289        }
290      }
291
292      return false;
293    }
294
295    @Override
296    public boolean onSingleTapConfirmed(MotionEvent e) {
297      mState = State.TAKING_PICTURE;
298      mCameraManager.requestAutoFocus(mHandler, ACTION_FOCUS);
299      return true;
300    }
301  }
302}