package com.google.zxing.oned;
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.ChecksumException;
+import com.google.zxing.DecodeHintType;
+import com.google.zxing.FormatException;
+import com.google.zxing.NotFoundException;
import com.google.zxing.ReaderException;
import com.google.zxing.Result;
-import com.google.zxing.ResultPointCallback;
-import com.google.zxing.DecodeHintType;
+import com.google.zxing.ResultMetadataType;
import com.google.zxing.ResultPoint;
-import com.google.zxing.BarcodeFormat;
+import com.google.zxing.ResultPointCallback;
import com.google.zxing.common.BitArray;
import java.util.Hashtable;
}
private final StringBuffer decodeRowStringBuffer;
+ private final UPCEANExtensionSupport extensionReader;
+ private final EANManufacturerOrgSupport eanManSupport;
protected UPCEANReader() {
decodeRowStringBuffer = new StringBuffer(20);
+ extensionReader = new UPCEANExtensionSupport();
+ eanManSupport = new EANManufacturerOrgSupport();
}
- static int[] findStartGuardPattern(BitArray row) throws ReaderException {
+ static int[] findStartGuardPattern(BitArray row) throws NotFoundException {
boolean foundStart = false;
int[] startRange = null;
int nextStart = 0;
return startRange;
}
- public Result decodeRow(int rowNumber, BitArray row, Hashtable hints) throws ReaderException {
+ public Result decodeRow(int rowNumber, BitArray row, Hashtable hints)
+ throws NotFoundException, ChecksumException, FormatException {
return decodeRow(rowNumber, row, findStartGuardPattern(row), hints);
}
* found. This allows this to be computed once and reused across many implementations.</p>
*/
public Result decodeRow(int rowNumber, BitArray row, int[] startGuardRange, Hashtable hints)
- throws ReaderException {
+ throws NotFoundException, ChecksumException, FormatException {
ResultPointCallback resultPointCallback = hints == null ? null :
(ResultPointCallback) hints.get(DecodeHintType.NEED_RESULT_POINT_CALLBACK);
int end = endRange[1];
int quietEnd = end + (end - endRange[0]);
if (quietEnd >= row.getSize() || !row.isRange(end, quietEnd, false)) {
- throw ReaderException.getInstance();
+ throw NotFoundException.getNotFoundInstance();
}
String resultString = result.toString();
if (!checkChecksum(resultString)) {
- throw ReaderException.getInstance();
+ throw ChecksumException.getChecksumInstance();
}
float left = (float) (startGuardRange[1] + startGuardRange[0]) / 2.0f;
float right = (float) (endRange[1] + endRange[0]) / 2.0f;
- return new Result(resultString,
+ BarcodeFormat format = getBarcodeFormat();
+ Result decodeResult = new Result(resultString,
null, // no natural byte representation for these barcodes
new ResultPoint[]{
new ResultPoint(left, (float) rowNumber),
new ResultPoint(right, (float) rowNumber)},
- getBarcodeFormat());
+ format);
+
+ try {
+ Result extensionResult = extensionReader.decodeRow(row, endRange[1]);
+ decodeResult.putAllMetadata(extensionResult.getResultMetadata());
+ } catch (ReaderException re) {
+ // continue
+ }
+
+ if (BarcodeFormat.EAN_13.equals(format) || BarcodeFormat.UPC_A.equals(format)) {
+ String countryID = eanManSupport.lookupCountryIdentifier(resultString);
+ if (countryID != null) {
+ decodeResult.putMetadata(ResultMetadataType.POSSIBLE_COUNTRY, countryID);
+ }
+ }
+
+ return decodeResult;
}
/**
* @return {@link #checkStandardUPCEANChecksum(String)}
*/
- boolean checkChecksum(String s) throws ReaderException {
+ boolean checkChecksum(String s) throws ChecksumException, FormatException {
return checkStandardUPCEANChecksum(s);
}
*
* @param s string of digits to check
* @return true iff string of digits passes the UPC/EAN checksum algorithm
- * @throws ReaderException if the string does not contain only digits
+ * @throws FormatException if the string does not contain only digits
*/
- private static boolean checkStandardUPCEANChecksum(String s) throws ReaderException {
+ private static boolean checkStandardUPCEANChecksum(String s) throws FormatException {
int length = s.length();
if (length == 0) {
return false;
for (int i = length - 2; i >= 0; i -= 2) {
int digit = (int) s.charAt(i) - (int) '0';
if (digit < 0 || digit > 9) {
- throw ReaderException.getInstance();
+ throw FormatException.getFormatInstance();
}
sum += digit;
}
for (int i = length - 1; i >= 0; i -= 2) {
int digit = (int) s.charAt(i) - (int) '0';
if (digit < 0 || digit > 9) {
- throw ReaderException.getInstance();
+ throw FormatException.getFormatInstance();
}
sum += digit;
}
return sum % 10 == 0;
}
- int[] decodeEnd(BitArray row, int endStart) throws ReaderException {
+ int[] decodeEnd(BitArray row, int endStart) throws NotFoundException {
return findGuardPattern(row, endStart, false, START_END_PATTERN);
}
* @param pattern pattern of counts of number of black and white pixels that are being
* searched for as a pattern
* @return start/end horizontal offset of guard pattern, as an array of two ints
- * @throws ReaderException if pattern is not found
+ * @throws NotFoundException if pattern is not found
*/
static int[] findGuardPattern(BitArray row, int rowOffset, boolean whiteFirst, int[] pattern)
- throws ReaderException {
+ throws NotFoundException {
int patternLength = pattern.length;
int[] counters = new int[patternLength];
int width = row.getSize();
isWhite = !isWhite;
}
}
- throw ReaderException.getInstance();
+ throw NotFoundException.getNotFoundInstance();
}
/**
* for the digits 0-9 are used, and this indicates the encodings for 0 to 9 that should
* be used
* @return horizontal offset of first pixel beyond the decoded digit
- * @throws ReaderException if digit cannot be decoded
+ * @throws NotFoundException if digit cannot be decoded
*/
static int decodeDigit(BitArray row, int[] counters, int rowOffset, int[][] patterns)
- throws ReaderException {
+ throws NotFoundException {
recordPattern(row, rowOffset, counters);
int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept
int bestMatch = -1;
if (bestMatch >= 0) {
return bestMatch;
} else {
- throw ReaderException.getInstance();
+ throw NotFoundException.getNotFoundInstance();
}
}
* @param startRange start/end offset of start guard pattern
* @param resultString {@link StringBuffer} to append decoded chars to
* @return horizontal offset of first pixel after the "middle" that was decoded
- * @throws ReaderException if decoding could not complete successfully
+ * @throws NotFoundException if decoding could not complete successfully
*/
protected abstract int decodeMiddle(BitArray row, int[] startRange, StringBuffer resultString)
- throws ReaderException;
+ throws NotFoundException;
}