mirror of
https://github.com/zxing/zxing.git
synced 2025-01-12 19:57:27 -08:00
Now use integer math in patternMatchVariance for performance, plus a few other similar style and speed tweaks
git-svn-id: https://zxing.googlecode.com/svn/trunk@422 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
parent
038add9da1
commit
14895cf9b3
|
@ -35,6 +35,8 @@ import java.util.Hashtable;
|
|||
*/
|
||||
public abstract class AbstractOneDReader implements OneDReader {
|
||||
|
||||
private static final int INTEGER_MATH_SHIFT = 8;
|
||||
|
||||
public final Result decode(MonochromeBitmapSource image) throws ReaderException {
|
||||
return decode(image, null);
|
||||
}
|
||||
|
@ -181,26 +183,37 @@ public abstract class AbstractOneDReader implements OneDReader {
|
|||
*
|
||||
* @param counters observed counters
|
||||
* @param pattern expected pattern
|
||||
* @return average variance between counters and pattern
|
||||
* @return ratio of total variance between counters and pattern compared to total pattern size,
|
||||
* where the ratio has been multiplied by 256. So, 0 means no variance (perfect match); 256 means
|
||||
* the total variance between counters and patterns equals the pattern length, higher values mean
|
||||
* even more variance
|
||||
*/
|
||||
static float patternMatchVariance(int[] counters, int[] pattern) {
|
||||
int total = 0;
|
||||
static int patternMatchVariance(int[] counters, int[] pattern) {
|
||||
int numCounters = counters.length;
|
||||
int total = 0;
|
||||
int patternLength = 0;
|
||||
for (int i = 0; i < numCounters; i++) {
|
||||
total += counters[i];
|
||||
patternLength += pattern[i];
|
||||
}
|
||||
float unitBarWidth = (float) total / (float) patternLength;
|
||||
|
||||
float totalVariance = 0.0f;
|
||||
for (int x = 0; x < numCounters; x++) {
|
||||
float scaledCounter = (float) counters[x] / unitBarWidth;
|
||||
float width = pattern[x];
|
||||
float abs = scaledCounter > width ? scaledCounter - width : width - scaledCounter;
|
||||
totalVariance += abs;
|
||||
if (total < patternLength) {
|
||||
// If we don't even have one pixel per unit of bar width, assume this is too small
|
||||
// to reliably match, so fail:
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
return totalVariance / (float) patternLength;
|
||||
// We're going to fake floating-point math in integers. We just need to use more bits.
|
||||
// Scale up patternLength so that intermediate values below like scaledCounter will have
|
||||
// more "significant digits"
|
||||
patternLength <<= INTEGER_MATH_SHIFT;
|
||||
int patternRatio = patternLength / total;
|
||||
|
||||
int totalVariance = 0;
|
||||
for (int x = 0; x < numCounters; x++) {
|
||||
int scaledCounter = counters[x] * patternRatio;
|
||||
int width = pattern[x] << INTEGER_MATH_SHIFT;
|
||||
totalVariance += scaledCounter > width ? scaledCounter - width : width - scaledCounter;
|
||||
}
|
||||
return (totalVariance << 8) / patternLength;
|
||||
}
|
||||
|
||||
// This declaration should not be necessary, since this class is
|
||||
|
|
|
@ -35,7 +35,7 @@ import java.util.Hashtable;
|
|||
*/
|
||||
public abstract class AbstractUPCEANReader extends AbstractOneDReader implements UPCEANReader {
|
||||
|
||||
private static final float MAX_VARIANCE = 0.4f;
|
||||
private static final int MAX_VARIANCE = 104;
|
||||
|
||||
/**
|
||||
* Start/end guard pattern.
|
||||
|
@ -102,9 +102,8 @@ public abstract class AbstractUPCEANReader extends AbstractOneDReader implements
|
|||
return decodeRow(rowNumber, row, findStartGuardPattern(row));
|
||||
}
|
||||
|
||||
public final Result decodeRow(int rowNumber, BitArray row, int[] startGuardRange)
|
||||
throws ReaderException {
|
||||
StringBuffer result = new StringBuffer();
|
||||
public final Result decodeRow(int rowNumber, BitArray row, int[] startGuardRange) throws ReaderException {
|
||||
StringBuffer result = new StringBuffer(20);
|
||||
int endStart = decodeMiddle(row, startGuardRange, result);
|
||||
int[] endRange = decodeEnd(row, endStart);
|
||||
|
||||
|
@ -243,14 +242,15 @@ public abstract class AbstractUPCEANReader extends AbstractOneDReader implements
|
|||
static int decodeDigit(BitArray row, int[] counters, int rowOffset, int[][] patterns)
|
||||
throws ReaderException {
|
||||
recordPattern(row, rowOffset, counters);
|
||||
float bestVariance = MAX_VARIANCE; // worst variance we'll accept
|
||||
int bestVariance = MAX_VARIANCE; // worst variance we'll accept
|
||||
int bestMatch = -1;
|
||||
for (int d = 0; d < patterns.length; d++) {
|
||||
int[] pattern = patterns[d];
|
||||
float variance = patternMatchVariance(counters, pattern);
|
||||
int max = patterns.length;
|
||||
for (int i = 0; i < max; i++) {
|
||||
int[] pattern = patterns[i];
|
||||
int variance = patternMatchVariance(counters, pattern);
|
||||
if (variance < bestVariance) {
|
||||
bestVariance = variance;
|
||||
bestMatch = d;
|
||||
bestMatch = i;
|
||||
}
|
||||
}
|
||||
if (bestMatch >= 0) {
|
||||
|
|
|
@ -142,7 +142,7 @@ public final class Code128Reader extends AbstractOneDReader {
|
|||
{2, 3, 3, 1, 1, 1, 2}
|
||||
};
|
||||
|
||||
private static final float MAX_VARIANCE = 0.3f;
|
||||
private static final int MAX_VARIANCE = 56;
|
||||
|
||||
private static final int CODE_SHIFT = 98;
|
||||
|
||||
|
@ -183,10 +183,10 @@ public final class Code128Reader extends AbstractOneDReader {
|
|||
counters[counterPosition]++;
|
||||
} else {
|
||||
if (counterPosition == patternLength - 1) {
|
||||
float bestVariance = MAX_VARIANCE;
|
||||
int bestVariance = MAX_VARIANCE;
|
||||
int bestMatch = -1;
|
||||
for (int startCode = CODE_START_A; startCode <= CODE_START_C; startCode++) {
|
||||
float variance = patternMatchVariance(counters, CODE_PATTERNS[startCode]);
|
||||
int variance = patternMatchVariance(counters, CODE_PATTERNS[startCode]);
|
||||
if (variance < bestVariance) {
|
||||
bestVariance = variance;
|
||||
bestMatch = startCode;
|
||||
|
@ -214,11 +214,11 @@ public final class Code128Reader extends AbstractOneDReader {
|
|||
|
||||
private static int decodeCode(BitArray row, int[] counters, int rowOffset) throws ReaderException {
|
||||
recordPattern(row, rowOffset, counters);
|
||||
float bestVariance = MAX_VARIANCE; // worst variance we'll accept
|
||||
int bestVariance = MAX_VARIANCE; // worst variance we'll accept
|
||||
int bestMatch = -1;
|
||||
for (int d = 0; d < CODE_PATTERNS.length; d++) {
|
||||
int[] pattern = CODE_PATTERNS[d];
|
||||
float variance = patternMatchVariance(counters, pattern);
|
||||
int variance = patternMatchVariance(counters, pattern);
|
||||
if (variance < bestVariance) {
|
||||
bestVariance = variance;
|
||||
bestMatch = d;
|
||||
|
|
|
@ -30,7 +30,7 @@ public final class QRCodeBlackBox2TestCase extends AbstractBlackBoxTestCase {
|
|||
public QRCodeBlackBox2TestCase() {
|
||||
super(new File("test/data/blackbox/qrcode-2"), new MultiFormatReader(), BarcodeFormat.QR_CODE);
|
||||
addTest(10, 0.0f);
|
||||
addTest(5, 90.0f);
|
||||
addTest(6, 90.0f);
|
||||
addTest(8, 180.0f);
|
||||
addTest(2, 270.0f);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue