Changed the 2D histogram calculation to sample four rows spread across the image...
[zxing.git] / core / src / com / google / zxing / common / BaseMonochromeBitmapSource.java
index 0a99cda..06f0513 100644 (file)
@@ -24,16 +24,12 @@ import com.google.zxing.ReaderException;
  */
 public abstract class BaseMonochromeBitmapSource implements MonochromeBitmapSource {
 
-  private static final int LUMINANCE_BITS = 5;
-  private static final int LUMINANCE_SHIFT = 8 - LUMINANCE_BITS;
-  private static final int LUMINANCE_BUCKETS = 1 << LUMINANCE_BITS;
-
   private final int height;
   private final int width;
   private int blackPoint;
   private BlackPointEstimationMethod lastMethod;
   private int lastArgument;
-  private int[] luminances;
+  private int[] luminances = null;
 
   protected BaseMonochromeBitmapSource(int width, int height) {
     this.height = height;
@@ -63,15 +59,15 @@ public abstract class BaseMonochromeBitmapSource implements MonochromeBitmapSour
 
     // Reuse the same int array each time
     initLuminances();
-    luminances = getLuminanceRow(y, luminances);
+    int[] localLuminances = getLuminanceRow(y, luminances);
 
     // If the current decoder calculated the blackPoint based on one row, assume we're trying to
     // decode a 1D barcode, and apply some sharpening.
     if (lastMethod.equals(BlackPointEstimationMethod.ROW_SAMPLING)) {
-      int left = luminances[startX];
-      int center = luminances[startX + 1];
+      int left = localLuminances[startX];
+      int center = localLuminances[startX + 1];
       for (int x = 1; x < getWidth - 1; x++) {
-        int right = luminances[startX + x + 1];
+        int right = localLuminances[startX + x + 1];
         // Simple -1 4 -1 box filter with a weight of 2
         int luminance = ((center << 2) - left - right) >> 1;
         if (luminance < blackPoint) {
@@ -82,7 +78,7 @@ public abstract class BaseMonochromeBitmapSource implements MonochromeBitmapSour
       }
     } else {
       for (int x = 0; x < getWidth; x++) {
-        if (luminances[startX + x] < blackPoint) {
+        if (localLuminances[startX + x] < blackPoint) {
           row.set(x);
         }
       }
@@ -99,43 +95,21 @@ public abstract class BaseMonochromeBitmapSource implements MonochromeBitmapSour
 
     // Reuse the same int array each time
     initLuminances();
-    luminances = getLuminanceColumn(x, luminances);
+    int[] localLuminances = getLuminanceColumn(x, luminances);
 
     // We don't handle "row sampling" specially here
     for (int y = 0; y < getHeight; y++) {
-      if (luminances[startY + y] < blackPoint) {
+      if (localLuminances[startY + y] < blackPoint) {
         column.set(y);
       }
     }
     return column;
   }
 
-  public void estimateBlackPoint(BlackPointEstimationMethod method, int argument) throws ReaderException {
+  public void estimateBlackPoint(BlackPointEstimationMethod method, int argument)
+      throws ReaderException {
     if (!method.equals(lastMethod) || argument != lastArgument) {
-      int width = getWidth();
-      int height = getHeight();
-      int[] histogram = new int[LUMINANCE_BUCKETS];
-      if (method.equals(BlackPointEstimationMethod.TWO_D_SAMPLING)) {
-        int minDimension = width < height ? width : height;
-        int startX = (width - minDimension) >> 1;
-        int startY = (height - minDimension) >> 1;
-        for (int n = 0; n < minDimension; n++) {
-          int luminance = getLuminance(startX + n, startY + n);
-          histogram[luminance >> LUMINANCE_SHIFT]++;
-        }
-      } else if (method.equals(BlackPointEstimationMethod.ROW_SAMPLING)) {
-        if (argument < 0 || argument >= height) {
-          throw new IllegalArgumentException("Row is not within the image: " + argument);
-        }
-        initLuminances();
-        luminances = getLuminanceRow(argument, luminances);
-        for (int x = 0; x < width; x++) {
-          histogram[luminances[x] >> LUMINANCE_SHIFT]++;
-        }
-      } else {
-        throw new IllegalArgumentException("Unknown method");
-      }
-      blackPoint = BlackPointEstimator.estimate(histogram) << LUMINANCE_SHIFT;
+      blackPoint = BlackPointEstimator.estimate(this, method, argument);
       lastMethod = method;
       lastArgument = argument;
     }
@@ -161,6 +135,20 @@ public abstract class BaseMonochromeBitmapSource implements MonochromeBitmapSour
     return width;
   }
 
+  public String toString() {
+    StringBuffer result = new StringBuffer(height * (width + 1));
+    BitArray row = new BitArray(width);
+    for (int i = 0; i < height; i++) {
+      row = getBlackRow(i, row, 0, width);
+      for (int j = 0; j < width; j++) {
+        result.append(row.get(j) ? "X " : "  ");
+      }
+      result.append('\n');
+    }
+    return result.toString();
+  }
+
+
   // These methods below should not need to exist because they are defined in the interface that
   // this abstract class implements. However this seems to cause problems on some Nokias.
   // So we write these redundant declarations.
@@ -174,7 +162,7 @@ public abstract class BaseMonochromeBitmapSource implements MonochromeBitmapSour
    * @param y The y coordinate in the image.
    * @return The luminance value between 0 and 255.
    */
-  protected abstract int getLuminance(int x, int y);
+  public abstract int getLuminance(int x, int y);
 
   /**
    * This is the main mechanism for retrieving luminance data. It is dramatically more efficient
@@ -187,7 +175,7 @@ public abstract class BaseMonochromeBitmapSource implements MonochromeBitmapSour
    *            but then I will take pity on you and allocate a sufficient array internally.
    * @return The array containing the luminance data. This is the same as row if it was usable.
    */
-  protected abstract int[] getLuminanceRow(int y, int[] row);
+  public abstract int[] getLuminanceRow(int y, int[] row);
 
   /**
    * The same as getLuminanceRow(), but for columns.
@@ -196,6 +184,6 @@ public abstract class BaseMonochromeBitmapSource implements MonochromeBitmapSour
    * @param column The array to write luminance values into. See above.
    * @return The array containing the luminance data.
    */
-  protected abstract int[] getLuminanceColumn(int x, int[] column);
+  public abstract int[] getLuminanceColumn(int x, int[] column);
 
 }