Added BarcodeFormat to Result, indicating what type of barcode was detected. Added TRY_HARDER hint. Improved logicalness of results when reading UPC-A code / EAN-13 code starting with 0.

git-svn-id: https://zxing.googlecode.com/svn/trunk@230 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
srowen 2008-02-25 23:02:50 +00:00
parent 848609c0c5
commit 1f442884aa
30 changed files with 260 additions and 115 deletions

View file

@ -25,20 +25,38 @@ public final class BarcodeFormat {
// No, we can't use an enum here. J2ME doesn't support it. // No, we can't use an enum here. J2ME doesn't support it.
/** /** QR Code 2D barcode format. */
* 1D barcode format family. public static final BarcodeFormat QR_CODE = new BarcodeFormat("QR_CODE");
*/
public static final BarcodeFormat ONED = new BarcodeFormat();
/**
* QR Code 2D barcode format
*/
public static final BarcodeFormat QR_CODE = new BarcodeFormat();
/**
* DataMatrix 2D barcode format
*/
public static final BarcodeFormat DATAMATRIX = new BarcodeFormat();
private BarcodeFormat() { /** DataMatrix 2D barcode format. */
public static final BarcodeFormat DATAMATRIX = new BarcodeFormat("DATAMATRIX");
/** UPC-E 1D format. */
public static final BarcodeFormat UPC_E = new BarcodeFormat("UPC_E");
/** UPC-A 1D format. */
public static final BarcodeFormat UPC_A = new BarcodeFormat("UPC_A");
/** EAN-8 1D format. */
public static final BarcodeFormat EAN_8 = new BarcodeFormat("EAN_8");
/** EAN-13 1D format. */
public static final BarcodeFormat EAN_13 = new BarcodeFormat("EAN_13");
/** Code 128 1D format. */
public static final BarcodeFormat CODE_128 = new BarcodeFormat("CODE_128");
/** Code 39 1D format. */
public static final BarcodeFormat CODE_39 = new BarcodeFormat("CODE_39");
private final String name;
private BarcodeFormat(String name) {
this.name = name;
}
public String toString() {
return name;
} }
} }

View file

