Add column caching to MonochromeBitmapSources and use it to improve Data Matrix speed

git-svn-id: https://zxing.googlecode.com/svn/trunk@631 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
srowen 2008-10-22 08:43:56 +00:00
parent 15deb0c3d9
commit 96f6428eea
7 changed files with 74 additions and 6 deletions

View file

@ -72,6 +72,10 @@ final class YUVMonochromeBitmapSource extends BaseMonochromeBitmapSource {
} }
public void cacheColumnForLuminance(int x) {
}
/** /**
* Create a greyscale Android Bitmap from the YUV data based on the crop rectangle. * Create a greyscale Android Bitmap from the YUV data based on the crop rectangle.
* *

View file

@ -74,4 +74,8 @@ public final class AWTImageMonochromeBitmapSource extends BaseMonochromeBitmapSo
// do nothing; we are already forced to cache all pixels // do nothing; we are already forced to cache all pixels
} }
public void cacheColumnForLuminance(int x) {
// do nothing
}
} }

View file

@ -48,6 +48,11 @@ public interface MonochromeBitmapSource {
*/ */
BitArray getBlackRow(int y, BitArray row, int startX, int getWidth); BitArray getBlackRow(int y, BitArray row, int startX, int getWidth);
/**
* Entirely analogous to {@link #getBlackRow(int, BitArray, int, int)} but gets a column.
*/
BitArray getBlackColumn(int x, BitArray column, int startY, int getHeight);
/** /**
* @return height of underlying image * @return height of underlying image
*/ */
@ -76,6 +81,11 @@ public interface MonochromeBitmapSource {
*/ */
void cacheRowForLuminance(int y); void cacheRowForLuminance(int y);
/**
* Entirely analogous to {@link #cacheRowForLuminance(int)} but caches a column.
*/
void cacheColumnForLuminance(int x);
/** /**
* <p>Estimates black point according to the given method, which is optionally parameterized by * <p>Estimates black point according to the given method, which is optionally parameterized by
* a single int argument. For {@link BlackPointEstimationMethod#ROW_SAMPLING}, this * a single int argument. For {@link BlackPointEstimationMethod#ROW_SAMPLING}, this

View file

@ -76,6 +76,23 @@ public abstract class BaseMonochromeBitmapSource implements MonochromeBitmapSour
return row; return row;
} }
public BitArray getBlackColumn(int x, BitArray column, int startY, int getHeight) {
if (column == null || column.getSize() < getHeight) {
column = new BitArray(getHeight);
} else {
column.clear();
}
cacheColumnForLuminance(x);
// We don't handle "row sampling" specially here
for (int y = 0; y < getHeight; y++) {
if (getLuminance(x, startY + y) < blackPoint) {
column.set(y);
}
}
return column;
}
public void estimateBlackPoint(BlackPointEstimationMethod method, int argument) throws ReaderException { public void estimateBlackPoint(BlackPointEstimationMethod method, int argument) throws ReaderException {
if (!method.equals(lastMethod) || argument != lastArgument) { if (!method.equals(lastMethod) || argument != lastArgument) {
int width = getWidth(); int width = getWidth();
@ -131,4 +148,6 @@ public abstract class BaseMonochromeBitmapSource implements MonochromeBitmapSour
public abstract void cacheRowForLuminance(int y); public abstract void cacheRowForLuminance(int y);
public abstract void cacheColumnForLuminance(int x);
} }

View file

@ -20,6 +20,7 @@ import com.google.zxing.MonochromeBitmapSource;
import com.google.zxing.ReaderException; import com.google.zxing.ReaderException;
import com.google.zxing.ResultPoint; import com.google.zxing.ResultPoint;
import com.google.zxing.BlackPointEstimationMethod; import com.google.zxing.BlackPointEstimationMethod;
import com.google.zxing.common.BitArray;
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;
@ -262,17 +263,19 @@ public final class Detector {
int center = (minDim + maxDim) / 2; int center = (minDim + maxDim) / 2;
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 (horizontal ? image.isBlack(start, fixedDimension) : image.isBlack(fixedDimension, start)) { if (rowOrColumn.get(start)) {
start--; start--;
} else { } else {
int whiteRunStart = start; int whiteRunStart = start;
do { do {
start--; start--;
} while (start >= minDim && } while (start >= minDim && !rowOrColumn.get(start));
!(horizontal ? image.isBlack(start, fixedDimension) : image.isBlack(fixedDimension, start)));
int whiteRunSize = whiteRunStart - start; int whiteRunSize = whiteRunStart - start;
if (start < minDim || whiteRunSize > maxWhiteRun) { if (start < minDim || whiteRunSize > maxWhiteRun) {
start = whiteRunStart + 1; // back up start = whiteRunStart + 1; // back up
@ -284,14 +287,13 @@ public final class Detector {
// Then try right/down // Then try right/down
int end = center; int end = center;
while (end < maxDim) { while (end < maxDim) {
if (horizontal ? image.isBlack(end, fixedDimension) : image.isBlack(fixedDimension, end)) { if (rowOrColumn.get(end)) {
end++; end++;
} else { } else {
int whiteRunStart = end; int whiteRunStart = end;
do { do {
end++; end++;
} while (end < maxDim && } while (end < maxDim && !rowOrColumn.get(end));
!(horizontal ? image.isBlack(end, fixedDimension) : image.isBlack(fixedDimension, end)));
int whiteRunSize = end - whiteRunStart; int whiteRunSize = end - whiteRunStart;
if (end >= maxDim || whiteRunSize > maxWhiteRun) { if (end >= maxDim || whiteRunSize > maxWhiteRun) {
end = whiteRunStart - 1; end = whiteRunStart - 1;

View file

@ -32,16 +32,20 @@ public final class LCDUIImageMonochromeBitmapSource extends BaseMonochromeBitmap
private final int width; private final int width;
// For why this isn't final, see below // For why this isn't final, see below
private int[] rgbRow; private int[] rgbRow;
private int[] rgbColumn;
private final int[] pixelHolder; private final int[] pixelHolder;
private int cachedRow; private int cachedRow;
private int cachedColumn;
public LCDUIImageMonochromeBitmapSource(Image image) { public LCDUIImageMonochromeBitmapSource(Image image) {
this.image = image; this.image = image;
height = image.getHeight(); height = image.getHeight();
width = image.getWidth(); width = image.getWidth();
rgbRow = new int[width]; rgbRow = new int[width];
rgbColumn = new int[height];
pixelHolder = new int[1]; pixelHolder = new int[1];
cachedRow = -1; cachedRow = -1;
cachedColumn = -1;
} }
public int getHeight() { public int getHeight() {
@ -61,6 +65,8 @@ public final class LCDUIImageMonochromeBitmapSource extends BaseMonochromeBitmap
int pixel; int pixel;
if (cachedRow == y && rgbRow.length == width) { if (cachedRow == y && rgbRow.length == width) {
pixel = rgbRow[x]; pixel = rgbRow[x];
} else if (cachedColumn == x && rgbColumn.length == height) {
pixel = rgbColumn[y];
} else { } else {
image.getRGB(pixelHolder, 0, width, x, y, 1, 1); image.getRGB(pixelHolder, 0, width, x, y, 1, 1);
pixel = pixelHolder[0]; pixel = pixelHolder[0];
@ -94,4 +100,14 @@ public final class LCDUIImageMonochromeBitmapSource extends BaseMonochromeBitmap
} }
} }
public void cacheColumnForLuminance(int x) {
if (x != cachedColumn) {
if (rgbColumn.length != height) {
rgbColumn = new int[height];
}
image.getRGB(rgbColumn, 0, 1, x, 0, 1, height);
cachedColumn = x;
}
}
} }

View file

@ -43,7 +43,9 @@ public final class BufferedImageMonochromeBitmapSource extends BaseMonochromeBit
private final int width; private final int width;
private final int height; private final int height;
private int[] rgbRow; private int[] rgbRow;
private int[] rgbColumn;
private int cachedRow; private int cachedRow;
private int cachedColumn;
/** /**
* Creates an instance that uses the entire given image as a source of pixels to decode. * Creates an instance that uses the entire given image as a source of pixels to decode.
@ -78,7 +80,9 @@ public final class BufferedImageMonochromeBitmapSource extends BaseMonochromeBit
this.width = right - left; this.width = right - left;
this.height = bottom - top; this.height = bottom - top;
rgbRow = new int[width]; rgbRow = new int[width];
rgbColumn = new int[height];
cachedRow = -1; cachedRow = -1;
cachedColumn = -1;
} }
/** /**
@ -136,6 +140,8 @@ public final class BufferedImageMonochromeBitmapSource extends BaseMonochromeBit
int pixel; int pixel;
if (cachedRow == y) { if (cachedRow == y) {
pixel = rgbRow[x]; pixel = rgbRow[x];
} else if (cachedColumn == x) {
pixel = rgbColumn[y];
} else { } else {
pixel = image.getRGB(left + x, top + y); pixel = image.getRGB(left + x, top + y);
} }
@ -153,4 +159,11 @@ public final class BufferedImageMonochromeBitmapSource extends BaseMonochromeBit
} }
} }
public void cacheColumnForLuminance(int x) {
if (x != cachedColumn) {
image.getRGB(left + x, top, 1, height, rgbColumn, 0, 1);
cachedColumn = x;
}
}
} }