package com.google.zxing.oned;\r
\r
import com.google.zxing.BarcodeFormat;\r
-import com.google.zxing.ReaderException;\r
+import com.google.zxing.DecodeHintType;\r
+import com.google.zxing.FormatException;\r
+import com.google.zxing.NotFoundException;\r
import com.google.zxing.Result;\r
import com.google.zxing.ResultPoint;\r
-import com.google.zxing.DecodeHintType;\r
import com.google.zxing.common.BitArray;\r
-import com.google.zxing.common.GenericResultPoint;\r
\r
import java.util.Hashtable;\r
\r
/**\r
* <p>Implements decoding of the ITF format.</p>\r
*\r
- * <p>"ITF" stands for Interleaved Two of Five. This Reader will scan ITF barcode with 6, 10 or 14 digits.\r
- * The checksum is optional and is not applied by this Reader. The consumer of the decoded value\r
- * will have to apply a checksum if required.</p>\r
+ * <p>"ITF" stands for Interleaved Two of Five. This Reader will scan ITF barcode with 6, 10 or 14\r
+ * digits. The checksum is optional and is not applied by this Reader. The consumer of the decoded\r
+ * value will have to apply a checksum if required.</p>\r
*\r
* <p><a href="http://en.wikipedia.org/wiki/Interleaved_2_of_5">http://en.wikipedia.org/wiki/Interleaved_2_of_5</a>\r
* is a great reference for Interleaved 2 of 5 information.</p>\r
*\r
* @author kevin.osullivan@sita.aero, SITA Lab.\r
*/\r
-public final class ITFReader extends AbstractOneDReader {\r
+public final class ITFReader extends OneDReader {\r
\r
private static final int MAX_AVG_VARIANCE = (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.42f);\r
private static final int MAX_INDIVIDUAL_VARIANCE = (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.8f);\r
private static final int W = 3; // Pixel width of a wide line\r
private static final int N = 1; // Pixed width of a narrow line\r
\r
- private static final int[] DEFAULT_ALLOWED_LENGTHS = { 6, 10, 14 };\r
+ private static final int[] DEFAULT_ALLOWED_LENGTHS = { 6, 10, 14, 44 };\r
\r
// Stores the actual narrow line width of the image being decoded.\r
private int narrowLineWidth = -1;\r
/**\r
* Patterns of Wide / Narrow lines to indicate each digit\r
*/\r
- private static final int[][] PATTERNS = {\r
+ static final int[][] PATTERNS = {\r
{N, N, W, W, N}, // 0\r
{W, N, N, N, W}, // 1\r
{N, W, N, N, W}, // 2\r
{N, W, N, W, N} // 9\r
};\r
\r
- public Result decodeRow(int rowNumber, BitArray row, Hashtable hints) throws ReaderException {\r
-\r
- StringBuffer result = new StringBuffer(20);\r
+ public Result decodeRow(int rowNumber, BitArray row, Hashtable hints) throws FormatException, NotFoundException {\r
\r
// Find out where the Middle section (payload) starts & ends\r
int[] startRange = decodeStart(row);\r
int[] endRange = decodeEnd(row);\r
\r
+ StringBuffer result = new StringBuffer(20);\r
decodeMiddle(row, startRange[1], endRange[0], result);\r
-\r
String resultString = result.toString();\r
\r
- int[] allowedLengths = (int[]) hints.get(DecodeHintType.ALLOWED_LENGTHS);\r
+ int[] allowedLengths = null;\r
+ if (hints != null) {\r
+ allowedLengths = (int[]) hints.get(DecodeHintType.ALLOWED_LENGTHS);\r
+\r
+ }\r
if (allowedLengths == null) {\r
allowedLengths = DEFAULT_ALLOWED_LENGTHS;\r
}\r
\r
}\r
if (!lengthOK) {\r
- throw ReaderException.getInstance();\r
+ throw FormatException.getFormatInstance();\r
}\r
\r
return new Result(\r
resultString,\r
null, // no natural byte representation for these barcodes\r
- new ResultPoint[] { new GenericResultPoint(startRange[1], (float) rowNumber),\r
- new GenericResultPoint(startRange[0], (float) rowNumber)},\r
+ new ResultPoint[] { new ResultPoint(startRange[1], (float) rowNumber),\r
+ new ResultPoint(endRange[0], (float) rowNumber)},\r
BarcodeFormat.ITF);\r
}\r
\r
* @param row row of black/white values to search\r
* @param payloadStart offset of start pattern\r
* @param resultString {@link StringBuffer} to append decoded chars to\r
- * @throws ReaderException if decoding could not complete successfully\r
+ * @throws NotFoundException if decoding could not complete successfully\r
*/\r
- static void decodeMiddle(BitArray row, int payloadStart, int payloadEnd, StringBuffer resultString) throws ReaderException {\r
+ private static void decodeMiddle(BitArray row, int payloadStart, int payloadEnd,\r
+ StringBuffer resultString) throws NotFoundException {\r
\r
// Digits are interleaved in pairs - 5 black lines for one digit, and the\r
// 5\r
* @param row row of black/white values to search\r
* @return Array, containing index of start of 'start block' and end of\r
* 'start block'\r
- * @throws ReaderException\r
+ * @throws NotFoundException\r
*/\r
- int[] decodeStart(BitArray row) throws ReaderException {\r
+ int[] decodeStart(BitArray row) throws NotFoundException {\r
int endStart = skipWhiteSpace(row);\r
int[] startPattern = findGuardPattern(row, endStart, START_PATTERN);\r
\r
*\r
* @param row bit array representing the scanned barcode.\r
* @param startPattern index into row of the start or end pattern.\r
- * @throws ReaderException if the quiet zone cannot be found, a ReaderException is thrown.\r
+ * @throws NotFoundException if the quiet zone cannot be found, a ReaderException is thrown.\r
*/\r
- private void validateQuietZone(BitArray row, int startPattern) throws ReaderException {\r
+ private void validateQuietZone(BitArray row, int startPattern) throws NotFoundException {\r
\r
int quietCount = this.narrowLineWidth * 10; // expect to find this many pixels of quiet zone\r
\r
}\r
if (quietCount != 0) {\r
// Unable to find the necessary number of quiet zone pixels.\r
- throw ReaderException.getInstance();\r
+ throw NotFoundException.getNotFoundInstance();\r
}\r
}\r
\r
*\r
* @param row row of black/white values to search\r
* @return index of the first black line.\r
- * @throws ReaderException Throws exception if no black lines are found in the row\r
+ * @throws NotFoundException Throws exception if no black lines are found in the row\r
*/\r
- private static int skipWhiteSpace(BitArray row) throws ReaderException {\r
+ private static int skipWhiteSpace(BitArray row) throws NotFoundException {\r
int width = row.getSize();\r
int endStart = 0;\r
while (endStart < width) {\r
endStart++;\r
}\r
if (endStart == width) {\r
- throw ReaderException.getInstance();\r
+ throw NotFoundException.getNotFoundInstance();\r
}\r
\r
return endStart;\r
* @param row row of black/white values to search\r
* @return Array, containing index of start of 'end block' and end of 'end\r
* block'\r
- * @throws ReaderException\r
+ * @throws NotFoundException\r
*/\r
\r
- int[] decodeEnd(BitArray row) throws ReaderException {\r
+ int[] decodeEnd(BitArray row) throws NotFoundException {\r
\r
// For convenience, reverse the row and then\r
// search from 'the start' for the end block\r
row.reverse();\r
-\r
- int endStart = skipWhiteSpace(row);\r
- int[] endPattern;\r
try {\r
- endPattern = findGuardPattern(row, endStart, END_PATTERN_REVERSED);\r
- } catch (ReaderException e) {\r
- // Put our row of data back the right way before throwing\r
+ int endStart = skipWhiteSpace(row);\r
+ int[] endPattern = findGuardPattern(row, endStart, END_PATTERN_REVERSED);\r
+\r
+ // The start & end patterns must be pre/post fixed by a quiet zone. This\r
+ // zone must be at least 10 times the width of a narrow line.\r
+ // ref: http://www.barcode-1.net/i25code.html\r
+ validateQuietZone(row, endPattern[0]);\r
+\r
+ // Now recalculate the indices of where the 'endblock' starts & stops to\r
+ // accommodate\r
+ // the reversed nature of the search\r
+ int temp = endPattern[0];\r
+ endPattern[0] = row.getSize() - endPattern[1];\r
+ endPattern[1] = row.getSize() - temp;\r
+\r
+ return endPattern;\r
+ } finally {\r
+ // Put the row back the right way.\r
row.reverse();\r
- throw e;\r
}\r
-\r
- // The start & end patterns must be pre/post fixed by a quiet zone. This\r
- // zone must be at least 10 times the width of a narrow line.\r
- // ref: http://www.barcode-1.net/i25code.html\r
- validateQuietZone(row, endPattern[0]);\r
-\r
- // Now recalc the indicies of where the 'endblock' starts & stops to\r
- // accomodate\r
- // the reversed nature of the search\r
- int temp = endPattern[0];\r
- endPattern[0] = row.getSize() - endPattern[1];\r
- endPattern[1] = row.getSize() - temp;\r
-\r
- // Put the row back the righ way.\r
- row.reverse();\r
- return endPattern;\r
}\r
\r
/**\r
* being searched for as a pattern\r
* @return start/end horizontal offset of guard pattern, as an array of two\r
* ints\r
- * @throws ReaderException if pattern is not found\r
+ * @throws NotFoundException if pattern is not found\r
*/\r
- static int[] findGuardPattern(BitArray row, int rowOffset, int[] pattern) throws ReaderException {\r
-\r
- // TODO: This is very similar to implementation in AbstractUPCEANReader. Consider if they can be merged to\r
- // a single method.\r
+ private static int[] findGuardPattern(BitArray row, int rowOffset, int[] pattern) throws NotFoundException {\r
\r
+ // TODO: This is very similar to implementation in UPCEANReader. Consider if they can be\r
+ // merged to a single method.\r
int patternLength = pattern.length;\r
int[] counters = new int[patternLength];\r
int width = row.getSize();\r
int patternStart = rowOffset;\r
for (int x = rowOffset; x < width; x++) {\r
boolean pixel = row.get(x);\r
- if ((!pixel && isWhite) || (pixel && !isWhite)) {\r
+ if (pixel ^ isWhite) {\r
counters[counterPosition]++;\r
} else {\r
if (counterPosition == patternLength - 1) {\r
isWhite = !isWhite;\r
}\r
}\r
- throw ReaderException.getInstance();\r
+ throw NotFoundException.getNotFoundInstance();\r
}\r
\r
/**\r
*\r
* @param counters the counts of runs of observed black/white/black/... values\r
* @return The decoded digit\r
- * @throws ReaderException if digit cannot be decoded\r
+ * @throws NotFoundException if digit cannot be decoded\r
*/\r
- private static int decodeDigit(int[] counters) throws ReaderException {\r
+ private static int decodeDigit(int[] counters) throws NotFoundException {\r
\r
int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept\r
int bestMatch = -1;\r
if (bestMatch >= 0) {\r
return bestMatch;\r
} else {\r
- throw ReaderException.getInstance();\r
+ throw NotFoundException.getNotFoundInstance();\r
}\r
}\r
\r
-}
\ No newline at end of file
+}\r