More optimizations plus some improved RSS expanded misdetection detection

git-svn-id: https://zxing.googlecode.com/svn/trunk@2517 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
srowen 2012-11-13 13:31:50 +00:00
parent 14b2eeb7ae
commit 6767168801
4 changed files with 126 additions and 43 deletions

View file

@ -99,10 +99,12 @@ public final class Code39Reader extends OneDReader {
public Result decodeRow(int rowNumber, BitArray row, Map<DecodeHintType,?> hints)
throws NotFoundException, ChecksumException, FormatException {
Arrays.fill(counters, 0);
decodeRowResult.setLength(0);
int[] theCounters = counters;
Arrays.fill(theCounters, 0);
StringBuilder result = decodeRowResult;
result.setLength(0);
int[] start = findAsteriskPattern(row, counters);
int[] start = findAsteriskPattern(row, theCounters);
// Read off white space
int nextStart = row.getNextSet(start[1]);
int end = row.getSize();
@ -110,25 +112,25 @@ public final class Code39Reader extends OneDReader {
char decodedChar;
int lastStart;
do {
recordPattern(row, nextStart, counters);
int pattern = toNarrowWidePattern(counters);
recordPattern(row, nextStart, theCounters);
int pattern = toNarrowWidePattern(theCounters);
if (pattern < 0) {
throw NotFoundException.getNotFoundInstance();
}
decodedChar = patternToChar(pattern);
decodeRowResult.append(decodedChar);
result.append(decodedChar);
lastStart = nextStart;
for (int counter : counters) {
for (int counter : theCounters) {
nextStart += counter;
}
// Read off white space
nextStart = row.getNextSet(nextStart);
} while (decodedChar != '*');
decodeRowResult.setLength(decodeRowResult.length() - 1); // remove asterisk
result.setLength(result.length() - 1); // remove asterisk
// Look for whitespace after pattern:
int lastPatternSize = 0;
for (int counter : counters) {
for (int counter : theCounters) {
lastPatternSize += counter;
}
int whiteSpaceAfterEnd = nextStart - lastStart - lastPatternSize;
@ -139,27 +141,27 @@ public final class Code39Reader extends OneDReader {
}
if (usingCheckDigit) {
int max = decodeRowResult.length() - 1;
int max = result.length() - 1;
int total = 0;
for (int i = 0; i < max; i++) {
total += ALPHABET_STRING.indexOf(decodeRowResult.charAt(i));
}
if (decodeRowResult.charAt(max) != ALPHABET[total % 43]) {
if (result.charAt(max) != ALPHABET[total % 43]) {
throw ChecksumException.getChecksumInstance();
}
decodeRowResult.setLength(max);
result.setLength(max);
}
if (decodeRowResult.length() == 0) {
if (result.length() == 0) {
// false positive
throw NotFoundException.getNotFoundInstance();
}
String resultString;
if (extendedMode) {
resultString = decodeExtended(decodeRowResult);
resultString = decodeExtended(result);
} else {
resultString = decodeRowResult.toString();
resultString = result.toString();
}
float left = (float) (start[1] + start[0]) / 2.0f;

View file

@ -25,6 +25,7 @@ import com.google.zxing.Result;
import com.google.zxing.ResultPoint;
import com.google.zxing.common.BitArray;
import java.util.Arrays;
import java.util.Map;
/**
@ -53,6 +54,14 @@ public final class Code93Reader extends OneDReader {
};
private static final int ASTERISK_ENCODING = CHARACTER_ENCODINGS[47];
private final StringBuilder decodeRowResult;
private final int[] counters;
public Code93Reader() {
decodeRowResult = new StringBuilder(20);
counters = new int[6];
}
@Override
public Result decodeRow(int rowNumber, BitArray row, Map<DecodeHintType,?> hints)
throws NotFoundException, ChecksumException, FormatException {
@ -62,20 +71,23 @@ public final class Code93Reader extends OneDReader {
int nextStart = row.getNextSet(start[1]);
int end = row.getSize();
StringBuilder result = new StringBuilder(20);
int[] counters = new int[6];
int[] theCounters = counters;
Arrays.fill(theCounters, 0);
StringBuilder result = decodeRowResult;
result.setLength(0);
char decodedChar;
int lastStart;
do {
recordPattern(row, nextStart, counters);
int pattern = toPattern(counters);
recordPattern(row, nextStart, theCounters);
int pattern = toPattern(theCounters);
if (pattern < 0) {
throw NotFoundException.getNotFoundInstance();
}
decodedChar = patternToChar(pattern);
result.append(decodedChar);
lastStart = nextStart;
for (int counter : counters) {
for (int counter : theCounters) {
nextStart += counter;
}
// Read off white space
@ -111,33 +123,34 @@ public final class Code93Reader extends OneDReader {
}
private static int[] findAsteriskPattern(BitArray row) throws NotFoundException {
private int[] findAsteriskPattern(BitArray row) throws NotFoundException {
int width = row.getSize();
int rowOffset = row.getNextSet(0);
int counterPosition = 0;
int[] counters = new int[6];
Arrays.fill(counters, 0);
int[] theCounters = counters;
int patternStart = rowOffset;
boolean isWhite = false;
int patternLength = counters.length;
int patternLength = theCounters.length;
int counterPosition = 0;
for (int i = rowOffset; i < width; i++) {
if (row.get(i) ^ isWhite) {
counters[counterPosition]++;
theCounters[counterPosition]++;
} else {
if (counterPosition == patternLength - 1) {
if (toPattern(counters) == ASTERISK_ENCODING) {
if (toPattern(theCounters) == ASTERISK_ENCODING) {
return new int[]{patternStart, i};
}
patternStart += counters[0] + counters[1];
System.arraycopy(counters, 2, counters, 0, patternLength - 2);
counters[patternLength - 2] = 0;
counters[patternLength - 1] = 0;
patternStart += theCounters[0] + theCounters[1];
System.arraycopy(theCounters, 2, theCounters, 0, patternLength - 2);
theCounters[patternLength - 2] = 0;
theCounters[patternLength - 1] = 0;
counterPosition--;
} else {
counterPosition++;
}
counters[counterPosition] = 1;
theCounters[counterPosition] = 1;
isWhite = !isWhite;
}
}

View file

@ -71,9 +71,13 @@ public final class RSS14Reader extends AbstractRSSReader {
Pair rightPair = decodePair(row, true, rowNumber, hints);
addOrTally(possibleRightPairs, rightPair);
row.reverse();
for (Pair left : possibleLeftPairs) {
int lefSize = possibleLeftPairs.size();
for (int i = 0; i < lefSize; i++) {
Pair left = possibleLeftPairs.get(i);
if (left.getCount() > 1) {
for (Pair right : possibleRightPairs) {
int rightSize = possibleRightPairs.size();
for (int j = 0; j < rightSize; j++) {
Pair right = possibleRightPairs.get(j);
if (right.getCount() > 1) {
if (checkChecksum(left, right)) {
return constructResult(left, right);

View file

@ -89,7 +89,6 @@ public final class RSSExpandedReader extends AbstractRSSReader {
{ 45, 135, 194, 160, 58, 174, 100, 89}
};
/*
private static final int FINDER_PAT_A = 0;
private static final int FINDER_PAT_B = 1;
private static final int FINDER_PAT_C = 2;
@ -110,8 +109,7 @@ public final class RSSExpandedReader extends AbstractRSSReader {
{ FINDER_PAT_A, FINDER_PAT_A, FINDER_PAT_B, FINDER_PAT_B, FINDER_PAT_C, FINDER_PAT_D, FINDER_PAT_D, FINDER_PAT_E, FINDER_PAT_E, FINDER_PAT_F, FINDER_PAT_F },
};
private static final int LONGEST_SEQUENCE_SIZE = FINDER_PATTERN_SEQUENCES[FINDER_PATTERN_SEQUENCES.length - 1].length;
*/
//private static final int LONGEST_SEQUENCE_SIZE = FINDER_PATTERN_SEQUENCES[FINDER_PATTERN_SEQUENCES.length - 1].length;
private static final int MAX_PAIRS = 11;
@ -188,24 +186,90 @@ public final class RSSExpandedReader extends AbstractRSSReader {
}
private List<ExpandedPair> checkRows(boolean reverse) {
// Limit number of rows we are checking
// We use recursive algorithm with pure complexity and don't want it to take forever
// Stacked barcode can have up to 11 rows, so 25 seems resonable enough
if (this.rows.size() > 25) {
this.rows.clear(); // We will never have a chance to get result, so clear it
return null;
}
this.pairs.clear();
if (reverse) {
Collections.reverse(this.rows);
}
for(ExpandedRow erow : this.rows) {
this.pairs.addAll(erow.getPairs());
}
//System.out.println(this.pairs.size()+" pairs on MULTIPLE ROWS: "+this.rows);
if (checkChecksum()) {
return this.pairs;
List<ExpandedPair> ps = null;
try {
ps = checkRows(new ArrayList<ExpandedRow>(), 0);
} catch (NotFoundException e) {
// OK
}
if (reverse) {
Collections.reverse(this.rows);
}
return null;
return ps;
}
// Try to construct a valid rows sequence
// Recursion is used to implement backtracking
private List<ExpandedPair> checkRows(List<ExpandedRow> collectedRows, int currentRow) throws NotFoundException {
for (int i = currentRow; i < rows.size(); i++) {
ExpandedRow row = rows.get(i);
this.pairs.clear();
int size = collectedRows.size();
for (int j = 0; j < size; j++) {
this.pairs.addAll(collectedRows.get(j).getPairs());
}
this.pairs.addAll(row.getPairs());
if (!isValidSequence(this.pairs)) {
continue;
}
if (checkChecksum()) {
return this.pairs;
}
List<ExpandedRow> rs = new ArrayList<ExpandedRow>();
rs.addAll(collectedRows);
rs.add(row);
try {
// Recursion: try to add more rows
return checkRows(rs, i + 1);
} catch (NotFoundException e) {
// We failed, try the next candidate
continue;
}
}
throw NotFoundException.getNotFoundInstance();
}
// Whether the pairs form a valid find pattern seqience,
// either complete or a prefix
private static boolean isValidSequence(List<ExpandedPair> pairs) {
for (int[] sequence : FINDER_PATTERN_SEQUENCES) {
if (pairs.size() > sequence.length) {
continue;
}
boolean stop = true;
for (int j = 0; j < pairs.size(); j++) {
if (pairs.get(j).getFinderPattern().getValue() != sequence[j]) {
stop = false;
break;
}
}
if (stop) {
return true;
}
}
return false;
}
private void storeRow(int rowNumber, boolean wasReversed) {