Issue 508
[zxing.git] / core / src / com / google / zxing / common / GlobalHistogramBinarizer.java
index 2f3e46a..144c099 100644 (file)
@@ -18,7 +18,7 @@ package com.google.zxing.common;
 
 import com.google.zxing.Binarizer;
 import com.google.zxing.LuminanceSource;
-import com.google.zxing.ReaderException;
+import com.google.zxing.NotFoundException;
 
 /**
  * This Binarizer implementation uses the old ZXing global histogram approach. It is suitable
@@ -26,10 +26,12 @@ import com.google.zxing.ReaderException;
  * algorithm. However, because it picks a global black point, it cannot handle difficult shadows
  * and gradients.
  *
+ * Faster mobile devices and all desktop applications should probably use HybridBinarizer instead.
+ *
  * @author dswitkin@google.com (Daniel Switkin)
  * @author Sean Owen
  */
-public final class GlobalHistogramBinarizer extends Binarizer {
+public class GlobalHistogramBinarizer extends Binarizer {
 
   private static final int LUMINANCE_BITS = 5;
   private static final int LUMINANCE_SHIFT = 8 - LUMINANCE_BITS;
@@ -43,7 +45,7 @@ public final class GlobalHistogramBinarizer extends Binarizer {
   }
 
   // Applies simple sharpening to the row data to improve performance of the 1D Readers.
-  public BitArray getBlackRow(int y, BitArray row) throws ReaderException {
+  public BitArray getBlackRow(int y, BitArray row) throws NotFoundException {
     LuminanceSource source = getLuminanceSource();
     int width = source.getWidth();
     if (row == null || row.getSize() < width) {
@@ -77,7 +79,7 @@ public final class GlobalHistogramBinarizer extends Binarizer {
   }
 
   // Does not sharpen the data, as this call is intended to only be used by 2D Readers.
-  public BitMatrix getBlackMatrix() throws ReaderException {
+  public BitMatrix getBlackMatrix() throws NotFoundException {
     LuminanceSource source = getLuminanceSource();
     int width = source.getWidth();
     int height = source.getHeight();
@@ -90,7 +92,7 @@ public final class GlobalHistogramBinarizer extends Binarizer {
     for (int y = 1; y < 5; y++) {
       int row = height * y / 5;
       byte[] localLuminances = source.getRow(row, luminances);
-      int right = width * 4 / 5;
+      int right = (width << 2) / 5;
       for (int x = width / 5; x < right; x++) {
         int pixel = localLuminances[x] & 0xff;
         localBuckets[pixel >> LUMINANCE_SHIFT]++;
@@ -105,7 +107,7 @@ public final class GlobalHistogramBinarizer extends Binarizer {
     for (int y = 0; y < height; y++) {
       int offset = y * width;
       for (int x = 0; x< width; x++) {
-        int pixel = localLuminances[offset + x] & 0xff; 
+        int pixel = localLuminances[offset + x] & 0xff;
         if (pixel < blackPoint) {
           matrix.set(x, y);
         }
@@ -132,31 +134,31 @@ public final class GlobalHistogramBinarizer extends Binarizer {
     }
   }
 
-  private static int estimateBlackPoint(int[] buckets) throws ReaderException {
+  private static int estimateBlackPoint(int[] buckets) throws NotFoundException {
     // Find the tallest peak in the histogram.
     int numBuckets = buckets.length;
     int maxBucketCount = 0;
     int firstPeak = 0;
     int firstPeakSize = 0;
-    for (int i = 0; i < numBuckets; i++) {
-      if (buckets[i] > firstPeakSize) {
-        firstPeak = i;
-        firstPeakSize = buckets[i];
+    for (int x = 0; x < numBuckets; x++) {
+      if (buckets[x] > firstPeakSize) {
+        firstPeak = x;
+        firstPeakSize = buckets[x];
       }
-      if (buckets[i] > maxBucketCount) {
-        maxBucketCount = buckets[i];
+      if (buckets[x] > maxBucketCount) {
+        maxBucketCount = buckets[x];
       }
     }
 
     // Find the second-tallest peak which is somewhat far from the tallest peak.
     int secondPeak = 0;
     int secondPeakScore = 0;
-    for (int i = 0; i < numBuckets; i++) {
-      int distanceToBiggest = i - firstPeak;
+    for (int x = 0; x < numBuckets; x++) {
+      int distanceToBiggest = x - firstPeak;
       // Encourage more distant second peaks by multiplying by square of distance.
-      int score = buckets[i] * distanceToBiggest * distanceToBiggest;
+      int score = buckets[x] * distanceToBiggest * distanceToBiggest;
       if (score > secondPeakScore) {
-        secondPeak = i;
+        secondPeak = x;
         secondPeakScore = score;
       }
     }
@@ -173,17 +175,17 @@ public final class GlobalHistogramBinarizer extends Binarizer {
     // TODO: It might be worth comparing the brightest and darkest pixels seen, rather than the
     // two peaks, to determine the contrast.
     if (secondPeak - firstPeak <= numBuckets >> 4) {
-      throw ReaderException.getInstance();
+      throw NotFoundException.getNotFoundInstance();
     }
 
     // Find a valley between them that is low and closer to the white peak.
     int bestValley = secondPeak - 1;
     int bestValleyScore = -1;
-    for (int i = secondPeak - 1; i > firstPeak; i--) {
-      int fromFirst = i - firstPeak;
-      int score = fromFirst * fromFirst * (secondPeak - i) * (maxBucketCount - buckets[i]);
+    for (int x = secondPeak - 1; x > firstPeak; x--) {
+      int fromFirst = x - firstPeak;
+      int score = fromFirst * fromFirst * (secondPeak - x) * (maxBucketCount - buckets[x]);
       if (score > bestValleyScore) {
-        bestValley = i;
+        bestValley = x;
         bestValleyScore = score;
       }
     }