"Try harder" mode now tries 2D formats first. BlackPointEstimator more conservative...
authorsrowen <srowen@59b500cc-1b3d-0410-9834-0bbf25fbcc57>
Wed, 19 Mar 2008 18:40:52 +0000 (18:40 +0000)
committersrowen <srowen@59b500cc-1b3d-0410-9834-0bbf25fbcc57>
Wed, 19 Mar 2008 18:40:52 +0000 (18:40 +0000)
git-svn-id: http://zxing.googlecode.com/svn/trunk@300 59b500cc-1b3d-0410-9834-0bbf25fbcc57

core/src/com/google/zxing/DecodeHintType.java
core/src/com/google/zxing/MultiFormatReader.java
core/src/com/google/zxing/common/BlackPointEstimator.java
core/src/com/google/zxing/oned/AbstractOneDReader.java

index 20c30c0..4d48a4a 100644 (file)
@@ -56,6 +56,7 @@ public final class DecodeHintType {
    * Skip the first n barcodes found. Currently applies only to 1D formats. This
    * enables a caller to repeatedly decode and find multiple barcodes. Maps
    * to an {@link Integer}.
+   * @deprecated
    */
   public static final DecodeHintType SKIP_N_BARCODES = new DecodeHintType();
 
index adab2f1..6b2c240 100644 (file)
@@ -38,15 +38,19 @@ public final class MultiFormatReader implements Reader {
 
   public Result decode(MonochromeBitmapSource image, Hashtable hints) throws ReaderException {
 
+    boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER);
     Vector possibleFormats = hints == null ? null : (Vector) hints.get(DecodeHintType.POSSIBLE_FORMATS);
     Vector readers = new Vector();
     if (possibleFormats != null) {
-      if (possibleFormats.contains(BarcodeFormat.UPC_A) ||
+      boolean addOneDReader =
+          possibleFormats.contains(BarcodeFormat.UPC_A) ||
           possibleFormats.contains(BarcodeFormat.UPC_E) ||
           possibleFormats.contains(BarcodeFormat.EAN_13) ||
           possibleFormats.contains(BarcodeFormat.EAN_8) ||
           possibleFormats.contains(BarcodeFormat.CODE_39) ||
-          possibleFormats.contains(BarcodeFormat.CODE_128)) {
+          possibleFormats.contains(BarcodeFormat.CODE_128);
+      // Put 1D readers upfront in "normal" mode
+      if (addOneDReader && !tryHarder) {
         readers.addElement(new MultiFormatOneDReader());
       }
       if (possibleFormats.contains(BarcodeFormat.QR_CODE)) {
@@ -55,12 +59,21 @@ public final class MultiFormatReader implements Reader {
       if (possibleFormats.contains(BarcodeFormat.DATAMATRIX)) {
         readers.addElement(new DataMatrixReader());
       }
+      // At end in "try harder" mode
+      if (addOneDReader && tryHarder) {
+        readers.addElement(new MultiFormatOneDReader());
+      }
     }
     if (readers.isEmpty()) {
-      readers.addElement(new MultiFormatOneDReader());
+      if (!tryHarder) {
+        readers.addElement(new MultiFormatOneDReader());
+      }
       readers.addElement(new QRCodeReader());
       // TODO re-enable once Data Matrix is ready
       // readers.addElement(new DataMatrixReader());
+      if (tryHarder) {
+        readers.addElement(new MultiFormatOneDReader());
+      }
     }
 
     for (int i = 0; i < readers.size(); i++) {
index a9fc793..c3e3738 100644 (file)
@@ -90,8 +90,8 @@ public final class BlackPointEstimator {
     // dynamic range in the image, that discriminating black and white is too error-prone.\r
     // Decoding the image/line is either pointless, or may in some cases lead to a false positive\r
     // for 1D formats, which are relatively lenient.\r
-    // We arbitrarily say "close" is "fewer than 1/8 of the total histogram buckets apart"\r
-    if (secondPeak - firstPeak < histogram.length >> 3) {\r
+    // We arbitrarily say "close" is "<= 1/16 of the total histogram buckets apart"\r
+    if (secondPeak - firstPeak <= histogram.length >> 4) {\r
       throw new ReaderException("Too little dynamic range in luminance");\r
     }\r
 \r
index 53a04a3..66eee2b 100644 (file)
@@ -69,13 +69,13 @@ public abstract class AbstractOneDReader implements OneDReader {
 
     BitArray row = new BitArray(width);
 
-    int barcodesToSkip = 0;
-    if (hints != null) {
-      Integer number = (Integer) hints.get(DecodeHintType.SKIP_N_BARCODES);
-      if (number != null) {
-        barcodesToSkip = number.intValue();
-      }
-    }
+    //int barcodesToSkip = 0;
+    //if (hints != null) {
+    //  Integer number = (Integer) hints.get(DecodeHintType.SKIP_N_BARCODES);
+    //  if (number != null) {
+    //    barcodesToSkip = number.intValue();
+    //  }
+    //}
 
     // We're going to examine rows from the middle outward, searching alternately above and below the middle,
     // and farther out each time. rowStep is the number of rows between each successive attempt above and below
@@ -87,23 +87,27 @@ public abstract class AbstractOneDReader implements OneDReader {
     int middle = height >> 1;
     int rowStep = Math.max(1, height >> (tryHarder ? 7 : 4));
     int maxLines;
-    if (tryHarder || barcodesToSkip > 0) {
+    //if (tryHarder || barcodesToSkip > 0) {
+    if (tryHarder) {
       maxLines = height; // Look at the whole image; looking for more than one barcode
     } else {
       maxLines = 7;
     }
 
-    Result lastResult = null;
+    //Result lastResult = null;
 
     for (int x = 0; x < maxLines; x++) {
 
+      // Scanning from the middle out. Determine which row we're looking at next:
       int rowStepsAboveOrBelow = (x + 1) >> 1;
       boolean isAbove = (x & 0x01) == 0; // i.e. is x even?
       int rowNumber = middle + rowStep * (isAbove ? rowStepsAboveOrBelow : -rowStepsAboveOrBelow);
       if (rowNumber < 0 || rowNumber >= height) {
+        // Oops, if we run off the top or bottom, stop
         break;
       }
 
+      // Estimate black point for this row and load it:
       try {
         image.estimateBlackPoint(BlackPointEstimationMethod.ROW_SAMPLING, rowNumber);
       } catch (ReaderException re) {
@@ -111,7 +115,9 @@ public abstract class AbstractOneDReader implements OneDReader {
       }
       image.getBlackRow(rowNumber, row, 0, width);
 
+      // We may try twice for each row, if "trying harder":
       for (int attempt = 0; attempt < 2; attempt++) {
+
         if (attempt == 1) { // trying again?
           if (tryHarder) { // only if "trying harder"
             row.reverse(); // reverse the row and continue
@@ -119,24 +125,33 @@ public abstract class AbstractOneDReader implements OneDReader {
             break;
           }
         }
+
         try {
+
+          // Look for a barcode
           Result result = decodeRow(rowNumber, row, hints);
-          if (lastResult == null || !lastResult.getText().equals(result.getText())) {
-            // Found new barcode, not just the last one again
-            if (barcodesToSkip > 0) { // See if we should skip and keep looking
-              barcodesToSkip--;
-              lastResult = result; // Remember what we just saw
-            } else {
-              if (attempt == 1) {
-                // Found it, but upside-down:
-                result.putMetadata(ResultMetadataType.ORIENTATION, new Integer(180));
-              }
-              return result;
+
+          //if (lastResult != null && lastResult.getText().equals(result.getText())) {
+            // Just saw the last barcode again, proceed
+            //continue;
+          //}
+
+          //if (barcodesToSkip > 0) { // See if we should skip and keep looking
+          //  barcodesToSkip--;
+          //  lastResult = result; // Remember what we just saw
+          //} else {
+            // We found our barcode
+            if (attempt == 1) {
+              // But it was upside down, so note that
+              result.putMetadata(ResultMetadataType.ORIENTATION, new Integer(180));
             }
-          }
+            return result;
+          //}
+
         } catch (ReaderException re) {
-          // continue
+          // continue -- just couldn't decode this row
         }
+
       }
     }