17620644768ffc235607b3a94671e49518c18686fBryan Mawhinney/*
27620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * Copyright (C) 2010 ZXing authors
37620644768ffc235607b3a94671e49518c18686fBryan Mawhinney *
47620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * Licensed under the Apache License, Version 2.0 (the "License");
57620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * you may not use this file except in compliance with the License.
67620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * You may obtain a copy of the License at
77620644768ffc235607b3a94671e49518c18686fBryan Mawhinney *
87620644768ffc235607b3a94671e49518c18686fBryan Mawhinney *      http://www.apache.org/licenses/LICENSE-2.0
97620644768ffc235607b3a94671e49518c18686fBryan Mawhinney *
107620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * Unless required by applicable law or agreed to in writing, software
117620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * distributed under the License is distributed on an "AS IS" BASIS,
127620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * See the License for the specific language governing permissions and
147620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * limitations under the License.
157620644768ffc235607b3a94671e49518c18686fBryan Mawhinney */
167620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
177620644768ffc235607b3a94671e49518c18686fBryan Mawhinneypackage com.google.zxing.client.android;
187620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
197620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport com.google.zxing.BinaryBitmap;
207620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport com.google.zxing.DecodeHintType;
217620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport com.google.zxing.MultiFormatReader;
227620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport com.google.zxing.ReaderException;
237620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport com.google.zxing.Result;
247620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport com.google.zxing.common.HybridBinarizer;
257620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
267620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.os.Bundle;
277620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.os.Handler;
287620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.os.Looper;
297620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.os.Message;
307620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.util.Log;
317620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
327620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport java.util.Hashtable;
337620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
347620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyfinal class DecodeHandler extends Handler {
357620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
367620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private static final String TAG = DecodeHandler.class.getSimpleName();
377620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
387620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private final CaptureActivity activity;
397620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private final MultiFormatReader multiFormatReader;
407620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private boolean running = true;
417620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
427620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  DecodeHandler(CaptureActivity activity, Hashtable<DecodeHintType,Object> hints) {
437620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    multiFormatReader = new MultiFormatReader();
447620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    multiFormatReader.setHints(hints);
457620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    this.activity = activity;
467620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
477620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
487620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  @Override
497620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  public void handleMessage(Message message) {
507620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    if (!running) {
517620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      return;
527620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    }
537620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    if (message.what == R.id.decode) {
547620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      decode((byte[]) message.obj, message.arg1, message.arg2);
557620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    } else if (message.what == R.id.quit) {
567620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      running = false;
577620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      Looper.myLooper().quit();
587620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    }
597620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
607620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
617620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  /**
627620644768ffc235607b3a94671e49518c18686fBryan Mawhinney   * Decode the data within the viewfinder rectangle, and time how long it took. For efficiency,
637620644768ffc235607b3a94671e49518c18686fBryan Mawhinney   * reuse the same reader objects from one decode to the next.
647620644768ffc235607b3a94671e49518c18686fBryan Mawhinney   *
657620644768ffc235607b3a94671e49518c18686fBryan Mawhinney   * @param data   The YUV preview frame.
667620644768ffc235607b3a94671e49518c18686fBryan Mawhinney   * @param width  The width of the preview frame.
677620644768ffc235607b3a94671e49518c18686fBryan Mawhinney   * @param height The height of the preview frame.
687620644768ffc235607b3a94671e49518c18686fBryan Mawhinney   */
697620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private void decode(byte[] data, int width, int height) {
707620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    long start = System.currentTimeMillis();
717620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    Result rawResult = null;
727620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    PlanarYUVLuminanceSource source = activity.getCameraManager().buildLuminanceSource(data, width, height);
737620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    if (source != null) {
747620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
757620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      try {
767620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        rawResult = multiFormatReader.decodeWithState(bitmap);
777620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      } catch (ReaderException re) {
787620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        // continue
797620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      } finally {
807620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        multiFormatReader.reset();
817620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      }
827620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    }
837620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
847620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    Handler handler = activity.getHandler();
857620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    if (rawResult != null) {
867620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      // Don't log the barcode contents for security.
877620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      long end = System.currentTimeMillis();
887620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      Log.d(TAG, "Found barcode in " + (end - start) + " ms");
897620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      if (handler != null) {
907620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        Message message = Message.obtain(handler, R.id.decode_succeeded, rawResult);
917620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        Bundle bundle = new Bundle();
927620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        bundle.putParcelable(DecodeThread.BARCODE_BITMAP, source.renderCroppedGreyscaleBitmap());
937620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        message.setData(bundle);
947620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        message.sendToTarget();
957620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      }
967620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    } else {
977620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      if (handler != null) {
987620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        Message message = Message.obtain(handler, R.id.decode_failed);
997620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        message.sendToTarget();
1007620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      }
1017620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    }
1027620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
1037620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
1047620644768ffc235607b3a94671e49518c18686fBryan Mawhinney}
105