Fixed some code which was ignoring the result of MonochromeBitmapSource calls, which...
[zxing.git] / core / src / com / google / zxing / MultiFormatReader.java
1 /*
2  * Copyright 2007 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 com.google.zxing;
18
19 import com.google.zxing.oned.MultiFormatOneDReader;
20 import com.google.zxing.pdf417.PDF417Reader;
21 import com.google.zxing.qrcode.QRCodeReader;
22 import com.google.zxing.datamatrix.DataMatrixReader;
23
24 import java.util.Hashtable;
25 import java.util.Vector;
26
27 /**
28  * MultiFormatReader is a convenience class and the main entry point into the library for most uses.
29  * By default it attempts to decode all barcode formats that the library supports. Optionally, you
30  * can provide a hints object to request different behavior, for example only decoding QR codes.
31  *
32  * @author Sean Owen
33  * @author dswitkin@google.com (Daniel Switkin)
34  */
35 public final class MultiFormatReader implements Reader {
36
37   private Hashtable hints;
38   private Vector readers;
39
40   /**
41    * This version of decode honors the intent of Reader.decode(MonochromeBitmapSource) in that it
42    * passes null as a hint to the decoders. However, that makes it inefficient to call repeatedly.
43    * Use setHints() followed by decodeWithState() for continuous scan applications.
44    *
45    * @param image The pixel data to decode
46    * @return The contents of the image
47    * @throws ReaderException Any errors which occurred
48    */
49   public Result decode(MonochromeBitmapSource image) throws ReaderException {
50     setHints(null);
51     return decodeInternal(image);
52   }
53
54   /**
55    * Decode an image using the hints provided. Does not honor existing state.
56    *
57    * @param image The pixel data to decode
58    * @param hints The hints to use, clearing the previous state.
59    * @return The contents of the image
60    * @throws ReaderException Any errors which occurred
61    */
62   public Result decode(MonochromeBitmapSource image, Hashtable hints) throws ReaderException {
63     setHints(hints);
64     return decodeInternal(image);
65   }
66
67   /**
68    * Decode an image using the state set up by calling setHints() previously. Continuous scan
69    * clients will get a <b>large</b> speed increase by using this instead of decode().
70    *
71    * @param image The pixel data to decode
72    * @return The contents of the image
73    * @throws ReaderException Any errors which occurred
74    */
75   public Result decodeWithState(MonochromeBitmapSource image) throws ReaderException {
76     // Make sure to set up the default state so we don't crash
77     if (readers == null) {
78       setHints(null);
79     }
80     return decodeInternal(image);
81   }
82
83   /**
84    * This method adds state to the MultiFormatReader. By setting the hints once, subsequent calls
85    * to decodeWithState(image) can reuse the same set of readers without reallocating memory. This
86    * is important for performance in continuous scan clients.
87    *
88    * @param hints The set of hints to use for subsequent calls to decode(image)
89    */
90   public void setHints(Hashtable hints) {
91     this.hints = hints;
92
93     boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER);
94     Vector formats = hints == null ? null : (Vector) hints.get(DecodeHintType.POSSIBLE_FORMATS);
95     readers = new Vector();
96     if (formats != null) {
97       boolean addOneDReader =
98           formats.contains(BarcodeFormat.UPC_A) ||
99               formats.contains(BarcodeFormat.UPC_E) ||
100               formats.contains(BarcodeFormat.EAN_13) ||
101               formats.contains(BarcodeFormat.EAN_8) ||
102               formats.contains(BarcodeFormat.CODE_39) ||
103               formats.contains(BarcodeFormat.CODE_128) ||
104               formats.contains(BarcodeFormat.ITF) ||
105               formats.contains(BarcodeFormat.PDF417);
106       // Put 1D readers upfront in "normal" mode
107       if (addOneDReader && !tryHarder) {
108         readers.addElement(new MultiFormatOneDReader(hints));
109       }
110       if (formats.contains(BarcodeFormat.QR_CODE)) {
111         readers.addElement(new QRCodeReader());
112       }
113       if (formats.contains(BarcodeFormat.DATAMATRIX)) {
114         readers.addElement(new DataMatrixReader());
115       }
116       if (formats.contains(BarcodeFormat.PDF417)) {
117          readers.addElement(new PDF417Reader());
118        }
119       // At end in "try harder" mode
120       if (addOneDReader && tryHarder) {
121         readers.addElement(new MultiFormatOneDReader(hints));
122       }
123     }
124     if (readers.isEmpty()) {
125       if (!tryHarder) {
126         readers.addElement(new MultiFormatOneDReader(hints));
127       }
128       readers.addElement(new QRCodeReader());
129       
130       // TODO re-enable once Data Matrix is ready
131       // readers.addElement(new DataMatrixReader());
132       
133       // TODO: Enable once PDF417 has passed QA
134       //readers.addElement(new PDF417Reader());
135       
136       if (tryHarder) {
137         readers.addElement(new MultiFormatOneDReader(hints));
138       }
139     }
140   }
141
142   private Result decodeInternal(MonochromeBitmapSource image) throws ReaderException {
143     int size = readers.size();
144     for (int i = 0; i < size; i++) {
145       Reader reader = (Reader) readers.elementAt(i);
146       try {
147         return reader.decode(image, hints);
148       } catch (ReaderException re) {
149         // continue
150       }
151     }
152
153     throw ReaderException.getInstance();
154   }
155
156 }