package com.google.zxing.oned;
import com.google.zxing.BarcodeFormat;
+import com.google.zxing.DecodeHintType;
import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.google.zxing.ResultPoint;
+import com.google.zxing.ResultPointCallback;
import com.google.zxing.common.BitArray;
import java.util.Hashtable;
*/
public abstract class AbstractUPCEANReader extends AbstractOneDReader implements UPCEANReader {
+ // These two values are critical for determining how permissive the decoding will be.
+ // We've arrived at these values through a lot of trial and error. Setting them any higher
+ // lets false positives creep in quickly.
private static final int MAX_AVG_VARIANCE = (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.42f);
private static final int MAX_INDIVIDUAL_VARIANCE = (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.7f);
startRange = findGuardPattern(row, nextStart, false, START_END_PATTERN);
int start = startRange[0];
nextStart = startRange[1];
- // Make sure there is a quiet zone at least as big as the start pattern before the barcode. If
- // this check would run off the left edge of the image, do not accept this barcode, as it is
- // very likely to be a false positive.
+ // Make sure there is a quiet zone at least as big as the start pattern before the barcode.
+ // If this check would run off the left edge of the image, do not accept this barcode,
+ // as it is very likely to be a false positive.
int quietStart = start - (nextStart - start);
if (quietStart >= 0) {
foundStart = row.isRange(quietStart, start, false);
return startRange;
}
- public final Result decodeRow(int rowNumber, BitArray row, Hashtable hints) throws ReaderException {
- return decodeRow(rowNumber, row, findStartGuardPattern(row));
+ public final Result decodeRow(int rowNumber, BitArray row, Hashtable hints)
+ throws ReaderException {
+ return decodeRow(rowNumber, row, findStartGuardPattern(row), hints);
}
- public final Result decodeRow(int rowNumber, BitArray row, int[] startGuardRange) throws ReaderException {
+ public final Result decodeRow(int rowNumber, BitArray row, int[] startGuardRange, Hashtable hints)
+ throws ReaderException {
+
+ ResultPointCallback resultPointCallback = hints == null ? null :
+ (ResultPointCallback) hints.get(DecodeHintType.NEED_RESULT_POINT_CALLBACK);
+
+ if (resultPointCallback != null) {
+ resultPointCallback.foundPossibleResultPoint(new ResultPoint(
+ (startGuardRange[0] + startGuardRange[1]) / 2.0f, rowNumber
+ ));
+ }
+
StringBuffer result = decodeRowStringBuffer;
result.setLength(0);
int endStart = decodeMiddle(row, startGuardRange, result);
+
+ if (resultPointCallback != null) {
+ resultPointCallback.foundPossibleResultPoint(new ResultPoint(
+ endStart, rowNumber
+ ));
+ }
+
int[] endRange = decodeEnd(row, endStart);
+ if (resultPointCallback != null) {
+ resultPointCallback.foundPossibleResultPoint(new ResultPoint(
+ (endRange[0] + endRange[1]) / 2.0f, rowNumber
+ ));
+ }
+
+
// Make sure there is a quiet zone at least as big as the end pattern after the barcode. The
// spec might want more whitespace, but in practice this is the maximum we can count on.
int end = endRange[1];
abstract BarcodeFormat getBarcodeFormat();
/**
- * @return {@link #checkStandardUPCEANChecksum(String)}
+ * @return {@link #checkStandardUPCEANChecksum(String)}
*/
boolean checkChecksum(String s) throws ReaderException {
return checkStandardUPCEANChecksum(s);
* @return true iff string of digits passes the UPC/EAN checksum algorithm
* @throws ReaderException if the string does not contain only digits
*/
- public static boolean checkStandardUPCEANChecksum(String s) throws ReaderException {
+ private static boolean checkStandardUPCEANChecksum(String s) throws ReaderException {
int length = s.length();
if (length == 0) {
return false;
}
/**
- * Subclasses override this to decode the portion of a barcode between the start and end guard patterns.
+ * Subclasses override this to decode the portion of a barcode between the start
+ * and end guard patterns.
*
* @param row row of black/white values to search
* @param startRange start/end offset of start guard pattern
counterPosition++;
}
counters[counterPosition] = 1;
- isWhite ^= true; // isWhite = !isWhite;
+ isWhite = !isWhite;
}
}
throw ReaderException.getInstance();