Improved approach to 1D decoding -- better use of integer math by scaling pattern...
[zxing.git] / core / src / com / google / zxing / oned / Code128Reader.java
index 7dfb953..8b027bb 100644 (file)
 
 package com.google.zxing.oned;
 
+import com.google.zxing.BarcodeFormat;
 import com.google.zxing.ReaderException;
 import com.google.zxing.Result;
 import com.google.zxing.ResultPoint;
 import com.google.zxing.common.BitArray;
 import com.google.zxing.common.GenericResultPoint;
 
+import java.util.Hashtable;
+
 /**
  * <p>Decodes Code 128 barcodes.</p>
  *
@@ -139,7 +142,8 @@ public final class Code128Reader extends AbstractOneDReader {
       {2, 3, 3, 1, 1, 1, 2}
   };
 
-  private static final float MAX_VARIANCE = 0.3f;
+  private static final int MAX_AVG_VARIANCE = (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.1875f);
+  private static final int MAX_INDIVIDUAL_VARIANCE = (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.25f);
 
   private static final int CODE_SHIFT = 98;
 
@@ -180,10 +184,10 @@ public final class Code128Reader extends AbstractOneDReader {
         counters[counterPosition]++;
       } else {
         if (counterPosition == patternLength - 1) {
-          float bestVariance = MAX_VARIANCE;
+          int bestVariance = MAX_AVG_VARIANCE;
           int bestMatch = -1;
           for (int startCode = CODE_START_A; startCode <= CODE_START_C; startCode++) {
-            float variance = patternMatchVariance(counters, CODE_PATTERNS[startCode]);
+            int variance = patternMatchVariance(counters, CODE_PATTERNS[startCode], MAX_INDIVIDUAL_VARIANCE);
             if (variance < bestVariance) {
               bestVariance = variance;
               bestMatch = startCode;
@@ -196,6 +200,8 @@ public final class Code128Reader extends AbstractOneDReader {
           for (int y = 2; y < patternLength; y++) {
             counters[y - 2] = counters[y];
           }
+          counters[patternLength - 2] = 0;
+          counters[patternLength - 1] = 0;
           counterPosition--;
         } else {
           counterPosition++;
@@ -209,11 +215,11 @@ public final class Code128Reader extends AbstractOneDReader {
 
   private static int decodeCode(BitArray row, int[] counters, int rowOffset) throws ReaderException {
     recordPattern(row, rowOffset, counters);
-    float bestVariance = MAX_VARIANCE; // worst variance we'll accept
+    int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept
     int bestMatch = -1;
     for (int d = 0; d < CODE_PATTERNS.length; d++) {
       int[] pattern = CODE_PATTERNS[d];
-      float variance = patternMatchVariance(counters, pattern);
+      int variance = patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE);
       if (variance < bestVariance) {
         bestVariance = variance;
         bestMatch = d;
@@ -227,7 +233,7 @@ public final class Code128Reader extends AbstractOneDReader {
     }
   }
 
-  public Result decodeRow(final int rowNumber, final BitArray row) throws ReaderException {
+  public Result decodeRow(int rowNumber, BitArray row, Hashtable hints) throws ReaderException {
 
     int[] startPatternInfo = findStartPattern(row);
     int startCode = startPatternInfo[2];
@@ -400,11 +406,21 @@ public final class Code128Reader extends AbstractOneDReader {
     }
 
     String resultString = result.toString();
-    return new Result(resultString,
-        new ResultPoint[]{new GenericResultPoint((float) (startPatternInfo[1] - startPatternInfo[0]) / 2.0f,
-            (float) rowNumber),
-            new GenericResultPoint((float) (nextStart - lastStart) / 2.0f,
-                (float) rowNumber)});
+
+    if (resultString.length() == 0) {
+      // Almost surely a false positive
+      throw new ReaderException("Empty barcode found; assuming a false positive");
+    }
+
+    float left = (float) (startPatternInfo[1] + startPatternInfo[0]) / 2.0f;
+    float right = (float) (nextStart + lastStart) / 2.0f;
+    return new Result(
+        resultString,
+        null,
+        new ResultPoint[]{
+            new GenericResultPoint(left, (float) rowNumber),
+            new GenericResultPoint(right, (float) rowNumber)},
+        BarcodeFormat.CODE_128);
 
   }