@ -28,20 +28,21 @@ public final class DecodeHintType {
// No, we can't use an enum here. J2ME doesn't support it. // No, we can't use an enum here. J2ME doesn't support it.
/** /** Unspecified, application-specific hint. */
* Unspecified, application-specific hint.
*/
public static final DecodeHintType OTHER = new DecodeHintType(); public static final DecodeHintType OTHER = new DecodeHintType();
/**
* Image is a pure monochrome image of a barcode. /** Image is a pure monochrome image of a barcode. */
*/
public static final DecodeHintType PURE_BARCODE = new DecodeHintType(); public static final DecodeHintType PURE_BARCODE = new DecodeHintType();
/** /**
* Image is known to be of one of a few possible formats. * Image is known to be of one of a few possible formats.
* Maps to {@link java.util.Collection} of {@link BarcodeFormat}s. * Maps to a collection of {@link BarcodeFormat}s.
*/ */
public static final DecodeHintType POSSIBLE_FORMATS = new DecodeHintType(); public static final DecodeHintType POSSIBLE_FORMATS = new DecodeHintType();
/** Spend more time to try to find a barcode; optimize for accuracy, not speed. */
public static final DecodeHintType TRY_HARDER = new DecodeHintType();
private DecodeHintType() { private DecodeHintType() {
} }

View file

@ -20,6 +20,7 @@ import com.google.zxing.oned.MultiFormatOneDReader;
import com.google.zxing.qrcode.QRCodeReader; import com.google.zxing.qrcode.QRCodeReader;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Vector;
/** /**
* <p>This implementation can detect barcodes in one of several formats within * <p>This implementation can detect barcodes in one of several formats within
@ -34,36 +35,34 @@ public final class MultiFormatReader implements Reader {
return decode(image, null); return decode(image, null);
} }
public Result decode(MonochromeBitmapSource image, Hashtable hints) public Result decode(MonochromeBitmapSource image, Hashtable hints) throws ReaderException {
throws ReaderException {
Hashtable possibleFormats = hints == null ? null : (Hashtable) hints.get(DecodeHintType.POSSIBLE_FORMATS); Hashtable possibleFormats = hints == null ? null : (Hashtable) hints.get(DecodeHintType.POSSIBLE_FORMATS);
Vector readers = new Vector();
boolean tryOneD; if (possibleFormats != null) {
boolean tryQR; if (possibleFormats.contains(BarcodeFormat.UPC_A) ||
if (possibleFormats == null) { possibleFormats.contains(BarcodeFormat.UPC_E) ||
tryOneD = true; possibleFormats.contains(BarcodeFormat.EAN_13) ||
tryQR = true; possibleFormats.contains(BarcodeFormat.EAN_8) ||
} else { possibleFormats.contains(BarcodeFormat.CODE_39) ||
tryOneD = possibleFormats.contains(BarcodeFormat.ONED); possibleFormats.contains(BarcodeFormat.CODE_128)) {
tryQR = possibleFormats.contains(BarcodeFormat.QR_CODE); readers.addElement(new MultiFormatOneDReader());
} }
if (!(tryOneD || tryQR)) { if (possibleFormats.contains(BarcodeFormat.QR_CODE)) {
throw new ReaderException("POSSIBLE_FORMATS specifies no supported types"); readers.addElement(new QRCodeReader());
}
}
if (readers.isEmpty()) {
readers.addElement(new MultiFormatOneDReader());
readers.addElement(new QRCodeReader());
} }
// UPC is much faster to decode, so try it first. for (int i = 0; i < readers.size(); i++) {
if (tryOneD) { Reader reader = (Reader) readers.elementAt(i);
try { try {
return new MultiFormatOneDReader().decode(image, hints); return reader.decode(image, hints);
} catch (ReaderException re) {
}
}
// Then fall through to QR codes.
if (tryQR) {
try {
return new QRCodeReader().decode(image, hints);
} catch (ReaderException re) { } catch (ReaderException re) {
// continue
} }
} }

View file

@ -25,10 +25,12 @@ public final class Result {
private final String text; private final String text;
private final ResultPoint[] resultPoints; private final ResultPoint[] resultPoints;
private final BarcodeFormat format;
public Result(String text, ResultPoint[] resultPoints) { public Result(String text, ResultPoint[] resultPoints, BarcodeFormat format) {
this.text = text; this.text = text;
this.resultPoints = resultPoints; this.resultPoints = resultPoints;
this.format = format;
} }
/** /**
@ -47,4 +49,11 @@ public final class Result {
return resultPoints; return resultPoints;
} }
/**
* @return {@link BarcodeFormat} representing the format of the barcode that was recognized and decoded
*/
public BarcodeFormat getBarcodeFormat() {
return format;
}
} }

View file

