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;
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;
}
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;