--- /dev/null
+/*
+ * Copyright 2007 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.zxing;
+
+/**
+ * <p>Enumerates different methods of sampling an imagine to estimate a black point.</p>
+ *
+ * @author srowen@google.com (Sean Owen), dswitkin@google.com (Daniel Switkin)
+ */
+public final class BlackPointEstimationMethod {
+
+ /** Method probably most suitable for use with 2D barcdoe format. */
+ public static final BlackPointEstimationMethod TWO_D_SAMPLING = new BlackPointEstimationMethod();
+ /** Method probably most suitable for 1D barcode decoding, where one row at a time is sampled. */
+ public static final BlackPointEstimationMethod ROW_SAMPLING = new BlackPointEstimationMethod();
+
+ private BlackPointEstimationMethod() {
+ // do nothing
+ }
+
+}
\ No newline at end of file
import com.google.zxing.common.BitArray;
/**
- * Encapsulates a generic black-and-white bitmap -- a collection of pixels in two dimensions.
- * This unifies many possible representations, like AWT's <code>BufferedImage</code>.
+ * <p>Encapsulates a generic black-and-white bitmap -- a collection of pixels in two dimensions.
+ * This unifies many possible representations, like AWT's <code>BufferedImage</code>.</p>
*
* @author srowen@google.com (Sean Owen)
*/
boolean isBlack(int x, int y);
/**
- * Returns an entire row of black/white pixels as an array of bits, where "true" means "black".
+ * <p>Returns an entire row of black/white pixels as an array of bits, where "true" means "black".
* This is a sort of "bulk get" operation intended to enable efficient access in
- * certain situations.
+ * certain situations.</p>
*
* @param y vertical offset, from top, of the row of pixels
* @param row if not null, {@link BitArray} to write pixels into. If null, a new {@link BitArray}
*/
int getWidth();
+ /**
+ * <p>Estimates black point according to the given method, which is optionally parameterized by
+ * a single int argument. For {@link BlackPointEstimationMethod#ROW_SAMPLING}, this
+ * specifies the row to sample.</p>
+ *
+ * <p>The estimated value will be used in subsequent computations that rely on an estimated black
+ * point.</p>
+ *
+ * @param method black point estimation method
+ * @param argument method-specific argument
+ */
+ void estimateBlackPoint(BlackPointEstimationMethod method, int argument);
+
+ /**
+ * @return {@link BlackPointEstimationMethod} representing last sampling method used
+ */
+ BlackPointEstimationMethod getLastEstimationMethod();
+
}
package com.google.zxing.qrcode.detector;
+import com.google.zxing.BlackPointEstimationMethod;
import com.google.zxing.MonochromeBitmapSource;
import com.google.zxing.ReaderException;
import com.google.zxing.ResultPoint;
public DetectorResult detect() throws ReaderException {
MonochromeBitmapSource image = this.image;
+ if (!BlackPointEstimationMethod.TWO_D_SAMPLING.equals(image.getLastEstimationMethod())) {
+ image.estimateBlackPoint(BlackPointEstimationMethod.TWO_D_SAMPLING, 0);
+ }
FinderPatternFinder finder = new FinderPatternFinder(image);
FinderPatternInfo info = finder.find();
GridSampler sampler = GridSampler.getInstance();
BitMatrix bits = sampler.sampleGrid(image, topLeft, topRight, bottomLeft, alignmentPattern, dimension);
- /*
- try {
- BufferedImage outImage =
- new BufferedImage(dimension,
- dimension,
- BufferedImage.TYPE_BYTE_BINARY);
- for (int i = 0; i < dimension; i++) {
- for (int j = 0; j < dimension; j++) {
- if (bits.get(i, j)) {
- outImage.setRGB(j, i, 0xFF000000);
- } else {
- outImage.setRGB(j, i, 0xFFFFFFFF);
- }
- }
- }
- ImageIO.write(outImage, "PNG", new File("/tmp/out.png"));
- } catch (IOException ioe) {
- ioe.printStackTrace();
- }
- */
-
ResultPoint[] points;
if (alignmentPattern == null) {
points = new ResultPoint[] { bottomLeft, topLeft, topRight };
package com.google.zxing.client.j2me;
import com.google.zxing.MonochromeBitmapSource;
+import com.google.zxing.BlackPointEstimationMethod;
import com.google.zxing.common.BitArray;
import com.google.zxing.common.BlackPointEstimator;
/**
* <p>An implementation based on Java ME's {@link Image} representation.</p>
*
- * @author Sean Owen (srowen@google.com)
+ * @author Sean Owen (srowen@google.com), Daniel Switkin (dswitkin@google.com)
*/
final class LCDUIImageMonochromeBitmapSource implements MonochromeBitmapSource {
private final int[] rgbPixels;
- private final int blackPoint;
private final int width;
private final int height;
+ private int blackPoint;
+ private BlackPointEstimationMethod lastMethod;
LCDUIImageMonochromeBitmapSource(final Image image) {
- int width = image.getWidth();
- int height = image.getHeight();
- this.width = width;
- this.height = height;
- int[] rgbPixels = new int[width * height];
- this.rgbPixels = rgbPixels;
+ width = image.getWidth();
+ height = image.getHeight();
+ rgbPixels = new int[width * height];
image.getRGB(rgbPixels, 0, width, 0, 0, width, height);
- int[] luminanceBuckets = new int[32];
- int minDimension = width < height ? width : height;
- for (int n = 0, offset = 0; n < minDimension; n++, offset += width + 1) {
- luminanceBuckets[computeRGBLuminance(rgbPixels[offset]) >> 3]++;
- }
- blackPoint = BlackPointEstimator.estimate(luminanceBuckets) << 3;
+ blackPoint = 0x7F;
}
public boolean isBlack(int x, int y) {
return width;
}
+ public void estimateBlackPoint(BlackPointEstimationMethod method, int argument) {
+ if (method.equals(BlackPointEstimationMethod.TWO_D_SAMPLING)) {
+ if (!BlackPointEstimationMethod.TWO_D_SAMPLING.equals(lastMethod)) {
+ int[] luminanceBuckets = new int[32];
+ int minDimension = width < height ? width : height;
+ for (int n = 0, offset = 0; n < minDimension; n++, offset += width + 1) {
+ luminanceBuckets[computeRGBLuminance(rgbPixels[offset]) >> 3]++;
+ }
+ blackPoint = BlackPointEstimator.estimate(luminanceBuckets) << 3;
+ }
+ } else if (method.equals(BlackPointEstimationMethod.ROW_SAMPLING)) {
+ // TODO
+ } else {
+ throw new IllegalArgumentException("Unknown method: " + method);
+ }
+ lastMethod = method;
+ }
+
+ 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
package com.google.zxing.client.j2se;
import com.google.zxing.MonochromeBitmapSource;
+import com.google.zxing.BlackPointEstimationMethod;
import com.google.zxing.common.BitArray;
import com.google.zxing.common.BlackPointEstimator;
* underlying image as if it were a monochrome image. Behind the scenes, it is evaluating
* the luminance of the underlying image by retrieving its pixels' RGB values.</p>
*
- * @author srowen@google.com (Sean Owen)
+ * @author srowen@google.com (Sean Owen), Daniel Switkin (dswitkin@google.com)
*/
public final class BufferedImageMonochromeBitmapSource implements MonochromeBitmapSource {
private final BufferedImage image;
- private final int blackPoint;
+ private int blackPoint;
+ private BlackPointEstimationMethod lastMethod;
public BufferedImageMonochromeBitmapSource(BufferedImage image) {
this.image = image;
- int width = image.getWidth();
- int height = image.getHeight();
- int[] luminanceBuckets = new int[32];
- int minDimension = width < height ? width : height;
- int startI = height == minDimension ? 0 : (height - width) >> 1;
- int startJ = width == minDimension ? 0 : (width - height) >> 1;
- for (int n = 0; n < minDimension; n++) {
- int pixel = image.getRGB(startJ + n, startI + n);
- luminanceBuckets[computeRGBLuminance(pixel) >> 3]++;
- }
- blackPoint = BlackPointEstimator.estimate(luminanceBuckets) << 3;
+ blackPoint = 0x7F;
}
public boolean isBlack(int x, int y) {
return image.getWidth();
}
+ public void estimateBlackPoint(BlackPointEstimationMethod method, int argument) {
+ if (method.equals(BlackPointEstimationMethod.TWO_D_SAMPLING)) {
+ if (!BlackPointEstimationMethod.TWO_D_SAMPLING.equals(lastMethod)) {
+ int width = image.getWidth();
+ int height = image.getHeight();
+ int[] luminanceBuckets = new int[32];
+ int minDimension = width < height ? width : height;
+ int startI = height == minDimension ? 0 : (height - width) >> 1;
+ int startJ = width == minDimension ? 0 : (width - height) >> 1;
+ for (int n = 0; n < minDimension; n++) {
+ int pixel = image.getRGB(startJ + n, startI + n);
+ luminanceBuckets[computeRGBLuminance(pixel) >> 3]++;
+ }
+ blackPoint = BlackPointEstimator.estimate(luminanceBuckets) << 3;
+ }
+ } else if (method.equals(BlackPointEstimationMethod.ROW_SAMPLING)) {
+ // TODO
+ } else {
+ throw new IllegalArgumentException("Unknown method: " + method);
+ }
+ lastMethod = method;
+ }
+
+ 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