]> rtime.felk.cvut.cz Git - hornmich/skoda-qr-demo.git/blob - BarCodeScanner/glass/src/main/java/cz/cvut/fel/dce/barcodescanner/DecodeRunnable.java
Initial commit
[hornmich/skoda-qr-demo.git] / BarCodeScanner / glass / src / main / java / cz / cvut / fel / dce / barcodescanner / DecodeRunnable.java
1 /*
2  * Copyright (C) 2014 ZXing authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of 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,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package cz.cvut.fel.dce.barcodescanner;
18
19 import android.hardware.Camera;
20 import android.os.Handler;
21 import android.os.Looper;
22 import android.os.Message;
23 import android.util.Log;
24
25 import com.google.zxing.BarcodeFormat;
26 import com.google.zxing.BinaryBitmap;
27 import com.google.zxing.DecodeHintType;
28 import com.google.zxing.MultiFormatReader;
29 import com.google.zxing.PlanarYUVLuminanceSource;
30 import com.google.zxing.ReaderException;
31 import com.google.zxing.Result;
32 import com.google.zxing.common.HybridBinarizer;
33
34 import java.util.Arrays;
35 import java.util.EnumMap;
36 import java.util.Map;
37 import java.util.concurrent.CountDownLatch;
38
39 /**
40  * @author Sean Owen
41  */
42 final class DecodeRunnable implements Runnable, Camera.PreviewCallback {
43
44   private static final String TAG = DecodeRunnable.class.getSimpleName();
45
46   private final CaptureActivity activity;
47   private final Camera camera;
48   private final int height;
49   private final int width;
50   private final byte[] previewBuffer;
51   private boolean running;
52   private Handler handler;
53   private final CountDownLatch handlerInitLatch;
54
55   DecodeRunnable(CaptureActivity activity, Camera camera) {
56     this.activity = activity;
57     this.camera = camera;
58     Camera.Parameters parameters = camera.getParameters();
59     Camera.Size previewSize = parameters.getPreviewSize();
60     height = previewSize.height;
61     width = previewSize.width;
62     previewBuffer = new byte[(height * width * 3) / 2];
63     running = true;
64     handlerInitLatch = new CountDownLatch(1);
65   }
66
67   private Handler getHandler() {
68     try {
69       handlerInitLatch.await();
70     } catch (InterruptedException ie) {
71       // continue?
72     }
73     return handler;
74   }
75
76
77   @Override
78   public void run() {
79     Looper.prepare();
80     handler = new DecodeHandler();
81     handlerInitLatch.countDown();
82     Looper.loop();
83   }
84
85   void startScanning() {
86     getHandler().obtainMessage(R.id.decode_start).sendToTarget();
87   }
88
89   void stop() {
90     getHandler().obtainMessage(R.id.quit).sendToTarget();
91   }
92
93   @Override
94   public void onPreviewFrame(byte[] data, Camera camera) {
95     if (running) {
96       getHandler().obtainMessage(R.id.decode, data).sendToTarget();
97     }
98   }
99
100   private final class DecodeHandler extends Handler {
101
102     private final Map<DecodeHintType,Object> hints;
103
104     DecodeHandler() {
105       hints = new EnumMap<>(DecodeHintType.class);
106       hints.put(DecodeHintType.POSSIBLE_FORMATS,
107           Arrays.asList(BarcodeFormat.AZTEC, BarcodeFormat.QR_CODE, BarcodeFormat.DATA_MATRIX));
108     }
109
110     @Override
111     public void handleMessage(Message message) {
112       if (!running) {
113         return;
114       }
115       switch (message.what) {
116         case R.id.decode_start:
117           camera.setPreviewCallbackWithBuffer(DecodeRunnable.this);
118           camera.addCallbackBuffer(previewBuffer);
119           break;
120         case R.id.decode:
121           decode((byte[]) message.obj);
122           break;
123         case R.id.decode_succeeded:
124           final Result result = (Result) message.obj;
125           activity.runOnUiThread(new Runnable() {
126             @Override
127             public void run() {
128               activity.setResult(result);
129             }
130           });
131           break;
132         case R.id.decode_failed:
133           camera.addCallbackBuffer(previewBuffer);
134           break;
135         case R.id.quit:
136           running = false;
137           Looper.myLooper().quit();
138           break;
139       }
140     }
141
142     private void decode(byte[] data) {
143       Result rawResult = null;
144
145       int subtendedWidth = width / CameraConfigurationManager.ZOOM;
146       int subtendedHeight = height / CameraConfigurationManager.ZOOM;
147       int excessWidth = width - subtendedWidth;
148       int excessHeight = height - subtendedHeight;
149
150       //long start = System.currentTimeMillis();
151       PlanarYUVLuminanceSource source =
152           new PlanarYUVLuminanceSource(data,
153                                        width, height,
154                                        excessWidth / 2, excessHeight / 2,
155                                        subtendedWidth, subtendedHeight,
156                                        false);
157       BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
158       try {
159         rawResult = new MultiFormatReader().decode(bitmap, hints);
160       } catch (ReaderException re) {
161         // continue
162       }
163
164       //long end = System.currentTimeMillis();
165       //Log.i(TAG, "Decode in " + (end - start));
166       Handler handler = getHandler();
167       Message message;
168       if (rawResult == null) {
169         message = handler.obtainMessage(R.id.decode_failed);
170       } else {
171         Log.i(TAG, "Decode succeeded: " + rawResult.getText());
172         message = handler.obtainMessage(R.id.decode_succeeded, rawResult);
173       }
174       message.sendToTarget();
175     }
176
177   }
178
179 }