@ -17,6 +17,7 @@
package com.google.zxing.oned; package com.google.zxing.oned;
import com.google.zxing.BlackPointEstimationMethod; import com.google.zxing.BlackPointEstimationMethod;
import com.google.zxing.DecodeHintType;
import com.google.zxing.MonochromeBitmapSource; import com.google.zxing.MonochromeBitmapSource;
import com.google.zxing.ReaderException; import com.google.zxing.ReaderException;
import com.google.zxing.Result; import com.google.zxing.Result;
@ -65,15 +66,16 @@ public abstract class AbstractOneDReader implements OneDReader {
image.getBlackRow(rowNumber, row, 0, width); image.getBlackRow(rowNumber, row, 0, width);
try { try {
return decodeRow(rowNumber, row); return decodeRow(rowNumber, row, hints);
} catch (ReaderException re) { } catch (ReaderException re) {
// TODO re-enable this in a "try harder" mode? if (hints != null && hints.contains(DecodeHintType.TRY_HARDER)) {
//row.reverse(); // try scanning the row backwards row.reverse(); // try scanning the row backwards
//try { try {
// return decodeRow(rowNumber, row); return decodeRow(rowNumber, row, hints);
//} catch (ReaderException re2) { } catch (ReaderException re2) {
// continue // continue
//} }
}
} }
} }
@ -82,7 +84,8 @@ public abstract class AbstractOneDReader implements OneDReader {
} }
protected static void recordPattern(BitArray row, int start, int[] counters) throws ReaderException { protected static void recordPattern(BitArray row, int start, int[] counters) throws ReaderException {
for (int i = 0; i < counters.length; i++) { int numCounters = counters.length;
for (int i = 0; i < numCounters; i++) {
counters[i] = 0; counters[i] = 0;
} }
int end = row.getSize(); int end = row.getSize();
@ -98,7 +101,7 @@ public abstract class AbstractOneDReader implements OneDReader {
counters[counterPosition]++; counters[counterPosition]++;
} else { } else {
counterPosition++; counterPosition++;
if (counterPosition == counters.length) { if (counterPosition == numCounters) {
break; break;
} else { } else {
counters[counterPosition] = 1; counters[counterPosition] = 1;
@ -109,7 +112,7 @@ public abstract class AbstractOneDReader implements OneDReader {
} }
// If we read fully the last section of pixels and filled up our counters -- or filled // If we read fully the last section of pixels and filled up our counters -- or filled
// the last counter but ran off the side of the image, OK. Otherwise, a problem. // the last counter but ran off the side of the image, OK. Otherwise, a problem.
if (!(counterPosition == counters.length || (counterPosition == counters.length - 1 && i == end))) { if (!(counterPosition == numCounters || (counterPosition == numCounters - 1 && i == end))) {
throw new ReaderException("Couldn't fully read a pattern"); throw new ReaderException("Couldn't fully read a pattern");
} }
} }

View file

@ -16,12 +16,15 @@
package com.google.zxing.oned; package com.google.zxing.oned;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.ReaderException; import com.google.zxing.ReaderException;
import com.google.zxing.Result; import com.google.zxing.Result;
import com.google.zxing.ResultPoint; import com.google.zxing.ResultPoint;
import com.google.zxing.common.BitArray; import com.google.zxing.common.BitArray;
import com.google.zxing.common.GenericResultPoint; import com.google.zxing.common.GenericResultPoint;
import java.util.Hashtable;
/** /**
* <p>Encapsulates functionality and implementation that is common to UPC and EAN families * <p>Encapsulates functionality and implementation that is common to UPC and EAN families
* of one-dimensional barcodes.</p> * of one-dimensional barcodes.</p>
@ -95,7 +98,7 @@ public abstract class AbstractUPCEANReader extends AbstractOneDReader implements
return startRange; return startRange;
} }
public final Result decodeRow(int rowNumber, BitArray row) throws ReaderException { public final Result decodeRow(int rowNumber, BitArray row, Hashtable hints) throws ReaderException {
return decodeRow(rowNumber, row, findStartGuardPattern(row)); return decodeRow(rowNumber, row, findStartGuardPattern(row));
} }
@ -118,11 +121,16 @@ public abstract class AbstractUPCEANReader extends AbstractOneDReader implements
throw new ReaderException("Checksum failed"); throw new ReaderException("Checksum failed");
} }
return new Result(resultString, new ResultPoint[]{ return new Result(
resultString,
new ResultPoint[]{
new GenericResultPoint((float) (startGuardRange[1] - startGuardRange[0]) / 2.0f, (float) rowNumber), new GenericResultPoint((float) (startGuardRange[1] - startGuardRange[0]) / 2.0f, (float) rowNumber),
new GenericResultPoint((float) (endRange[1] - endRange[0]) / 2.0f, (float) rowNumber)}); new GenericResultPoint((float) (endRange[1] - endRange[0]) / 2.0f, (float) rowNumber)},
getBarcodeFormat());
} }
abstract BarcodeFormat getBarcodeFormat();
/** /**
* Computes the UPC/EAN checksum on a string of digits, and reports * Computes the UPC/EAN checksum on a string of digits, and reports
* whether the checksum is correct or not. * whether the checksum is correct or not.

View file

@ -16,12 +16,15 @@
package com.google.zxing.oned; package com.google.zxing.oned;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.ReaderException; import com.google.zxing.ReaderException;
import com.google.zxing.Result; import com.google.zxing.Result;
import com.google.zxing.ResultPoint; import com.google.zxing.ResultPoint;
import com.google.zxing.common.BitArray; import com.google.zxing.common.BitArray;
import com.google.zxing.common.GenericResultPoint; import com.google.zxing.common.GenericResultPoint;
import java.util.Hashtable;
/** /**
* <p>Decodes Code 128 barcodes.</p> * <p>Decodes Code 128 barcodes.</p>
* *
@ -229,7 +232,7 @@ public final class Code128Reader extends AbstractOneDReader {
} }
} }
public Result decodeRow(final int rowNumber, final BitArray row) throws ReaderException { public Result decodeRow(int rowNumber, BitArray row, Hashtable hints) throws ReaderException {
int[] startPatternInfo = findStartPattern(row); int[] startPatternInfo = findStartPattern(row);
int startCode = startPatternInfo[2]; int startCode = startPatternInfo[2];
@ -402,11 +405,12 @@ public final class Code128Reader extends AbstractOneDReader {
} }
String resultString = result.toString(); String resultString = result.toString();
return new Result(resultString, return new Result(
new ResultPoint[]{new GenericResultPoint((float) (startPatternInfo[1] - startPatternInfo[0]) / 2.0f, resultString,
(float) rowNumber), new ResultPoint[]{
new GenericResultPoint((float) (nextStart - lastStart) / 2.0f, new GenericResultPoint((float) (startPatternInfo[1] - startPatternInfo[0]) / 2.0f, (float) rowNumber),
(float) rowNumber)}); new GenericResultPoint((float) (nextStart - lastStart) / 2.0f, (float) rowNumber)},
BarcodeFormat.CODE_128);
} }

View file

@ -16,12 +16,15 @@
package com.google.zxing.oned; package com.google.zxing.oned;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.ReaderException; import com.google.zxing.ReaderException;
import com.google.zxing.Result; import com.google.zxing.Result;
import com.google.zxing.ResultPoint; import com.google.zxing.ResultPoint;
import com.google.zxing.common.BitArray; import com.google.zxing.common.BitArray;
import com.google.zxing.common.GenericResultPoint; import com.google.zxing.common.GenericResultPoint;
import java.util.Hashtable;
/** /**
* <p>Decodes Code 39 barcodes. This does not supported "Full ASCII Code 39" yet.</p> * <p>Decodes Code 39 barcodes. This does not supported "Full ASCII Code 39" yet.</p>
* *
@ -86,7 +89,7 @@ public final class Code39Reader extends AbstractOneDReader {
this.extendedMode = extendedMode; this.extendedMode = extendedMode;
} }
public Result decodeRow(final int rowNumber, final BitArray row) throws ReaderException { public Result decodeRow(int rowNumber, BitArray row, Hashtable hints) throws ReaderException {
int[] start = findAsteriskPattern(row); int[] start = findAsteriskPattern(row);
@ -135,9 +138,12 @@ public final class Code39Reader extends AbstractOneDReader {
if (extendedMode) { if (extendedMode) {
resultString = decodeExtended(resultString); resultString = decodeExtended(resultString);
} }
return new Result(resultString, return new Result(
new ResultPoint[]{new GenericResultPoint((float) (start[1] - start[0]) / 2.0f, (float) rowNumber), resultString,
new GenericResultPoint((float) (nextStart - lastStart) / 2.0f, (float) rowNumber)}); new ResultPoint[]{
new GenericResultPoint((float) (start[1] - start[0]) / 2.0f, (float) rowNumber),
new GenericResultPoint((float) (nextStart - lastStart) / 2.0f, (float) rowNumber)},
BarcodeFormat.CODE_39);
} }

View file

@ -17,6 +17,7 @@
package com.google.zxing.oned; package com.google.zxing.oned;
import com.google.zxing.ReaderException; import com.google.zxing.ReaderException;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.common.BitArray; import com.google.zxing.common.BitArray;
/** /**
@ -96,6 +97,10 @@ public final class EAN13Reader extends AbstractUPCEANReader {
return rowOffset; return rowOffset;
} }
BarcodeFormat getBarcodeFormat() {
return BarcodeFormat.EAN_13;
}
/** /**
* Based on pattern of odd-even ('L' and 'G') patterns used to encoded the explicitly-encoded digits * Based on pattern of odd-even ('L' and 'G') patterns used to encoded the explicitly-encoded digits
* in a barcode, determines the implicitly encoded first digit and adds it to the result string. * in a barcode, determines the implicitly encoded first digit and adds it to the result string.
@ -108,12 +113,7 @@ public final class EAN13Reader extends AbstractUPCEANReader {
private static void determineFirstDigit(StringBuffer resultString, int lgPatternFound) throws ReaderException { private static void determineFirstDigit(StringBuffer resultString, int lgPatternFound) throws ReaderException {
for (int d = 0; d < 10; d++) { for (int d = 0; d < 10; d++) {
if (lgPatternFound == FIRST_DIGIT_ENCODINGS[d]) { if (lgPatternFound == FIRST_DIGIT_ENCODINGS[d]) {
// OK, if the first digit is a 0, then this is effectively also a UPC-A code.
// I think it's best (?) to go ahead and treat it as if it had matched as UPC-A, and return a result
// *without* the leading 0
if (d != 0) {
resultString.insert(0, (char) ('0' + d)); resultString.insert(0, (char) ('0' + d));
}
return; return;
} }
} }

View file

@ -17,6 +17,7 @@
package com.google.zxing.oned; package com.google.zxing.oned;
import com.google.zxing.ReaderException; import com.google.zxing.ReaderException;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.common.BitArray; import com.google.zxing.common.BitArray;
/** /**
@ -54,4 +55,8 @@ public final class EAN8Reader extends AbstractUPCEANReader {
return rowOffset; return rowOffset;
} }
BarcodeFormat getBarcodeFormat() {
return BarcodeFormat.EAN_8;
}
} }

View file

@ -16,30 +16,55 @@
package com.google.zxing.oned; package com.google.zxing.oned;
import com.google.zxing.DecodeHintType;
import com.google.zxing.ReaderException; import com.google.zxing.ReaderException;
import com.google.zxing.Result; import com.google.zxing.Result;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.common.BitArray; import com.google.zxing.common.BitArray;
import java.util.Hashtable;
import java.util.Vector;
/** /**
* @author dswitkin@google.com (Daniel Switkin) * @author dswitkin@google.com (Daniel Switkin)
* @author srowen@google.com (Sean Owen) * @author srowen@google.com (Sean Owen)
*/ */
public final class MultiFormatOneDReader extends AbstractOneDReader { public final class MultiFormatOneDReader extends AbstractOneDReader {
private final OneDReader[] readers = new OneDReader[]{ public Result decodeRow(int rowNumber, BitArray row, Hashtable hints) throws ReaderException {
new MultiFormatUPCEANReader(), new Code39Reader(), new Code128Reader()
};
public Result decodeRow(int rowNumber, BitArray row) throws ReaderException { Hashtable possibleFormats = hints == null ? null : (Hashtable) hints.get(DecodeHintType.POSSIBLE_FORMATS);
ReaderException saved = null; Vector readers = new Vector();
for (int i = 0; i < readers.length; i++) { if (possibleFormats != null) {
if (possibleFormats.contains(BarcodeFormat.EAN_13) ||
possibleFormats.contains(BarcodeFormat.UPC_A) ||
possibleFormats.contains(BarcodeFormat.EAN_8) ||
possibleFormats.contains(BarcodeFormat.UPC_E)) {
readers.addElement(new MultiFormatUPCEANReader());
}
if (possibleFormats.contains(BarcodeFormat.CODE_39)) {
readers.addElement(new Code39Reader());
}
if (possibleFormats.contains(BarcodeFormat.CODE_128)) {
readers.addElement(new Code128Reader());
}
}
if (readers.isEmpty()) {
readers.addElement(new MultiFormatUPCEANReader());
readers.addElement(new Code39Reader());
readers.addElement(new Code128Reader());
}
for (int i = 0; i < readers.size(); i++) {
OneDReader reader = (OneDReader) readers.elementAt(i);
try { try {
return readers[i].decodeRow(rowNumber, row); return reader.decodeRow(rowNumber, row, hints);
} catch (ReaderException re) { } catch (ReaderException re) {
saved = re; // continue
} }
} }
throw saved;
throw new ReaderException("No barcode was detected in this image.");
} }
} }

View file

@ -16,10 +16,15 @@
package com.google.zxing.oned; package com.google.zxing.oned;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.DecodeHintType;
import com.google.zxing.ReaderException; import com.google.zxing.ReaderException;
import com.google.zxing.Result; import com.google.zxing.Result;
import com.google.zxing.common.BitArray; import com.google.zxing.common.BitArray;
import java.util.Hashtable;
import java.util.Vector;
/** /**
* <p>A reader that can read all available UPC/EAN formats. If a caller wants to try to * <p>A reader that can read all available UPC/EAN formats. If a caller wants to try to
* read all such formats, it is most efficent to use this implementation rather than invoke * read all such formats, it is most efficent to use this implementation rather than invoke
@ -29,26 +34,59 @@ import com.google.zxing.common.BitArray;
*/ */
public final class MultiFormatUPCEANReader extends AbstractOneDReader { public final class MultiFormatUPCEANReader extends AbstractOneDReader {
/** public Result decodeRow(int rowNumber, BitArray row, Hashtable hints) throws ReaderException {
* Reader implementations to which this implementation delegates, in the order Hashtable possibleFormats = hints == null ? null : (Hashtable) hints.get(DecodeHintType.POSSIBLE_FORMATS);
* they will be attempted. Order is important. Vector readers = new Vector();
*/ if (possibleFormats != null) {
private final UPCEANReader[] readers = new UPCEANReader[]{ if (possibleFormats.contains(BarcodeFormat.EAN_13)) {
new EAN13Reader(), new UPCAReader(), new EAN8Reader(), new UPCEReader() readers.addElement(new EAN13Reader());
}; }
if (possibleFormats.contains(BarcodeFormat.UPC_A)) {
readers.addElement(new UPCAReader());
}
if (possibleFormats.contains(BarcodeFormat.EAN_8)) {
readers.addElement(new EAN8Reader());
}
if (possibleFormats.contains(BarcodeFormat.UPC_E)) {
readers.addElement(new UPCEReader());
}
}
if (readers.isEmpty()) {
readers.addElement(new EAN13Reader());
readers.addElement(new UPCAReader());
readers.addElement(new EAN8Reader());
readers.addElement(new UPCEReader());
}
public Result decodeRow(int rowNumber, BitArray row) throws ReaderException {
// Compute this location once and reuse it on multiple implementations // Compute this location once and reuse it on multiple implementations
int[] startGuardPattern = AbstractUPCEANReader.findStartGuardPattern(row); int[] startGuardPattern = AbstractUPCEANReader.findStartGuardPattern(row);
ReaderException saved = null; for (int i = 0; i < readers.size(); i++) {
for (int i = 0; i < readers.length; i++) { UPCEANReader reader = (UPCEANReader) readers.elementAt(i);
Result result;
try { try {
return readers[i].decodeRow(rowNumber, row, startGuardPattern); result = reader.decodeRow(rowNumber, row, startGuardPattern);
} catch (ReaderException re) { } catch (ReaderException re) {
saved = re; continue;
} }
// 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.
//
// 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') {
return new Result(result.getText().substring(1), result.getResultPoints(), BarcodeFormat.UPC_A);
} }
throw saved; return result;
}
throw new ReaderException("No barcode was detected in this image.");
} }
} }

