Improved approach to 1D decoding -- better use of integer math by scaling pattern...
[zxing.git] / core / src / com / google / zxing / oned / AbstractOneDReader.java
index d642547..86f0a7b 100644 (file)
@@ -36,6 +36,7 @@ import java.util.Hashtable;
 public abstract class AbstractOneDReader implements OneDReader {
 
   private static final int INTEGER_MATH_SHIFT = 8;
+  public static final int PATTERN_MATCH_RESULT_SCALE_FACTOR = 256;
 
   public final Result decode(MonochromeBitmapSource image) throws ReaderException {
     return decode(image, null);
@@ -183,12 +184,13 @@ public abstract class AbstractOneDReader implements OneDReader {
    *
    * @param counters observed counters
    * @param pattern expected pattern
+   * @param maxIndividualVariance
    * @return ratio of total variance between counters and pattern compared to total pattern size,
    *  where the ratio has been multiplied by 256. So, 0 means no variance (perfect match); 256 means
    *  the total variance between counters and patterns equals the pattern length, higher values mean
    *  even more variance
    */
-  static int patternMatchVariance(int[] counters, int[] pattern) {
+  static int patternMatchVariance(int[] counters, int[] pattern, int maxIndividualVariance) {
     int numCounters = counters.length;
     int total = 0;
     int patternLength = 0;
@@ -204,16 +206,20 @@ public abstract class AbstractOneDReader implements OneDReader {
     // We're going to fake floating-point math in integers. We just need to use more bits.
     // Scale up patternLength so that intermediate values below like scaledCounter will have
     // more "significant digits"
-    patternLength <<= INTEGER_MATH_SHIFT;
-    int patternRatio = patternLength / total;
+    int unitBarWidth = (total << INTEGER_MATH_SHIFT) / patternLength;
+    maxIndividualVariance *= unitBarWidth;
 
     int totalVariance = 0;
     for (int x = 0; x < numCounters; x++) {
-      int scaledCounter = counters[x] * patternRatio;
-      int width = pattern[x] << INTEGER_MATH_SHIFT;
-      totalVariance += scaledCounter > width ? scaledCounter - width : width - scaledCounter;
+      int counter = counters[x] << INTEGER_MATH_SHIFT;
+      int scaledPattern = pattern[x] * unitBarWidth;
+      int variance = counter > scaledPattern ? counter - scaledPattern : scaledPattern - counter;
+      if (variance > maxIndividualVariance) {
+        return Integer.MAX_VALUE;
+      }
+      totalVariance += variance; 
     }
-    return (totalVariance << 8) / patternLength;
+    return totalVariance / total;
   }
 
   // This declaration should not be necessary, since this class is