X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=javame%2Fsrc%2Fcom%2Fgoogle%2Fzxing%2Fclient%2Fj2me%2FLCDUIImageMonochromeBitmapSource.java;h=b65b715939974329f069627251ad0a76f92b5dbc;hb=7eec24ee881d16e10dac4228adb5aa199eec0b29;hp=643097173f9d19f1436bf18a59befe4b8a3ba9f0;hpb=324c4749d7fc3e6823d48921ef3e7ae81ca9cd0f;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 64309717..b65b7159 100644 --- a/javame/src/com/google/zxing/client/j2me/LCDUIImageMonochromeBitmapSource.java +++ b/javame/src/com/google/zxing/client/j2me/LCDUIImageMonochromeBitmapSource.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 Google Inc. + * Copyright 2007 ZXing authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,112 +16,86 @@ package com.google.zxing.client.j2me; -import com.google.zxing.BlackPointEstimationMethod; -import com.google.zxing.MonochromeBitmapSource; -import com.google.zxing.common.BitArray; -import com.google.zxing.common.BlackPointEstimator; +import com.google.zxing.common.BaseMonochromeBitmapSource; 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) + * @author Sean Owen + * @author Daniel Switkin (dswitkin@google.com) */ -public final class LCDUIImageMonochromeBitmapSource implements MonochromeBitmapSource { +public final class LCDUIImageMonochromeBitmapSource extends BaseMonochromeBitmapSource { - private final int[] rgbPixels; - private final int width; - private final int height; - 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; + private final Image image; + private final int[] pixelHolder; public LCDUIImageMonochromeBitmapSource(Image image) { - width = image.getWidth(); - height = image.getHeight(); - rgbPixels = new int[width * height]; - image.getRGB(rgbPixels, 0, width, 0, 0, width, height); - blackPoint = 0x7F; - lastMethod = null; - lastArgument = 0; + super(image.getWidth(), image.getHeight()); + this.image = image; + pixelHolder = new int[1]; } - public boolean isBlack(int x, int y) { - return computeRGBLuminance(rgbPixels[x + y * width]) < blackPoint; + public final int getHeight() { + return image.getHeight(); } - public BitArray getBlackRow(int y, BitArray row, int startX, int getWidth) { - if (row == null) { - 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); - } - } - return row; + public final int getWidth() { + return image.getWidth(); } - public int getHeight() { - return height; - } + // This is expensive and should be used very sparingly. + protected int getLuminance(int x, int y) { + image.getRGB(pixelHolder, 0, getWidth(), x, y, 1, 1); + int pixel = pixelHolder[0]; - public int getWidth() { - return width; + // 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. + return (((pixel & 0x00FF0000) >> 16) + + ((pixel & 0x0000FF00) >> 7) + + (pixel & 0x000000FF )) >> 2; } - public void estimateBlackPoint(BlackPointEstimationMethod method, int argument) { - if (!method.equals(lastMethod) || argument != lastArgument) { - int[] histogram = new int[LUMINANCE_BUCKETS]; - float biasTowardsWhite = 1.0f; - if (method.equals(BlackPointEstimationMethod.TWO_D_SAMPLING)) { - int minDimension = width < height ? width : height; - for (int n = 0, offset = 0; n < minDimension; n++, offset += width + 1) { - histogram[computeRGBLuminance(rgbPixels[offset]) >> LUMINANCE_SHIFT]++; - } - } else if (method.equals(BlackPointEstimationMethod.ROW_SAMPLING)) { - if (argument < 0 || argument >= height) { - throw new IllegalArgumentException("Row is not within the image: " + argument); - } - biasTowardsWhite = 2.0f; - int offset = argument * width; - for (int x = 0; x < width; x++) { - histogram[computeRGBLuminance(rgbPixels[offset + x]) >> LUMINANCE_SHIFT]++; - } - } else { - throw new IllegalArgumentException("Unknown method: " + method); - } - blackPoint = BlackPointEstimator.estimate(histogram, biasTowardsWhite) << LUMINANCE_SHIFT; - lastMethod = method; - lastArgument = argument; + // For efficiency, the RGB data and the luminance data share the same array. + protected int[] getLuminanceRow(int y, int[] row) { + int width = getWidth(); + if (row == null || row.length < width) { + row = new int[width]; } + image.getRGB(row, 0, width, 0, y, width, 1); + for (int x = 0; x < width; x++) { + int pixel = row[x]; + row[x] = (((pixel & 0x00FF0000) >> 16) + + ((pixel & 0x0000FF00) >> 7) + + (pixel & 0x000000FF )) >> 2; + } + return row; } - public BlackPointEstimationMethod getLastEstimationMethod() { - return lastMethod; - } - - /** - * 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]. - */ - 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; + protected int[] getLuminanceColumn(int x, int[] column) { + int height = getHeight(); + if (column == null || column.length < height) { + column = new int[height]; + } + image.getRGB(column, 0, 1, x, 0, 1, height); + for (int y = 0; y < height; y++) { + int pixel = column[y]; + column[y] = (((pixel & 0x00FF0000) >> 16) + + ((pixel & 0x0000FF00) >> 7) + + (pixel & 0x000000FF )) >> 2; + } + return column; } -} \ No newline at end of file +}