Unify UPC-A reader into EAN-13 reader since EAN-13 is a superset and we can take advantage of the commonality to improve performance.

git-svn-id: https://zxing.googlecode.com/svn/trunk@416 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
srowen 2008-06-11 19:30:57 +00:00
parent 3140b4abdb
commit 88afca0842
2 changed files with 38 additions and 41 deletions

View file

@ -40,8 +40,7 @@ public final class MultiFormatUPCEANReader extends AbstractOneDReader {
if (possibleFormats != null) {
if (possibleFormats.contains(BarcodeFormat.EAN_13)) {
readers.addElement(new EAN13Reader());
}
if (possibleFormats.contains(BarcodeFormat.UPC_A)) {
} else if (possibleFormats.contains(BarcodeFormat.UPC_A)) {
readers.addElement(new UPCAReader());
}
if (possibleFormats.contains(BarcodeFormat.EAN_8)) {
@ -53,7 +52,7 @@ public final class MultiFormatUPCEANReader extends AbstractOneDReader {
}
if (readers.isEmpty()) {
readers.addElement(new EAN13Reader());
readers.addElement(new UPCAReader());
// UPC-A is covered by EAN-13
readers.addElement(new EAN8Reader());
readers.addElement(new UPCEReader());
}
@ -71,16 +70,14 @@ public final class MultiFormatUPCEANReader extends AbstractOneDReader {
// Special case: a 12-digit code encoded in UPC-A is identical to a "0"
// followed by those 12 digits encoded as EAN-13. Each will recognize such a code,
// UPC-A as a 12-digit string and EAN-13 as a 13-digit string starting with "0".
// Individually these are correct.
// Individually these are correct and their readers will both read such a code
// and correctly call it EAN-13, or UPC-A, respectively.
//
// These cases can't be distinguished, so we defer to the UPC-A decoder and
// treat this case as a UPC-A code. But if we let the UPC-A decoder look at
// symbols first, it will recognize any EAN-13 code as a 12-digit string,
// which is wrong. So EAN-13 has to try first.
//
// Here is, therefore, where we implement this logic:
if (result.getBarcodeFormat().equals(BarcodeFormat.EAN_13) &&
result.getText().charAt(0) == '0') {
// In this case, if we've been looking for both types, we'd like to call it
// a UPC-A code. But for efficiency we only run the EAN-13 decoder to also read
// UPC-A. So we special case it here, and convert an EAN-13 result to a UPC-A
// result if appropriate.
if (result.getBarcodeFormat().equals(BarcodeFormat.EAN_13) && result.getText().charAt(0) == '0') {
return new Result(result.getText().substring(1), null, result.getResultPoints(), BarcodeFormat.UPC_A);
}
return result;

View file

@ -16,47 +16,47 @@
package com.google.zxing.oned;
import com.google.zxing.ReaderException;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.MonochromeBitmapSource;
import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.google.zxing.common.BitArray;
import java.util.Hashtable;
/**
* <p>Implements decoding of the UPC-A format.</p>
*
* @author dswitkin@google.com (Daniel Switkin)
* @author srowen@google.com (Sean Owen)
*/
public final class UPCAReader extends AbstractUPCEANReader {
public final class UPCAReader implements UPCEANReader {
protected int decodeMiddle(BitArray row, int[] startRange, StringBuffer resultString) throws ReaderException {
int middleStart = decodeDigits(row, startRange[1], resultString);
int[] middleRange = findGuardPattern(row, middleStart, true, MIDDLE_PATTERN);
return decodeDigits(row, middleRange[1], resultString);
private final UPCEANReader ean13Reader = new EAN13Reader();
public Result decodeRow(int rowNumber, BitArray row, int[] startGuardRange) throws ReaderException {
return maybeReturnResult(ean13Reader.decodeRow(rowNumber, row, startGuardRange));
}
/**
* @param row row of black/white values to decode
* @param start horizontal offset from which decoding starts
* @param result {@link StringBuffer} to append decoded digits to
* @return horizontal offset of first pixel after the six decoded digits
* @throws ReaderException if six digits could not be decoded from the row
*/
private static int decodeDigits(BitArray row, int start, StringBuffer result) throws ReaderException {
int[] counters = new int[4];
int end = row.getSize();
int rowOffset = start;
for (int x = 0; x < 6 && rowOffset < end; x++) {
int bestMatch = decodeDigit(row, counters, rowOffset, L_PATTERNS);
result.append((char) ('0' + bestMatch));
for (int i = 0; i < counters.length; i++) {
rowOffset += counters[i];
}
}
return rowOffset;
public Result decodeRow(int rowNumber, BitArray row, Hashtable hints) throws ReaderException {
return maybeReturnResult(ean13Reader.decodeRow(rowNumber, row, hints));
}
BarcodeFormat getBarcodeFormat() {
return BarcodeFormat.UPC_A;
public Result decode(MonochromeBitmapSource image) throws ReaderException {
return maybeReturnResult(ean13Reader.decode(image));
}
public Result decode(MonochromeBitmapSource image, Hashtable hints) throws ReaderException {
return maybeReturnResult(ean13Reader.decode(image, hints));
}
private static Result maybeReturnResult(Result result) throws ReaderException {
String text = result.getText();
if (text.charAt(0) == '0') {
return new Result(text.substring(1), null, result.getResultPoints(), BarcodeFormat.UPC_A);
} else {
throw new ReaderException("Found EAN-13 code but was not a UPC-A code");
}
}
}