Fix bad logic black point estimator, improving threshold estimation performance ...
[zxing.git] / javase / src / com / google / zxing / client / j2se / BufferedImageMonochromeBitmapSource.java
index bfe97bc..e8396b4 100644 (file)
@@ -53,10 +53,25 @@ public final class BufferedImageMonochromeBitmapSource implements MonochromeBitm
   private static final int LUMINANCE_SHIFT = 8 - LUMINANCE_BITS;
   private static final int LUMINANCE_BUCKETS = 1 << LUMINANCE_BITS;
 
+  /**
+   * Creates an instance that uses the entire given image as a source of pixels to decode.
+   *
+   * @param image image to decode
+   */
   public BufferedImageMonochromeBitmapSource(BufferedImage image) {
     this(image, 0, 0, image.getWidth(), image.getHeight());
   }
 
+  /**
+   * Creates an instance that uses only a region of the given image as a source of pixels to decode.
+   *
+   * @param image image to decode a region of
+   * @param left x coordinate of leftmost pixels to decode
+   * @param top y coordinate of topmost pixels to decode
+   * @param right one more than the x coordinate of rightmost pixels to decode. That is, we will decode
+   *  pixels whose x coordinate is in [left,right)
+   * @param bottom likewise, one more than the y coordinate of the bottommost pixels to decode
+   */
   public BufferedImageMonochromeBitmapSource(BufferedImage image, int left, int top, int right, int bottom) {
     this.image = image;
     blackPoint = 0x7F;
@@ -64,7 +79,7 @@ public final class BufferedImageMonochromeBitmapSource implements MonochromeBitm
     lastArgument = 0;
     int sourceHeight = image.getHeight();
     int sourceWidth = image.getWidth();
-    if (left < 0 || top < 0 || right >= sourceWidth || bottom >= sourceHeight || right <= left || bottom <= top) {
+    if (left < 0 || top < 0 || right > sourceWidth || bottom > sourceHeight || right <= left || bottom <= top) {
       throw new IllegalArgumentException("Invalid bounds: (" + top + ',' + left + ") (" + right + ',' + bottom + ')');
     }
     this.left = left;
@@ -94,16 +109,35 @@ public final class BufferedImageMonochromeBitmapSource implements MonochromeBitm
   }
 
   public BitArray getBlackRow(int y, BitArray row, int startX, int getWidth) {
-    if (row == null) {
+    if (row == null || row.getSize() < getWidth) {
       row = new BitArray(getWidth);
     } else {
       row.clear();
     }
     int[] pixelRow = new int[getWidth];
     getRGBRow(startX, y, pixelRow);
-    for (int i = 0; i < getWidth; i++) {
-      if (computeRGBLuminance(pixelRow[i]) < blackPoint) {
-        row.set(i);
+
+    // If the current decoder calculated the blackPoint based on one row, assume we're trying to
+    // decode a 1D barcode, and apply some sharpening.
+    // TODO: We may want to add a fifth parameter to request the amount of shapening to be done.
+    if (lastMethod.equals(BlackPointEstimationMethod.ROW_SAMPLING)) {
+      int left = computeRGBLuminance(pixelRow[0]);
+      int center = computeRGBLuminance(pixelRow[1]);
+      for (int i = 1; i < getWidth - 1; i++) {
+        int right = computeRGBLuminance(pixelRow[i + 1]);
+        // Simple -1 4 -1 box filter with a weight of 2
+        int luminance = ((center << 2) - left - right) >> 1;
+        if (luminance < blackPoint) {
+          row.set(i);
+        }
+        left = center;
+        center = right;
+      }
+    } else {
+      for (int i = 0; i < getWidth; i++) {
+        if (computeRGBLuminance(pixelRow[i]) < blackPoint) {
+          row.set(i);
+        }
       }
     }
     return row;