View file

@ -21,6 +21,8 @@ import com.google.zxing.ReaderException;
import com.google.zxing.Result; import com.google.zxing.Result;
import com.google.zxing.common.BitArray; import com.google.zxing.common.BitArray;
import java.util.Hashtable;
/** /**
* <p>{@link Reader}s which also implement this interface read one-dimensional barcode * <p>{@link Reader}s which also implement this interface read one-dimensional barcode
* formats, and expose additional functionality that is specific to this type of barcode.</p> * formats, and expose additional functionality that is specific to this type of barcode.</p>
@ -35,9 +37,10 @@ public interface OneDReader extends Reader {
* *
* @param rowNumber row number from top of the row * @param rowNumber row number from top of the row
* @param row the black/white pixel data of the row * @param row the black/white pixel data of the row
* @param hints decode hints
* @return {@link Result} containing encoded string and start/end of barcode * @return {@link Result} containing encoded string and start/end of barcode
* @throws ReaderException if an error occurs or barcode cannot be found * @throws ReaderException if an error occurs or barcode cannot be found
*/ */
Result decodeRow(int rowNumber, BitArray row) throws ReaderException; Result decodeRow(int rowNumber, BitArray row, Hashtable hints) throws ReaderException;
} }

View file

@ -17,6 +17,7 @@
package com.google.zxing.oned; package com.google.zxing.oned;
import com.google.zxing.ReaderException; import com.google.zxing.ReaderException;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.common.BitArray; import com.google.zxing.common.BitArray;
/** /**
@ -54,4 +55,8 @@ public final class UPCAReader extends AbstractUPCEANReader {
return rowOffset; return rowOffset;
} }
BarcodeFormat getBarcodeFormat() {
return BarcodeFormat.UPC_A;
}
} }

View file

@ -17,6 +17,7 @@
package com.google.zxing.oned; package com.google.zxing.oned;
import com.google.zxing.ReaderException; import com.google.zxing.ReaderException;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.common.BitArray; import com.google.zxing.common.BitArray;
/** /**
@ -92,6 +93,10 @@ public final class UPCEReader extends AbstractUPCEANReader {
throw new ReaderException("Unable to determine number system and check digit"); throw new ReaderException("Unable to determine number system and check digit");
} }
BarcodeFormat getBarcodeFormat() {
return BarcodeFormat.UPC_E;
}
/** /**
* Expands a UPC-E value back into its full, equivalent UPC-A code value. * Expands a UPC-E value back into its full, equivalent UPC-A code value.
* *

View file

@ -16,6 +16,7 @@
package com.google.zxing.qrcode; package com.google.zxing.qrcode;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.DecodeHintType; import com.google.zxing.DecodeHintType;
import com.google.zxing.MonochromeBitmapSource; import com.google.zxing.MonochromeBitmapSource;
import com.google.zxing.Reader; import com.google.zxing.Reader;
@ -63,7 +64,7 @@ public final class QRCodeReader implements Reader {
text = decoder.decode(result.getBits()); text = decoder.decode(result.getBits());
points = result.getPoints(); points = result.getPoints();
} }
return new Result(text, points); return new Result(text, points, BarcodeFormat.QR_CODE);
} }
/** /**

View file

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 65 KiB

View file

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 56 KiB

View file

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 94 KiB

View file

@ -16,6 +16,7 @@
package com.google.zxing.common; package com.google.zxing.common;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.MonochromeBitmapSource; import com.google.zxing.MonochromeBitmapSource;
import com.google.zxing.Reader; import com.google.zxing.Reader;
import com.google.zxing.ReaderException; import com.google.zxing.ReaderException;
@ -50,11 +51,16 @@ public abstract class AbstractBlackBoxTestCase extends TestCase {
private final File testBase; private final File testBase;
private final Reader barcodeReader; private final Reader barcodeReader;
private final double passPercent; private final double passPercent;
private final BarcodeFormat expectedFormat;
protected AbstractBlackBoxTestCase(File testBase, Reader barcodeReader, double passPercent) { protected AbstractBlackBoxTestCase(File testBase,
Reader barcodeReader,
double passPercent,
BarcodeFormat expectedFormat) {
this.testBase = testBase; this.testBase = testBase;
this.barcodeReader = barcodeReader; this.barcodeReader = barcodeReader;
this.passPercent = passPercent; this.passPercent = passPercent;
this.expectedFormat = expectedFormat;
} }
public void testBlackBox() throws IOException { public void testBlackBox() throws IOException {
@ -82,6 +88,8 @@ public abstract class AbstractBlackBoxTestCase extends TestCase {
continue; continue;
} }
assertEquals(expectedFormat, result.getBarcodeFormat());
String testImageFileName = testImage.getName(); String testImageFileName = testImage.getName();
File expectedTextFile = File expectedTextFile =
new File(testBase, testImageFileName.substring(0, testImageFileName.indexOf('.')) + ".txt"); new File(testBase, testImageFileName.substring(0, testImageFileName.indexOf('.')) + ".txt");

View file

@ -16,6 +16,7 @@
package com.google.zxing.oned; package com.google.zxing.oned;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.MultiFormatReader; import com.google.zxing.MultiFormatReader;
import com.google.zxing.common.AbstractBlackBoxTestCase; import com.google.zxing.common.AbstractBlackBoxTestCase;
@ -27,7 +28,7 @@ import java.io.File;
public final class Code128BlackBox1TestCase extends AbstractBlackBoxTestCase { public final class Code128BlackBox1TestCase extends AbstractBlackBoxTestCase {
public Code128BlackBox1TestCase() { public Code128BlackBox1TestCase() {
super(new File("test/data/blackbox/code128-1"), new MultiFormatReader(), 1.0); super(new File("test/data/blackbox/code128-1"), new MultiFormatReader(), 1.0, BarcodeFormat.CODE_128);
} }
} }

View file

@ -17,6 +17,7 @@
package com.google.zxing.oned; package com.google.zxing.oned;
import com.google.zxing.MultiFormatReader; import com.google.zxing.MultiFormatReader;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.common.AbstractBlackBoxTestCase; import com.google.zxing.common.AbstractBlackBoxTestCase;
import java.io.File; import java.io.File;
@ -27,7 +28,7 @@ import java.io.File;
public final class Code39BlackBox1TestCase extends AbstractBlackBoxTestCase { public final class Code39BlackBox1TestCase extends AbstractBlackBoxTestCase {
public Code39BlackBox1TestCase() { public Code39BlackBox1TestCase() {
super(new File("test/data/blackbox/code39-1"), new MultiFormatReader(), 1.0); super(new File("test/data/blackbox/code39-1"), new MultiFormatReader(), 1.0, BarcodeFormat.CODE_39);
} }
} }

View file

@ -17,6 +17,7 @@
package com.google.zxing.oned; package com.google.zxing.oned;
import com.google.zxing.common.AbstractBlackBoxTestCase; import com.google.zxing.common.AbstractBlackBoxTestCase;
import com.google.zxing.BarcodeFormat;
import java.io.File; import java.io.File;
@ -26,7 +27,7 @@ import java.io.File;
public final class Code39ExtendedBlackBox2TestCase extends AbstractBlackBoxTestCase { public final class Code39ExtendedBlackBox2TestCase extends AbstractBlackBoxTestCase {
public Code39ExtendedBlackBox2TestCase() { public Code39ExtendedBlackBox2TestCase() {
super(new File("test/data/blackbox/code39-2"), new Code39Reader(false, true), 1.0); super(new File("test/data/blackbox/code39-2"), new Code39Reader(false, true), 1.0, BarcodeFormat.CODE_39);
} }
} }

View file

@ -17,6 +17,7 @@
package com.google.zxing.oned; package com.google.zxing.oned;
import com.google.zxing.MultiFormatReader; import com.google.zxing.MultiFormatReader;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.common.AbstractBlackBoxTestCase; import com.google.zxing.common.AbstractBlackBoxTestCase;
import java.io.File; import java.io.File;
@ -27,7 +28,7 @@ import java.io.File;
public final class EAN13BlackBox1TestCase extends AbstractBlackBoxTestCase { public final class EAN13BlackBox1TestCase extends AbstractBlackBoxTestCase {
public EAN13BlackBox1TestCase() { public EAN13BlackBox1TestCase() {
super(new File("test/data/blackbox/ean13-1"), new MultiFormatReader(), 0.66); super(new File("test/data/blackbox/ean13-1"), new MultiFormatReader(), 0.66, BarcodeFormat.EAN_13);
} }
} }

View file

@ -17,6 +17,7 @@
package com.google.zxing.oned; package com.google.zxing.oned;
import com.google.zxing.MultiFormatReader; import com.google.zxing.MultiFormatReader;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.common.AbstractBlackBoxTestCase; import com.google.zxing.common.AbstractBlackBoxTestCase;
import java.io.File; import java.io.File;
@ -27,7 +28,7 @@ import java.io.File;
public final class UPCABlackBox1TestCase extends AbstractBlackBoxTestCase { public final class UPCABlackBox1TestCase extends AbstractBlackBoxTestCase {
public UPCABlackBox1TestCase() { public UPCABlackBox1TestCase() {
super(new File("test/data/blackbox/upca-1"), new MultiFormatReader(), 0.5); super(new File("test/data/blackbox/upca-1"), new MultiFormatReader(), 0.5, BarcodeFormat.UPC_A);
} }
} }

View file

@ -17,6 +17,7 @@
package com.google.zxing.qrcode; package com.google.zxing.qrcode;
import com.google.zxing.MultiFormatReader; import com.google.zxing.MultiFormatReader;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.common.AbstractBlackBoxTestCase; import com.google.zxing.common.AbstractBlackBoxTestCase;
import java.io.File; import java.io.File;
@ -27,7 +28,7 @@ import java.io.File;
public final class QRCodeBlackBox1TestCase extends AbstractBlackBoxTestCase { public final class QRCodeBlackBox1TestCase extends AbstractBlackBoxTestCase {
public QRCodeBlackBox1TestCase() { public QRCodeBlackBox1TestCase() {
super(new File("test/data/blackbox/qrcode-1"), new MultiFormatReader(), 0.5); super(new File("test/data/blackbox/qrcode-1"), new MultiFormatReader(), 0.5, BarcodeFormat.QR_CODE);
} }
} }

View file

@ -17,6 +17,7 @@
package com.google.zxing.qrcode; package com.google.zxing.qrcode;
import com.google.zxing.MultiFormatReader; import com.google.zxing.MultiFormatReader;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.common.AbstractBlackBoxTestCase; import com.google.zxing.common.AbstractBlackBoxTestCase;
import java.io.File; import java.io.File;
@ -27,7 +28,7 @@ import java.io.File;
public final class QRCodeBlackBox2TestCase extends AbstractBlackBoxTestCase { public final class QRCodeBlackBox2TestCase extends AbstractBlackBoxTestCase {
public QRCodeBlackBox2TestCase() { public QRCodeBlackBox2TestCase() {
super(new File("test/data/blackbox/qrcode-2"), new MultiFormatReader(), 1.0); super(new File("test/data/blackbox/qrcode-2"), new MultiFormatReader(), 1.0, BarcodeFormat.QR_CODE);
} }
} }