mirror of
https://github.com/zxing/zxing.git
synced 2025-01-12 19:57:27 -08:00
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:
parent
14b2eeb7ae
commit
6767168801
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue