/*
- * Copyright 2008 Google Inc.
+ * Copyright 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
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 support "Full ASCII Code 39" yet.</p>
*
* @author srowen@google.com (Sean Owen)
*/
* It will not decoded "extended Code 39" sequences.
*
* @param usingCheckDigit if true, treat the last data character as a check digit, not
- * data, and verify that the checksum passes
+ * data, and verify that the checksum passes.
*/
public Code39Reader(boolean usingCheckDigit) {
this.usingCheckDigit = usingCheckDigit;
* the full ASCII character set.
*
* @param usingCheckDigit if true, treat the last data character as a check digit, not
- * data, and verify that the checksum passes
- * @param extendedMode if true, willa tetmpt to decode extended Code 39 sequences in the
- * text
+ * data, and verify that the checksum passes.
+ * @param extendedMode if true, will attempt to decode extended Code 39 sequences in the
+ * text.
*/
public Code39Reader(boolean usingCheckDigit, boolean extendedMode) {
this.usingCheckDigit = usingCheckDigit;
public Result decodeRow(int rowNumber, BitArray row, Hashtable hints) throws ReaderException {
int[] start = findAsteriskPattern(row);
-
int nextStart = start[1];
-
int end = row.getSize();
// Read off white space
} while (decodedChar != '*');
result.deleteCharAt(result.length() - 1); // remove asterisk
+ // Look for whitespace after pattern:
+ int lastPatternSize = 0;
+ for (int i = 0; i < counters.length; i++) {
+ lastPatternSize += counters[i];
+ }
+ int whiteSpaceAfterEnd = nextStart - lastStart - lastPatternSize;
+ // If 50% of last pattern size, following last pattern, is not whitespace, fail
+ // (but if it's whitespace to the very end of the image, that's OK)
+ if (nextStart != end && whiteSpaceAfterEnd / 2 < lastPatternSize) {
+ throw new ReaderException("Pattern not followed by whitespace");
+ }
+
if (usingCheckDigit) {
int max = result.length() - 1;
int total = 0;
if (extendedMode) {
resultString = decodeExtended(resultString);
}
+
+ if (resultString.length() == 0) {
+ // Almost surely a false positive
+ throw new ReaderException("Empty barcode found; assuming a false positive");
+ }
+
+ float left = (float) (start[1] + start[0]) / 2.0f;
+ float right = (float) (nextStart + lastStart) / 2.0f;
return new Result(
resultString,
null,
new ResultPoint[]{
- new GenericResultPoint((float) (start[1] - start[0]) / 2.0f, (float) rowNumber),
- new GenericResultPoint((float) (nextStart - lastStart) / 2.0f, (float) rowNumber)},
+ new GenericResultPoint(left, (float) rowNumber),
+ new GenericResultPoint(right, (float) rowNumber)},
BarcodeFormat.CODE_39);
}
if (counterPosition == patternLength - 1) {
try {
if (toNarrowWidePattern(counters) == ASTERISK_ENCODING) {
- return new int[]{patternStart, i};
+ // Look for whitespace before start pattern, >= 50% of width of start pattern
+ if (row.isRange(Math.max(0, patternStart - (i - patternStart) / 2), patternStart, false)) {
+ return new int[]{patternStart, i};
+ }
}
} catch (ReaderException re) {
// no match, continue
}
maxNarrowCounter = minCounter;
wideCounters = 0;
+ int totalWideCountersWidth = 0;
int pattern = 0;
for (int i = 0; i < numCounters; i++) {
+ int counter = counters[i];
if (counters[i] > maxNarrowCounter) {
pattern |= 1 << (numCounters - 1 - i);
wideCounters++;
+ totalWideCountersWidth += counter;
}
}
if (wideCounters == 3) {
+ // Found 3 wide counters, but are they close enough in width?
+ // We can perform a cheap, conservative check to see if any individual
+ // counter is more than 1.5 times the average:
+ for (int i = 0; i < numCounters && wideCounters > 0; i++) {
+ int counter = counters[i];
+ if (counters[i] > maxNarrowCounter) {
+ wideCounters--;
+ // totalWideCountersWidth = 3 * average, so this checks if counter >= 3/2 * average
+ if ((counter << 1) >= totalWideCountersWidth) {
+ throw new ReaderException("Wide bars vary too much in width, rejecting");
+ }
+ }
+ }
return pattern;
}
} while (wideCounters > 3);
return decoded.toString();
}
-}
\ No newline at end of file
+}