Finished work on the local binarizer and renamed it to HybridBinarizer. It uses the...
[zxing.git] / core / src / com / google / zxing / common / GlobalHistogramBinarizer.java
index 2f3e46a..015dfa9 100644 (file)
@@ -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;
@@ -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);
         }
@@ -138,25 +140,25 @@ public final class GlobalHistogramBinarizer extends Binarizer {
     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;
       }
     }
@@ -179,11 +181,11 @@ public final class GlobalHistogramBinarizer extends Binarizer {
     // 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;
       }
     }