X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=javame%2Fsrc%2Fcom%2Fgoogle%2Fzxing%2Fclient%2Fj2me%2FLCDUIImageMonochromeBitmapSource.java;h=f123abbb7b746b09042a24187b730ee5ea22571d;hb=2ad6bf1cb08ff6b695443359ff849a0134e6e699;hp=2b7bd10a92f61cf5b44e25c83936e35ff349b535;hpb=8200a7ae095206a8f8919b54a434930a676d73b4;p=zxing.git diff --git a/javame/src/com/google/zxing/client/j2me/LCDUIImageMonochromeBitmapSource.java b/javame/src/com/google/zxing/client/j2me/LCDUIImageMonochromeBitmapSource.java index 2b7bd10a..f123abbb 100644 --- a/javame/src/com/google/zxing/client/j2me/LCDUIImageMonochromeBitmapSource.java +++ b/javame/src/com/google/zxing/client/j2me/LCDUIImageMonochromeBitmapSource.java @@ -16,8 +16,9 @@ package com.google.zxing.client.j2me; -import com.google.zxing.MonochromeBitmapSource; import com.google.zxing.BlackPointEstimationMethod; +import com.google.zxing.MonochromeBitmapSource; +import com.google.zxing.ReaderException; import com.google.zxing.common.BitArray; import com.google.zxing.common.BlackPointEstimator; @@ -25,10 +26,10 @@ import javax.microedition.lcdui.Image; /** *

An implementation based on Java ME's {@link Image} representation.

- * + * * @author Sean Owen (srowen@google.com), Daniel Switkin (dswitkin@google.com) */ -final class LCDUIImageMonochromeBitmapSource implements MonochromeBitmapSource { +public final class LCDUIImageMonochromeBitmapSource implements MonochromeBitmapSource { private final int[] rgbPixels; private final int width; @@ -36,12 +37,12 @@ final class LCDUIImageMonochromeBitmapSource implements MonochromeBitmapSource { private int blackPoint; private BlackPointEstimationMethod lastMethod; private int lastArgument; - + 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; - LCDUIImageMonochromeBitmapSource(final Image image) { + public LCDUIImageMonochromeBitmapSource(Image image) { width = image.getWidth(); height = image.getHeight(); rgbPixels = new int[width * height]; @@ -56,14 +57,35 @@ final class LCDUIImageMonochromeBitmapSource implements MonochromeBitmapSource { } 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(); } - for (int i = 0, offset = y * width + startX; i < getWidth; i++, offset++) { - if (computeRGBLuminance(rgbPixels[offset]) < 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 offset = y * width + startX; + int left = computeRGBLuminance(rgbPixels[offset]); + offset++; + int center = computeRGBLuminance(rgbPixels[offset]); + for (int i = 1; i < getWidth - 1; i++, offset++) { + int right = computeRGBLuminance(rgbPixels[offset + 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, offset = y * width + startX; i < getWidth; i++, offset++) { + if (computeRGBLuminance(rgbPixels[offset]) < blackPoint) { + row.set(i); + } } } return row; @@ -77,7 +99,7 @@ final class LCDUIImageMonochromeBitmapSource implements MonochromeBitmapSource { return width; } - public void estimateBlackPoint(BlackPointEstimationMethod method, int argument) { + public void estimateBlackPoint(BlackPointEstimationMethod method, int argument) throws ReaderException { if (!method.equals(lastMethod) || argument != lastArgument) { int[] histogram = new int[LUMINANCE_BUCKETS]; if (method.equals(BlackPointEstimationMethod.TWO_D_SAMPLING)) { @@ -106,20 +128,36 @@ final class LCDUIImageMonochromeBitmapSource implements MonochromeBitmapSource { return lastMethod; } + public MonochromeBitmapSource rotateCounterClockwise() { + throw new IllegalStateException("Rotate not supported"); + } + + public boolean isRotateSupported() { + return false; + } + /** - * Extracts luminance from a pixel from this source. By default, the source is assumed to use RGB, - * so this implementation computes luminance is a function of a red, green and blue components as - * follows: - * - * Y = 0.299R + 0.587G + 0.114B - * - * where R, G, and B are values in [0,1]. + * An optimized approximation of a more proper conversion from RGB to luminance which + * only uses shifts. See BufferedImageMonochromeBitmapSource for an original version. */ private static int computeRGBLuminance(int pixel) { - // Coefficients add up to 1024 to make the divide into a fast shift - return (306 * ((pixel >> 16) & 0xFF) + - 601 * ((pixel >> 8) & 0xFF) + - 117 * (pixel & 0xFF)) >> 10; + // Instead of multiplying by 306, 601, 117, we multiply by 256, 512, 256, so that + // the multiplies can be implemented as shifts. + // + // Really, it's: + // + // return ((((pixel >> 16) & 0xFF) << 8) + + // (((pixel >> 8) & 0xFF) << 9) + + // (( pixel & 0xFF) << 8)) >> 10; + // + // That is, we're replacing the coefficients in the original with powers of two, + // which can be implemented as shifts, even though changing the coefficients slightly + // corrupts the conversion. Not significant for our purposes. + // + // But we can get even cleverer and eliminate a few shifts: + return (((pixel & 0x00FF0000) >> 16) + + ((pixel & 0x0000FF00) >> 7) + + ( pixel & 0x000000FF )) >> 2; } } \ No newline at end of file