import com.google.zxing.Result;
import com.google.zxing.ResultPoint;
import com.google.zxing.common.BitArray;
import com.google.zxing.Result;
import com.google.zxing.ResultPoint;
import com.google.zxing.common.BitArray;
* The 9 least-significant bits of each int correspond to the pattern of wide and narrow,
* with 1s representing "wide" and 0s representing narrow.
*/
* The 9 least-significant bits of each int correspond to the pattern of wide and narrow,
* with 1s representing "wide" and 0s representing narrow.
*/
0x034, 0x121, 0x061, 0x160, 0x031, 0x130, 0x070, 0x025, 0x124, 0x064, // 0-9
0x109, 0x049, 0x148, 0x019, 0x118, 0x058, 0x00D, 0x10C, 0x04C, 0x01C, // A-J
0x103, 0x043, 0x142, 0x013, 0x112, 0x052, 0x007, 0x106, 0x046, 0x016, // K-T
0x034, 0x121, 0x061, 0x160, 0x031, 0x130, 0x070, 0x025, 0x124, 0x064, // 0-9
0x109, 0x049, 0x148, 0x019, 0x118, 0x058, 0x00D, 0x10C, 0x04C, 0x01C, // A-J
0x103, 0x043, 0x142, 0x013, 0x112, 0x052, 0x007, 0x106, 0x046, 0x016, // K-T
- public Result decodeRow(int rowNumber, BitArray row, Hashtable hints) throws ReaderException {
+ public Result decodeRow(int rowNumber, BitArray row, Hashtable hints)
+ throws NotFoundException, ChecksumException, FormatException {
int[] counters = new int[9];
char decodedChar;
int lastStart;
do {
recordPattern(row, nextStart, counters);
int pattern = toNarrowWidePattern(counters);
int[] counters = new int[9];
char decodedChar;
int lastStart;
do {
recordPattern(row, nextStart, counters);
int pattern = toNarrowWidePattern(counters);
+ // 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 NotFoundException.getNotFoundInstance();
+ }
+
if (usingCheckDigit) {
int max = result.length() - 1;
int total = 0;
for (int i = 0; i < max; i++) {
total += ALPHABET_STRING.indexOf(result.charAt(i));
}
if (usingCheckDigit) {
int max = result.length() - 1;
int total = 0;
for (int i = 0; i < max; i++) {
total += ALPHABET_STRING.indexOf(result.charAt(i));
}
- if (total % 43 != ALPHABET_STRING.indexOf(result.charAt(max))) {
- throw new ReaderException("Checksum failed");
+ if (result.charAt(max) != ALPHABET[total % 43]) {
+ throw ChecksumException.getChecksumInstance();
- String resultString = result.toString();
- if (extendedMode) {
- resultString = decodeExtended(resultString);
+ if (result.length() == 0) {
+ // Almost surely a false positive
+ throw NotFoundException.getNotFoundInstance();
- if (resultString.length() == 0) {
- // Almost surely a false positive
- throw new ReaderException("Empty barcode found; assuming a false positive");
+ String resultString;
+ if (extendedMode) {
+ resultString = decodeExtended(result);
+ } else {
+ resultString = result.toString();
- new GenericResultPoint(left, (float) rowNumber),
- new GenericResultPoint(right, (float) rowNumber)},
+ new ResultPoint(left, (float) rowNumber),
+ new ResultPoint(right, (float) rowNumber)},
- try {
- if (toNarrowWidePattern(counters) == ASTERISK_ENCODING) {
+ if (toNarrowWidePattern(counters) == ASTERISK_ENCODING) {
+ // Look for whitespace before start pattern, >= 50% of width of start pattern
+ if (row.isRange(Math.max(0, patternStart - (i - patternStart) / 2), patternStart, false)) {
- private static int toNarrowWidePattern(int[] counters) throws ReaderException {
+ // For efficiency, returns -1 on failure. Not throwing here saved as many as 700 exceptions
+ // per image when using some of our blackbox images.
+ private static int toNarrowWidePattern(int[] counters) {
wideCounters--;
// totalWideCountersWidth = 3 * average, so this checks if counter >= 3/2 * average
if ((counter << 1) >= totalWideCountersWidth) {
wideCounters--;
// totalWideCountersWidth = 3 * average, so this checks if counter >= 3/2 * average
if ((counter << 1) >= totalWideCountersWidth) {
int length = encoded.length();
StringBuffer decoded = new StringBuffer(length);
for (int i = 0; i < length; i++) {
int length = encoded.length();
StringBuffer decoded = new StringBuffer(length);
for (int i = 0; i < length; i++) {