Remove use of BinaryBitmap in QR Code, DM

git-svn-id: https://zxing.googlecode.com/svn/trunk@999 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
srowen 2009-06-26 19:22:48 +00:00
parent ce1badea71
commit 550511d760
13 changed files with 86 additions and 111 deletions

View file

@ -138,13 +138,13 @@ public final class BitMatrix {
* @return The resulting BitArray - this reference should always be used even when passing * @return The resulting BitArray - this reference should always be used even when passing
* your own row * your own row
*/ */
BitArray getRow(int y, BitArray row) { public BitArray getRow(int y, BitArray row) {
if (row == null || row.getSize() < width) { if (row == null || row.getSize() < width) {
row = new BitArray(width); row = new BitArray(width);
} }
int offset = y * rowSize; int offset = y * rowSize;
for (int x = 0; x < rowSize; x++) { for (int x = 0; x < rowSize; x++) {
row.setBulk(x * 32, bits[offset + x]); row.setBulk(x << 5, bits[offset + x]);
} }
return row; return row;
} }

View file

@ -17,14 +17,13 @@
package com.google.zxing.common; package com.google.zxing.common;
import com.google.zxing.ReaderException; import com.google.zxing.ReaderException;
import com.google.zxing.BinaryBitmap;
/** /**
* @author Sean Owen * @author Sean Owen
*/ */
public final class DefaultGridSampler extends GridSampler { public final class DefaultGridSampler extends GridSampler {
public BitMatrix sampleGrid(BinaryBitmap image, public BitMatrix sampleGrid(BitMatrix image,
int dimension, int dimension,
float p1ToX, float p1ToY, float p1ToX, float p1ToY,
float p2ToX, float p2ToY, float p2ToX, float p2ToY,
@ -50,11 +49,11 @@ public final class DefaultGridSampler extends GridSampler {
} }
transform.transformPoints(points); transform.transformPoints(points);
// Quick check to see if points transformed to something inside the image; // Quick check to see if points transformed to something inside the image;
// sufficent to check the endpoints // sufficient to check the endpoints
checkAndNudgePoints(image, points); checkAndNudgePoints(image, points);
try { try {
for (int j = 0; j < max; j += 2) { for (int j = 0; j < max; j += 2) {
if (image.isBlack((int) points[j], (int) points[j + 1])) { if (image.get((int) points[j], (int) points[j + 1])) {
// Black(-ish) pixel // Black(-ish) pixel
bits.set(j >> 1, i); bits.set(j >> 1, i);
} }

View file

@ -16,7 +16,6 @@
package com.google.zxing.common; package com.google.zxing.common;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.ReaderException; import com.google.zxing.ReaderException;
/** /**
@ -82,7 +81,7 @@ public abstract class GridSampler {
* @throws ReaderException if image can't be sampled, for example, if the transformation defined * @throws ReaderException if image can't be sampled, for example, if the transformation defined
* by the given points is invalid or results in sampling outside the image boundaries * by the given points is invalid or results in sampling outside the image boundaries
*/ */
public abstract BitMatrix sampleGrid(BinaryBitmap image, public abstract BitMatrix sampleGrid(BitMatrix image,
int dimension, int dimension,
float p1ToX, float p1ToY, float p1ToX, float p1ToY,
float p2ToX, float p2ToY, float p2ToX, float p2ToY,
@ -108,7 +107,7 @@ public abstract class GridSampler {
* @param points actual points in x1,y1,...,xn,yn form * @param points actual points in x1,y1,...,xn,yn form
* @throws ReaderException if an endpoint is lies outside the image boundaries * @throws ReaderException if an endpoint is lies outside the image boundaries
*/ */
protected static void checkAndNudgePoints(BinaryBitmap image, float[] points) protected static void checkAndNudgePoints(BitMatrix image, float[] points)
throws ReaderException { throws ReaderException {
int width = image.getWidth(); int width = image.getWidth();
int height = image.getHeight(); int height = image.getHeight();

View file

@ -16,10 +16,10 @@
package com.google.zxing.common.detector; package com.google.zxing.common.detector;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.ReaderException; import com.google.zxing.ReaderException;
import com.google.zxing.ResultPoint; import com.google.zxing.ResultPoint;
import com.google.zxing.common.BitArray; import com.google.zxing.common.BitArray;
import com.google.zxing.common.BitMatrix;
/** /**
* <p>A somewhat generic detector that looks for a barcode-like rectangular region within an image. * <p>A somewhat generic detector that looks for a barcode-like rectangular region within an image.
@ -32,9 +32,9 @@ public final class MonochromeRectangleDetector {
private static final int MAX_MODULES = 32; private static final int MAX_MODULES = 32;
private final BinaryBitmap image; private final BitMatrix image;
public MonochromeRectangleDetector(BinaryBitmap image) { public MonochromeRectangleDetector(BitMatrix image) {
this.image = image; this.image = image;
} }
@ -160,24 +160,20 @@ public final class MonochromeRectangleDetector {
* (e.g. only white was found) * (e.g. only white was found)
*/ */
private int[] blackWhiteRange(int fixedDimension, int maxWhiteRun, int minDim, int maxDim, private int[] blackWhiteRange(int fixedDimension, int maxWhiteRun, int minDim, int maxDim,
boolean horizontal) throws ReaderException { boolean horizontal) {
int center = (minDim + maxDim) >> 1; int center = (minDim + maxDim) >> 1;
BitArray rowOrColumn = horizontal ?
image.getBlackRow(fixedDimension, null, 0, image.getWidth()) :
image.getBlackColumn(fixedDimension, null, 0, image.getHeight());
// Scan left/up first // Scan left/up first
int start = center; int start = center;
while (start >= minDim) { while (start >= minDim) {
if (rowOrColumn.get(start)) { if (horizontal ? image.get(start, fixedDimension) : image.get(fixedDimension, start)) {
start--; start--;
} else { } else {
int whiteRunStart = start; int whiteRunStart = start;
do { do {
start--; start--;
} while (start >= minDim && !rowOrColumn.get(start)); } while (start >= minDim && !(horizontal ? image.get(start, fixedDimension) : image.get(fixedDimension, start)));
int whiteRunSize = whiteRunStart - start; int whiteRunSize = whiteRunStart - start;
if (start < minDim || whiteRunSize > maxWhiteRun) { if (start < minDim || whiteRunSize > maxWhiteRun) {
start = whiteRunStart; start = whiteRunStart;
@ -190,13 +186,13 @@ public final class MonochromeRectangleDetector {
// Then try right/down // Then try right/down
int end = center; int end = center;
while (end < maxDim) { while (end < maxDim) {
if (rowOrColumn.get(end)) { if (horizontal ? image.get(end, fixedDimension) : image.get(fixedDimension, end)) {
end++; end++;
} else { } else {
int whiteRunStart = end; int whiteRunStart = end;
do { do {
end++; end++;
} while (end < maxDim && !rowOrColumn.get(end)); } while (end < maxDim && !(horizontal ? image.get(end, fixedDimension) : image.get(fixedDimension, end)));
int whiteRunSize = end - whiteRunStart; int whiteRunSize = end - whiteRunStart;
if (end >= maxDim || whiteRunSize > maxWhiteRun) { if (end >= maxDim || whiteRunSize > maxWhiteRun) {
end = whiteRunStart; end = whiteRunStart;

View file

@ -24,7 +24,6 @@ import com.google.zxing.ReaderException;
import com.google.zxing.Result; import com.google.zxing.Result;
import com.google.zxing.ResultPoint; import com.google.zxing.ResultPoint;
import com.google.zxing.ResultMetadataType; import com.google.zxing.ResultMetadataType;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.common.BitMatrix; import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.DecoderResult; import com.google.zxing.common.DecoderResult;
import com.google.zxing.common.DetectorResult; import com.google.zxing.common.DetectorResult;
@ -59,11 +58,11 @@ public final class DataMatrixReader implements Reader {
DecoderResult decoderResult; DecoderResult decoderResult;
ResultPoint[] points; ResultPoint[] points;
if (hints != null && hints.containsKey(DecodeHintType.PURE_BARCODE)) { if (hints != null && hints.containsKey(DecodeHintType.PURE_BARCODE)) {
BitMatrix bits = extractPureBits(image); BitMatrix bits = extractPureBits(image.getBlackMatrix());
decoderResult = decoder.decode(bits); decoderResult = decoder.decode(bits);
points = NO_POINTS; points = NO_POINTS;
} else { } else {
DetectorResult detectorResult = new Detector(image).detect(); DetectorResult detectorResult = new Detector(image.getBlackMatrix()).detect();
decoderResult = decoder.decode(detectorResult.getBits()); decoderResult = decoder.decode(detectorResult.getBits());
points = detectorResult.getPoints(); points = detectorResult.getPoints();
} }
@ -80,7 +79,7 @@ public final class DataMatrixReader implements Reader {
* around it. This is a specialized method that works exceptionally fast in this special * around it. This is a specialized method that works exceptionally fast in this special
* case. * case.
*/ */
private static BitMatrix extractPureBits(BinaryBitmap image) throws ReaderException { private static BitMatrix extractPureBits(BitMatrix image) throws ReaderException {
// Now need to determine module size in pixels // Now need to determine module size in pixels
int height = image.getHeight(); int height = image.getHeight();
@ -89,7 +88,7 @@ public final class DataMatrixReader implements Reader {
// First, skip white border by tracking diagonally from the top left down and to the right: // First, skip white border by tracking diagonally from the top left down and to the right:
int borderWidth = 0; int borderWidth = 0;
while (borderWidth < minDimension && !image.isBlack(borderWidth, borderWidth)) { while (borderWidth < minDimension && !image.get(borderWidth, borderWidth)) {
borderWidth++; borderWidth++;
} }
if (borderWidth == minDimension) { if (borderWidth == minDimension) {
@ -98,7 +97,7 @@ public final class DataMatrixReader implements Reader {
// And then keep tracking across the top-left black module to determine module size // And then keep tracking across the top-left black module to determine module size
int moduleEnd = borderWidth + 1; int moduleEnd = borderWidth + 1;
while (moduleEnd < width && image.isBlack(moduleEnd, borderWidth)) { while (moduleEnd < width && image.get(moduleEnd, borderWidth)) {
moduleEnd++; moduleEnd++;
} }
if (moduleEnd == width) { if (moduleEnd == width) {
@ -109,7 +108,7 @@ public final class DataMatrixReader implements Reader {
// And now find where the bottommost black module on the first column ends // And now find where the bottommost black module on the first column ends
int columnEndOfSymbol = height - 1; int columnEndOfSymbol = height - 1;
while (columnEndOfSymbol >= 0 && !image.isBlack(borderWidth, columnEndOfSymbol)) { while (columnEndOfSymbol >= 0 && !image.get(borderWidth, columnEndOfSymbol)) {
columnEndOfSymbol--; columnEndOfSymbol--;
} }
if (columnEndOfSymbol < 0) { if (columnEndOfSymbol < 0) {
@ -138,7 +137,7 @@ public final class DataMatrixReader implements Reader {
for (int i = 0; i < dimension; i++) { for (int i = 0; i < dimension; i++) {
int iOffset = borderWidth + i * moduleSize; int iOffset = borderWidth + i * moduleSize;
for (int j = 0; j < dimension; j++) { for (int j = 0; j < dimension; j++) {
if (image.isBlack(borderWidth + j * moduleSize, iOffset)) { if (image.get(borderWidth + j * moduleSize, iOffset)) {
bits.set(j, i); bits.set(j, i);
} }
} }

View file

@ -16,10 +16,8 @@
package com.google.zxing.datamatrix.detector; package com.google.zxing.datamatrix.detector;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.ReaderException; import com.google.zxing.ReaderException;
import com.google.zxing.ResultPoint; import com.google.zxing.ResultPoint;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.common.BitMatrix; import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.Collections; import com.google.zxing.common.Collections;
import com.google.zxing.common.Comparator; import com.google.zxing.common.Comparator;
@ -46,10 +44,10 @@ public final class Detector {
private static final Integer[] INTEGERS = private static final Integer[] INTEGERS =
{ new Integer(0), new Integer(1), new Integer(2), new Integer(3), new Integer(4) }; { new Integer(0), new Integer(1), new Integer(2), new Integer(3), new Integer(4) };
private final BinaryBitmap image; private final BitMatrix image;
private final MonochromeRectangleDetector rectangleDetector; private final MonochromeRectangleDetector rectangleDetector;
public Detector(BinaryBitmap image) { public Detector(BitMatrix image) {
this.image = image; this.image = image;
rectangleDetector = new MonochromeRectangleDetector(image); rectangleDetector = new MonochromeRectangleDetector(image);
} }
@ -166,7 +164,7 @@ public final class Detector {
table.put(key, value == null ? INTEGERS[1] : INTEGERS[value.intValue() + 1]); table.put(key, value == null ? INTEGERS[1] : INTEGERS[value.intValue() + 1]);
} }
private static BitMatrix sampleGrid(BinaryBitmap image, private static BitMatrix sampleGrid(BitMatrix image,
ResultPoint topLeft, ResultPoint topLeft,
ResultPoint bottomLeft, ResultPoint bottomLeft,
ResultPoint bottomRight, ResultPoint bottomRight,
@ -228,9 +226,9 @@ public final class Detector {
int ystep = fromY < toY ? 1 : -1; int ystep = fromY < toY ? 1 : -1;
int xstep = fromX < toX ? 1 : -1; int xstep = fromX < toX ? 1 : -1;
int transitions = 0; int transitions = 0;
boolean inBlack = image.isBlack(steep ? fromY : fromX, steep ? fromX : fromY); boolean inBlack = image.get(steep ? fromY : fromX, steep ? fromX : fromY);
for (int x = fromX, y = fromY; x != toX; x += xstep) { for (int x = fromX, y = fromY; x != toX; x += xstep) {
boolean isBlack = image.isBlack(steep ? y : x, steep ? x : y); boolean isBlack = image.get(steep ? y : x, steep ? x : y);
if (isBlack != inBlack) { if (isBlack != inBlack) {
transitions++; transitions++;
inBlack = isBlack; inBlack = isBlack;

View file

@ -47,7 +47,7 @@ public final class QRCodeMultiReader extends QRCodeReader implements MultipleBar
public Result[] decodeMultiple(BinaryBitmap image, Hashtable hints) throws ReaderException { public Result[] decodeMultiple(BinaryBitmap image, Hashtable hints) throws ReaderException {
Vector results = new Vector(); Vector results = new Vector();
DetectorResult[] detectorResult = new MultiDetector(image).detectMulti(hints); DetectorResult[] detectorResult = new MultiDetector(image.getBlackMatrix()).detectMulti(hints);
for (int i = 0; i < detectorResult.length; i++) { for (int i = 0; i < detectorResult.length; i++) {
try { try {
DecoderResult decoderResult = getDecoder().decode(detectorResult[i].getBits()); DecoderResult decoderResult = getDecoder().decode(detectorResult[i].getBits());

View file

@ -16,9 +16,9 @@
package com.google.zxing.multi.qrcode.detector; package com.google.zxing.multi.qrcode.detector;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.ReaderException; import com.google.zxing.ReaderException;
import com.google.zxing.common.DetectorResult; import com.google.zxing.common.DetectorResult;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.detector.Detector; import com.google.zxing.qrcode.detector.Detector;
import com.google.zxing.qrcode.detector.FinderPatternInfo; import com.google.zxing.qrcode.detector.FinderPatternInfo;
@ -36,12 +36,12 @@ public final class MultiDetector extends Detector {
private static final DetectorResult[] EMPTY_DETECTOR_RESULTS = new DetectorResult[0]; private static final DetectorResult[] EMPTY_DETECTOR_RESULTS = new DetectorResult[0];
public MultiDetector(BinaryBitmap image) { public MultiDetector(BitMatrix image) {
super(image); super(image);
} }
public DetectorResult[] detectMulti(Hashtable hints) throws ReaderException { public DetectorResult[] detectMulti(Hashtable hints) throws ReaderException {
BinaryBitmap image = getImage(); BitMatrix image = getImage();
MultiFinderPatternFinder finder = new MultiFinderPatternFinder(image); MultiFinderPatternFinder finder = new MultiFinderPatternFinder(image);
FinderPatternInfo[] info = finder.findMulti(hints); FinderPatternInfo[] info = finder.findMulti(hints);

View file

@ -17,12 +17,11 @@
package com.google.zxing.multi.qrcode.detector; package com.google.zxing.multi.qrcode.detector;
import com.google.zxing.DecodeHintType; import com.google.zxing.DecodeHintType;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.ReaderException; import com.google.zxing.ReaderException;
import com.google.zxing.ResultPoint; import com.google.zxing.ResultPoint;
import com.google.zxing.common.BitArray;
import com.google.zxing.common.Collections; import com.google.zxing.common.Collections;
import com.google.zxing.common.Comparator; import com.google.zxing.common.Comparator;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.detector.FinderPattern; import com.google.zxing.qrcode.detector.FinderPattern;
import com.google.zxing.qrcode.detector.FinderPatternFinder; import com.google.zxing.qrcode.detector.FinderPatternFinder;
import com.google.zxing.qrcode.detector.FinderPatternInfo; import com.google.zxing.qrcode.detector.FinderPatternInfo;
@ -87,7 +86,7 @@ final class MultiFinderPatternFinder extends FinderPatternFinder {
* *
* @param image image to search * @param image image to search
*/ */
MultiFinderPatternFinder(BinaryBitmap image) { MultiFinderPatternFinder(BitMatrix image) {
super(image); super(image);
} }
@ -228,7 +227,7 @@ final class MultiFinderPatternFinder extends FinderPatternFinder {
public FinderPatternInfo[] findMulti(Hashtable hints) throws ReaderException { public FinderPatternInfo[] findMulti(Hashtable hints) throws ReaderException {
boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER); boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER);
BinaryBitmap image = getImage(); BitMatrix image = getImage();
int maxI = image.getHeight(); int maxI = image.getHeight();
int maxJ = image.getWidth(); int maxJ = image.getWidth();
// We are looking for black/white/black/white/black modules in // We are looking for black/white/black/white/black modules in
@ -245,10 +244,7 @@ final class MultiFinderPatternFinder extends FinderPatternFinder {
int[] stateCount = new int[5]; int[] stateCount = new int[5];
for (int i = iSkip - 1; i < maxI; i += iSkip) { for (int i = iSkip - 1; i < maxI; i += iSkip) {
BitArray blackRow = new BitArray(maxJ);
// Get a row of black/white values // Get a row of black/white values
blackRow = image.getBlackRow(i, blackRow, 0, maxJ);
stateCount[0] = 0; stateCount[0] = 0;
stateCount[1] = 0; stateCount[1] = 0;
stateCount[2] = 0; stateCount[2] = 0;
@ -256,7 +252,7 @@ final class MultiFinderPatternFinder extends FinderPatternFinder {
stateCount[4] = 0; stateCount[4] = 0;
int currentState = 0; int currentState = 0;
for (int j = 0; j < maxJ; j++) { for (int j = 0; j < maxJ; j++) {
if (blackRow.get(j)) { if (image.get(j, i)) {
// Black pixel // Black pixel
if ((currentState & 1) == 1) { // Counting white pixels if ((currentState & 1) == 1) { // Counting white pixels
currentState++; currentState++;
@ -270,7 +266,7 @@ final class MultiFinderPatternFinder extends FinderPatternFinder {
if (!confirmed) { if (!confirmed) {
do { // Advance to next black pixel do { // Advance to next black pixel
j++; j++;
} while (j < maxJ && !blackRow.get(j)); } while (j < maxJ && !image.get(j, i));
j--; // back up to that last white pixel j--; // back up to that last white pixel
} }
// Clear state to start looking again // Clear state to start looking again

View file

@ -62,11 +62,11 @@ public class QRCodeReader implements Reader {
DecoderResult decoderResult; DecoderResult decoderResult;
ResultPoint[] points; ResultPoint[] points;
if (hints != null && hints.containsKey(DecodeHintType.PURE_BARCODE)) { if (hints != null && hints.containsKey(DecodeHintType.PURE_BARCODE)) {
BitMatrix bits = extractPureBits(image); BitMatrix bits = extractPureBits(image.getBlackMatrix());
decoderResult = decoder.decode(bits); decoderResult = decoder.decode(bits);
points = NO_POINTS; points = NO_POINTS;
} else { } else {
DetectorResult detectorResult = new Detector(image).detect(hints); DetectorResult detectorResult = new Detector(image.getBlackMatrix()).detect(hints);
decoderResult = decoder.decode(detectorResult.getBits()); decoderResult = decoder.decode(detectorResult.getBits());
points = detectorResult.getPoints(); points = detectorResult.getPoints();
} }
@ -84,7 +84,7 @@ public class QRCodeReader implements Reader {
* around it. This is a specialized method that works exceptionally fast in this special * around it. This is a specialized method that works exceptionally fast in this special
* case. * case.
*/ */
private static BitMatrix extractPureBits(BinaryBitmap image) throws ReaderException { private static BitMatrix extractPureBits(BitMatrix image) throws ReaderException {
// Now need to determine module size in pixels // Now need to determine module size in pixels
int height = image.getHeight(); int height = image.getHeight();
@ -93,7 +93,7 @@ public class QRCodeReader implements Reader {
// First, skip white border by tracking diagonally from the top left down and to the right: // First, skip white border by tracking diagonally from the top left down and to the right:
int borderWidth = 0; int borderWidth = 0;
while (borderWidth < minDimension && !image.isBlack(borderWidth, borderWidth)) { while (borderWidth < minDimension && !image.get(borderWidth, borderWidth)) {
borderWidth++; borderWidth++;
} }
if (borderWidth == minDimension) { if (borderWidth == minDimension) {
@ -102,7 +102,7 @@ public class QRCodeReader implements Reader {
// And then keep tracking across the top-left black module to determine module size // And then keep tracking across the top-left black module to determine module size
int moduleEnd = borderWidth; int moduleEnd = borderWidth;
while (moduleEnd < minDimension && image.isBlack(moduleEnd, moduleEnd)) { while (moduleEnd < minDimension && image.get(moduleEnd, moduleEnd)) {
moduleEnd++; moduleEnd++;
} }
if (moduleEnd == minDimension) { if (moduleEnd == minDimension) {
@ -113,7 +113,7 @@ public class QRCodeReader implements Reader {
// And now find where the rightmost black module on the first row ends // And now find where the rightmost black module on the first row ends
int rowEndOfSymbol = width - 1; int rowEndOfSymbol = width - 1;
while (rowEndOfSymbol >= 0 && !image.isBlack(rowEndOfSymbol, borderWidth)) { while (rowEndOfSymbol >= 0 && !image.get(rowEndOfSymbol, borderWidth)) {
rowEndOfSymbol--; rowEndOfSymbol--;
} }
if (rowEndOfSymbol < 0) { if (rowEndOfSymbol < 0) {
@ -142,7 +142,7 @@ public class QRCodeReader implements Reader {
for (int i = 0; i < dimension; i++) { for (int i = 0; i < dimension; i++) {
int iOffset = borderWidth + i * moduleSize; int iOffset = borderWidth + i * moduleSize;
for (int j = 0; j < dimension; j++) { for (int j = 0; j < dimension; j++) {
if (image.isBlack(borderWidth + j * moduleSize, iOffset)) { if (image.get(borderWidth + j * moduleSize, iOffset)) {
bits.set(j, i); bits.set(j, i);
} }
} }

View file

@ -17,8 +17,7 @@
package com.google.zxing.qrcode.detector; package com.google.zxing.qrcode.detector;
import com.google.zxing.ReaderException; import com.google.zxing.ReaderException;
import com.google.zxing.BinaryBitmap; import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.BitArray;
import java.util.Vector; import java.util.Vector;
@ -38,7 +37,7 @@ import java.util.Vector;
*/ */
final class AlignmentPatternFinder { final class AlignmentPatternFinder {
private final BinaryBitmap image; private final BitMatrix image;
private final Vector possibleCenters; private final Vector possibleCenters;
private final int startX; private final int startX;
private final int startY; private final int startY;
@ -57,7 +56,7 @@ final class AlignmentPatternFinder {
* @param height height of region to search * @param height height of region to search
* @param moduleSize estimated module size so far * @param moduleSize estimated module size so far
*/ */
AlignmentPatternFinder(BinaryBitmap image, AlignmentPatternFinder(BitMatrix image,
int startX, int startX,
int startY, int startY,
int width, int width,
@ -85,14 +84,12 @@ final class AlignmentPatternFinder {
int height = this.height; int height = this.height;
int maxJ = startX + width; int maxJ = startX + width;
int middleI = startY + (height >> 1); int middleI = startY + (height >> 1);
BitArray luminanceRow = new BitArray(width);
// We are looking for black/white/black modules in 1:1:1 ratio; // We are looking for black/white/black modules in 1:1:1 ratio;
// this tracks the number of black/white/black modules seen so far // this tracks the number of black/white/black modules seen so far
int[] stateCount = new int[3]; int[] stateCount = new int[3];
for (int iGen = 0; iGen < height; iGen++) { for (int iGen = 0; iGen < height; iGen++) {
// Search from middle outwards // Search from middle outwards
int i = middleI + ((iGen & 0x01) == 0 ? ((iGen + 1) >> 1) : -((iGen + 1) >> 1)); int i = middleI + ((iGen & 0x01) == 0 ? ((iGen + 1) >> 1) : -((iGen + 1) >> 1));
luminanceRow = image.getBlackRow(i, luminanceRow, startX, width);
stateCount[0] = 0; stateCount[0] = 0;
stateCount[1] = 0; stateCount[1] = 0;
stateCount[2] = 0; stateCount[2] = 0;
@ -100,12 +97,12 @@ final class AlignmentPatternFinder {
// Burn off leading white pixels before anything else; if we start in the middle of // Burn off leading white pixels before anything else; if we start in the middle of
// a white run, it doesn't make sense to count its length, since we don't know if the // a white run, it doesn't make sense to count its length, since we don't know if the
// white run continued to the left of the start point // white run continued to the left of the start point
while (j < maxJ && !luminanceRow.get(j - startX)) { while (j < maxJ && !image.get(j, i)) {
j++; j++;
} }
int currentState = 0; int currentState = 0;
while (j < maxJ) { while (j < maxJ) {
if (luminanceRow.get(j - startX)) { if (image.get(j, i)) {
// Black pixel // Black pixel
if (currentState == 1) { // Counting black pixels if (currentState == 1) { // Counting black pixels
stateCount[currentState]++; stateCount[currentState]++;
@ -187,8 +184,8 @@ final class AlignmentPatternFinder {
* @return vertical center of alignment pattern, or {@link Float#NaN} if not found * @return vertical center of alignment pattern, or {@link Float#NaN} if not found
*/ */
private float crossCheckVertical(int startI, int centerJ, int maxCount, private float crossCheckVertical(int startI, int centerJ, int maxCount,
int originalStateCountTotal) throws ReaderException { int originalStateCountTotal) {
BinaryBitmap image = this.image; BitMatrix image = this.image;
int maxI = image.getHeight(); int maxI = image.getHeight();
int[] stateCount = crossCheckStateCount; int[] stateCount = crossCheckStateCount;
@ -198,7 +195,7 @@ final class AlignmentPatternFinder {
// Start counting up from center // Start counting up from center
int i = startI; int i = startI;
while (i >= 0 && image.isBlack(centerJ, i) && stateCount[1] <= maxCount) { while (i >= 0 && image.get(centerJ, i) && stateCount[1] <= maxCount) {
stateCount[1]++; stateCount[1]++;
i--; i--;
} }
@ -206,7 +203,7 @@ final class AlignmentPatternFinder {
if (i < 0 || stateCount[1] > maxCount) { if (i < 0 || stateCount[1] > maxCount) {
return Float.NaN; return Float.NaN;
} }
while (i >= 0 && !image.isBlack(centerJ, i) && stateCount[0] <= maxCount) { while (i >= 0 && !image.get(centerJ, i) && stateCount[0] <= maxCount) {
stateCount[0]++; stateCount[0]++;
i--; i--;
} }
@ -216,14 +213,14 @@ final class AlignmentPatternFinder {
// Now also count down from center // Now also count down from center
i = startI + 1; i = startI + 1;
while (i < maxI && image.isBlack(centerJ, i) && stateCount[1] <= maxCount) { while (i < maxI && image.get(centerJ, i) && stateCount[1] <= maxCount) {
stateCount[1]++; stateCount[1]++;
i++; i++;
} }
if (i == maxI || stateCount[1] > maxCount) { if (i == maxI || stateCount[1] > maxCount) {
return Float.NaN; return Float.NaN;
} }
while (i < maxI && !image.isBlack(centerJ, i) && stateCount[2] <= maxCount) { while (i < maxI && !image.get(centerJ, i) && stateCount[2] <= maxCount) {
stateCount[2]++; stateCount[2]++;
i++; i++;
} }
@ -250,8 +247,7 @@ final class AlignmentPatternFinder {
* @param j end of possible alignment pattern in row * @param j end of possible alignment pattern in row
* @return {@link AlignmentPattern} if we have found the same pattern twice, or null if not * @return {@link AlignmentPattern} if we have found the same pattern twice, or null if not
*/ */
private AlignmentPattern handlePossibleCenter(int[] stateCount, int i, int j) private AlignmentPattern handlePossibleCenter(int[] stateCount, int i, int j) {
throws ReaderException {
int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2]; int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2];
float centerJ = centerFromEnd(stateCount, j); float centerJ = centerFromEnd(stateCount, j);
float centerI = crossCheckVertical(i, (int) centerJ, 2 * stateCount[1], stateCountTotal); float centerI = crossCheckVertical(i, (int) centerJ, 2 * stateCount[1], stateCountTotal);

View file

@ -18,7 +18,6 @@ package com.google.zxing.qrcode.detector;
import com.google.zxing.ReaderException; import com.google.zxing.ReaderException;
import com.google.zxing.ResultPoint; import com.google.zxing.ResultPoint;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.common.BitMatrix; import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.DetectorResult; import com.google.zxing.common.DetectorResult;
import com.google.zxing.common.GridSampler; import com.google.zxing.common.GridSampler;
@ -34,13 +33,13 @@ import java.util.Hashtable;
*/ */
public class Detector { public class Detector {
private final BinaryBitmap image; private final BitMatrix image;
public Detector(BinaryBitmap image) { public Detector(BitMatrix image) {
this.image = image; this.image = image;
} }
protected BinaryBitmap getImage() { protected BitMatrix getImage() {
return image; return image;
} }
@ -63,7 +62,6 @@ public class Detector {
*/ */
public DetectorResult detect(Hashtable hints) throws ReaderException { public DetectorResult detect(Hashtable hints) throws ReaderException {
BinaryBitmap image = this.image;
FinderPatternFinder finder = new FinderPatternFinder(image); FinderPatternFinder finder = new FinderPatternFinder(image);
FinderPatternInfo info = finder.find(hints); FinderPatternInfo info = finder.find(hints);
@ -124,7 +122,7 @@ public class Detector {
return new DetectorResult(bits, points); return new DetectorResult(bits, points);
} }
private static BitMatrix sampleGrid(BinaryBitmap image, private static BitMatrix sampleGrid(BitMatrix image,
ResultPoint topLeft, ResultPoint topLeft,
ResultPoint topRight, ResultPoint topRight,
ResultPoint bottomLeft, ResultPoint bottomLeft,
@ -209,8 +207,7 @@ public class Detector {
* {@link #sizeOfBlackWhiteBlackRunBothWays(int, int, int, int)} to figure the * {@link #sizeOfBlackWhiteBlackRunBothWays(int, int, int, int)} to figure the
* width of each, measuring along the axis between their centers.</p> * width of each, measuring along the axis between their centers.</p>
*/ */
private float calculateModuleSizeOneWay(ResultPoint pattern, ResultPoint otherPattern) private float calculateModuleSizeOneWay(ResultPoint pattern, ResultPoint otherPattern) {
throws ReaderException {
float moduleSizeEst1 = sizeOfBlackWhiteBlackRunBothWays((int) pattern.getX(), float moduleSizeEst1 = sizeOfBlackWhiteBlackRunBothWays((int) pattern.getX(),
(int) pattern.getY(), (int) pattern.getY(),
(int) otherPattern.getX(), (int) otherPattern.getX(),
@ -235,8 +232,7 @@ public class Detector {
* a finder pattern by looking for a black-white-black run from the center in the direction * a finder pattern by looking for a black-white-black run from the center in the direction
* of another point (another finder pattern center), and in the opposite direction too.</p> * of another point (another finder pattern center), and in the opposite direction too.</p>
*/ */
private float sizeOfBlackWhiteBlackRunBothWays(int fromX, int fromY, int toX, int toY) private float sizeOfBlackWhiteBlackRunBothWays(int fromX, int fromY, int toX, int toY) {
throws ReaderException {
float result = sizeOfBlackWhiteBlackRun(fromX, fromY, toX, toY); float result = sizeOfBlackWhiteBlackRun(fromX, fromY, toX, toY);
@ -267,8 +263,7 @@ public class Detector {
* <p>This is used when figuring out how wide a finder pattern is, when the finder pattern * <p>This is used when figuring out how wide a finder pattern is, when the finder pattern
* may be skewed or rotated.</p> * may be skewed or rotated.</p>
*/ */
private float sizeOfBlackWhiteBlackRun(int fromX, int fromY, int toX, int toY) private float sizeOfBlackWhiteBlackRun(int fromX, int fromY, int toX, int toY) {
throws ReaderException {
// Mild variant of Bresenham's algorithm; // Mild variant of Bresenham's algorithm;
// see http://en.wikipedia.org/wiki/Bresenham's_line_algorithm // see http://en.wikipedia.org/wiki/Bresenham's_line_algorithm
boolean steep = Math.abs(toY - fromY) > Math.abs(toX - fromX); boolean steep = Math.abs(toY - fromY) > Math.abs(toX - fromX);
@ -292,11 +287,11 @@ public class Detector {
int realX = steep ? y : x; int realX = steep ? y : x;
int realY = steep ? x : y; int realY = steep ? x : y;
if (state == 1) { // In white pixels, looking for black if (state == 1) { // In white pixels, looking for black
if (image.isBlack(realX, realY)) { if (image.get(realX, realY)) {
state++; state++;
} }
} else { } else {
if (!image.isBlack(realX, realY)) { if (!image.get(realX, realY)) {
state++; state++;
} }
} }

View file

@ -16,13 +16,12 @@
package com.google.zxing.qrcode.detector; package com.google.zxing.qrcode.detector;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType; import com.google.zxing.DecodeHintType;
import com.google.zxing.ReaderException; import com.google.zxing.ReaderException;
import com.google.zxing.ResultPoint; import com.google.zxing.ResultPoint;
import com.google.zxing.common.BitArray;
import com.google.zxing.common.Collections; import com.google.zxing.common.Collections;
import com.google.zxing.common.Comparator; import com.google.zxing.common.Comparator;
import com.google.zxing.common.BitMatrix;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Vector; import java.util.Vector;
@ -42,7 +41,7 @@ public class FinderPatternFinder {
protected static final int MAX_MODULES = 57; // support up to version 10 for mobile clients protected static final int MAX_MODULES = 57; // support up to version 10 for mobile clients
private static final int INTEGER_MATH_SHIFT = 8; private static final int INTEGER_MATH_SHIFT = 8;
private final BinaryBitmap image; private final BitMatrix image;
private final Vector possibleCenters; private final Vector possibleCenters;
private boolean hasSkipped; private boolean hasSkipped;
private final int[] crossCheckStateCount; private final int[] crossCheckStateCount;
@ -52,13 +51,13 @@ public class FinderPatternFinder {
* *
* @param image image to search * @param image image to search
*/ */
public FinderPatternFinder(BinaryBitmap image) { public FinderPatternFinder(BitMatrix image) {
this.image = image; this.image = image;
this.possibleCenters = new Vector(); this.possibleCenters = new Vector();
this.crossCheckStateCount = new int[5]; this.crossCheckStateCount = new int[5];
} }
protected BinaryBitmap getImage() { protected BitMatrix getImage() {
return image; return image;
} }
@ -84,10 +83,8 @@ public class FinderPatternFinder {
boolean done = false; boolean done = false;
int[] stateCount = new int[5]; int[] stateCount = new int[5];
BitArray blackRow = new BitArray(maxJ);
for (int i = iSkip - 1; i < maxI && !done; i += iSkip) { for (int i = iSkip - 1; i < maxI && !done; i += iSkip) {
// Get a row of black/white values // Get a row of black/white values
blackRow = image.getBlackRow(i, blackRow, 0, maxJ);
stateCount[0] = 0; stateCount[0] = 0;
stateCount[1] = 0; stateCount[1] = 0;
stateCount[2] = 0; stateCount[2] = 0;
@ -95,7 +92,7 @@ public class FinderPatternFinder {
stateCount[4] = 0; stateCount[4] = 0;
int currentState = 0; int currentState = 0;
for (int j = 0; j < maxJ; j++) { for (int j = 0; j < maxJ; j++) {
if (blackRow.get(j)) { if (image.get(j, i)) {
// Black pixel // Black pixel
if ((currentState & 1) == 1) { // Counting white pixels if ((currentState & 1) == 1) { // Counting white pixels
currentState++; currentState++;
@ -131,7 +128,7 @@ public class FinderPatternFinder {
// Advance to next black pixel // Advance to next black pixel
do { do {
j++; j++;
} while (j < maxJ && !blackRow.get(j)); } while (j < maxJ && !image.get(j, i));
j--; // back up to that last white pixel j--; // back up to that last white pixel
} }
// Clear state to start looking again // Clear state to start looking again
@ -231,22 +228,22 @@ public class FinderPatternFinder {
* @return vertical center of finder pattern, or {@link Float#NaN} if not found * @return vertical center of finder pattern, or {@link Float#NaN} if not found
*/ */
private float crossCheckVertical(int startI, int centerJ, int maxCount, private float crossCheckVertical(int startI, int centerJ, int maxCount,
int originalStateCountTotal) throws ReaderException { int originalStateCountTotal) {
BinaryBitmap image = this.image; BitMatrix image = this.image;
int maxI = image.getHeight(); int maxI = image.getHeight();
int[] stateCount = getCrossCheckStateCount(); int[] stateCount = getCrossCheckStateCount();
// Start counting up from center // Start counting up from center
int i = startI; int i = startI;
while (i >= 0 && image.isBlack(centerJ, i)) { while (i >= 0 && image.get(centerJ, i)) {
stateCount[2]++; stateCount[2]++;
i--; i--;
} }
if (i < 0) { if (i < 0) {
return Float.NaN; return Float.NaN;
} }
while (i >= 0 && !image.isBlack(centerJ, i) && stateCount[1] <= maxCount) { while (i >= 0 && !image.get(centerJ, i) && stateCount[1] <= maxCount) {
stateCount[1]++; stateCount[1]++;
i--; i--;
} }
@ -254,7 +251,7 @@ public class FinderPatternFinder {
if (i < 0 || stateCount[1] > maxCount) { if (i < 0 || stateCount[1] > maxCount) {
return Float.NaN; return Float.NaN;
} }
while (i >= 0 && image.isBlack(centerJ, i) && stateCount[0] <= maxCount) { while (i >= 0 && image.get(centerJ, i) && stateCount[0] <= maxCount) {
stateCount[0]++; stateCount[0]++;
i--; i--;
} }
@ -264,21 +261,21 @@ public class FinderPatternFinder {
// Now also count down from center // Now also count down from center
i = startI + 1; i = startI + 1;
while (i < maxI && image.isBlack(centerJ, i)) { while (i < maxI && image.get(centerJ, i)) {
stateCount[2]++; stateCount[2]++;
i++; i++;
} }
if (i == maxI) { if (i == maxI) {
return Float.NaN; return Float.NaN;
} }
while (i < maxI && !image.isBlack(centerJ, i) && stateCount[3] < maxCount) { while (i < maxI && !image.get(centerJ, i) && stateCount[3] < maxCount) {
stateCount[3]++; stateCount[3]++;
i++; i++;
} }
if (i == maxI || stateCount[3] >= maxCount) { if (i == maxI || stateCount[3] >= maxCount) {
return Float.NaN; return Float.NaN;
} }
while (i < maxI && image.isBlack(centerJ, i) && stateCount[4] < maxCount) { while (i < maxI && image.get(centerJ, i) && stateCount[4] < maxCount) {
stateCount[4]++; stateCount[4]++;
i++; i++;
} }
@ -303,28 +300,28 @@ public class FinderPatternFinder {
* check a vertical cross check and locate the real center of the alignment pattern.</p> * check a vertical cross check and locate the real center of the alignment pattern.</p>
*/ */
private float crossCheckHorizontal(int startJ, int centerI, int maxCount, private float crossCheckHorizontal(int startJ, int centerI, int maxCount,
int originalStateCountTotal) throws ReaderException { int originalStateCountTotal) {
BinaryBitmap image = this.image; BitMatrix image = this.image;
int maxJ = image.getWidth(); int maxJ = image.getWidth();
int[] stateCount = getCrossCheckStateCount(); int[] stateCount = getCrossCheckStateCount();
int j = startJ; int j = startJ;
while (j >= 0 && image.isBlack(j, centerI)) { while (j >= 0 && image.get(j, centerI)) {
stateCount[2]++; stateCount[2]++;
j--; j--;
} }
if (j < 0) { if (j < 0) {
return Float.NaN; return Float.NaN;
} }
while (j >= 0 && !image.isBlack(j, centerI) && stateCount[1] <= maxCount) { while (j >= 0 && !image.get(j, centerI) && stateCount[1] <= maxCount) {
stateCount[1]++; stateCount[1]++;
j--; j--;
} }
if (j < 0 || stateCount[1] > maxCount) { if (j < 0 || stateCount[1] > maxCount) {
return Float.NaN; return Float.NaN;
} }
while (j >= 0 && image.isBlack(j, centerI) && stateCount[0] <= maxCount) { while (j >= 0 && image.get(j, centerI) && stateCount[0] <= maxCount) {
stateCount[0]++; stateCount[0]++;
j--; j--;
} }
@ -333,21 +330,21 @@ public class FinderPatternFinder {
} }
j = startJ + 1; j = startJ + 1;
while (j < maxJ && image.isBlack(j, centerI)) { while (j < maxJ && image.get(j, centerI)) {
stateCount[2]++; stateCount[2]++;
j++; j++;
} }
if (j == maxJ) { if (j == maxJ) {
return Float.NaN; return Float.NaN;
} }
while (j < maxJ && !image.isBlack(j, centerI) && stateCount[3] < maxCount) { while (j < maxJ && !image.get(j, centerI) && stateCount[3] < maxCount) {
stateCount[3]++; stateCount[3]++;
j++; j++;
} }
if (j == maxJ || stateCount[3] >= maxCount) { if (j == maxJ || stateCount[3] >= maxCount) {
return Float.NaN; return Float.NaN;
} }
while (j < maxJ && image.isBlack(j, centerI) && stateCount[4] < maxCount) { while (j < maxJ && image.get(j, centerI) && stateCount[4] < maxCount) {
stateCount[4]++; stateCount[4]++;
j++; j++;
} }