/*\r
- * Copyright 2007 ZXing authors\r
+ * Copyright 2009 ZXing authors\r
*\r
* Licensed under the Apache License, Version 2.0 (the "License");\r
* you may not use this file except in compliance with the License.\r
* See the License for the specific language governing permissions and\r
* limitations under the License.\r
*/\r
+\r
package com.google.zxing.pdf417.decoder;\r
\r
import com.google.zxing.ReaderException;\r
//import com.google.zxing.pdf417.reedsolomon.ReedSolomonDecoder;\r
\r
/**\r
- * <p>The main class which implements PDF417 Code decoding -- as \r
+ * <p>The main class which implements PDF417 Code decoding -- as\r
* opposed to locating and extracting the PDF417 Code from an image.</p>\r
*\r
* @author SITA Lab (kevin.osullivan@sita.aero)\r
*/\r
public final class Decoder {\r
- public static final boolean debug = false;\r
- private static final int MAX_ERRORS = 3;\r
- private static final int MAX_EC_CODEWORDS = 512;\r
- //private final ReedSolomonDecoder rsDecoder;\r
\r
- public Decoder() {\r
- // TODO MGMG\r
- //rsDecoder = new ReedSolomonDecoder();\r
- }\r
+ private static final int MAX_ERRORS = 3;\r
+ private static final int MAX_EC_CODEWORDS = 512;\r
+ //private final ReedSolomonDecoder rsDecoder;\r
\r
- /**\r
- * <p>Convenience method that can decode a PDF417 Code represented as a 2D array of booleans.\r
- * "true" is taken to mean a black module.</p>\r
- *\r
- * @param image booleans representing white/black PDF417 modules\r
- * @return text and bytes encoded within the PDF417 Code\r
- * @throws ReaderException if the PDF417 Code cannot be decoded\r
- */\r
- public DecoderResult decode(boolean[][] image) throws ReaderException {\r
- int dimension = image.length;\r
- BitMatrix bits = new BitMatrix(dimension);\r
- for (int i = 0; i < dimension; i++) {\r
- for (int j = 0; j < dimension; j++) {\r
- if (image[i][j]) {\r
- bits.set(i, j);\r
- }\r
- }\r
- }\r
- return decode(bits);\r
- }\r
+ public Decoder() {\r
+ // TODO MGMG\r
+ //rsDecoder = new ReedSolomonDecoder();\r
+ }\r
\r
- /**\r
- * <p>Decodes a PDF417 Code represented as a {@link BitMatrix}. \r
- * A 1 or "true" is taken to mean a black module.</p>\r
- *\r
- * @param bits booleans representing white/black PDF417 Code modules\r
- * @return text and bytes encoded within the PDF417 Code\r
- * @throws ReaderException if the PDF417 Code cannot be decoded\r
- */\r
- public DecoderResult decode(BitMatrix bits) throws ReaderException {\r
- // Construct a parser to read the data codewords and error-correction level\r
- long t2;\r
- long t1 = System.currentTimeMillis();\r
- BitMatrixParser parser = new BitMatrixParser(bits);\r
- int[] codewords = parser.readCodewords();\r
- if (codewords == null || codewords.length == 0) {\r
- if (debug) System.out.println("No codewords read"); \r
- throw ReaderException.getInstance();\r
- }\r
- if (debug) {\r
- t2 = System.currentTimeMillis();\r
- System.out.println("Elapsed time in ms - BitMatrixParser " +(t2-t1));\r
- }\r
+ /**\r
+ * <p>Convenience method that can decode a PDF417 Code represented as a 2D array of booleans.\r
+ * "true" is taken to mean a black module.</p>\r
+ *\r
+ * @param image booleans representing white/black PDF417 modules\r
+ * @return text and bytes encoded within the PDF417 Code\r
+ * @throws ReaderException if the PDF417 Code cannot be decoded\r
+ */\r
+ public DecoderResult decode(boolean[][] image) throws ReaderException {\r
+ int dimension = image.length;\r
+ BitMatrix bits = new BitMatrix(dimension);\r
+ for (int i = 0; i < dimension; i++) {\r
+ for (int j = 0; j < dimension; j++) {\r
+ if (image[j][i]) {\r
+ bits.set(j, i);\r
+ }\r
+ }\r
+ }\r
+ return decode(bits);\r
+ }\r
\r
- int ecLevel = parser.getECLevel();\r
- int numECCodewords = 1 << (ecLevel+1);\r
- int erasures[] = parser.getErasures();\r
- \r
- t1 = System.currentTimeMillis();\r
- correctErrors(codewords, erasures, numECCodewords);\r
- if (debug) {\r
- t2 = System.currentTimeMillis();\r
- System.out.println("Elapsed time in ms - Reed Solomon " +(t2-t1));\r
- }\r
- verifyCodewordCount(codewords, numECCodewords);\r
- \r
- t1 = System.currentTimeMillis();\r
- DecoderResult dr = DecodedBitStreamParser.decode(codewords);\r
- if (debug) {\r
- t2 = System.currentTimeMillis();\r
- System.out.println("Elapsed time in ms - DecodeBitStreamParser " +(t2-t1));\r
- }\r
- // Decode the codewords\r
- return dr;\r
- }\r
+ /**\r
+ * <p>Decodes a PDF417 Code represented as a {@link BitMatrix}.\r
+ * A 1 or "true" is taken to mean a black module.</p>\r
+ *\r
+ * @param bits booleans representing white/black PDF417 Code modules\r
+ * @return text and bytes encoded within the PDF417 Code\r
+ * @throws ReaderException if the PDF417 Code cannot be decoded\r
+ */\r
+ public DecoderResult decode(BitMatrix bits) throws ReaderException {\r
+ // Construct a parser to read the data codewords and error-correction level\r
+ BitMatrixParser parser = new BitMatrixParser(bits);\r
+ int[] codewords = parser.readCodewords();\r
+ if (codewords == null || codewords.length == 0) {\r
+ throw ReaderException.getInstance();\r
+ }\r
\r
- /**\r
- * Verify that all is OK with the codeword array.\r
- * @param codewords\r
- * @return an index to the first data codeword.\r
- * @throws ReaderException\r
- */\r
- private int verifyCodewordCount(int codewords[], int numECCodewords) throws ReaderException {\r
- int numberOfCodewords = 0;\r
- if (codewords.length < 4) {\r
- // Codeword array size should be at least 4 allowing for\r
- // Count CW, At least one Data CW, Error Correction CW, Error Correction CW\r
- if (debug) System.out.println("Not enough codewords " + codewords.length);\r
- throw ReaderException.getInstance();\r
- }\r
- // The first codeword, the Symbol Length Descriptor, shall always encode the total number of data\r
- // codewords in the symbol, including the Symbol Length Descriptor itself, data codewords and pad\r
- // codewords, but excluding the number of error correction codewords. \r
- numberOfCodewords = codewords[0];\r
- if (numberOfCodewords > codewords.length) {\r
- if (debug) System.out.println("Invalid number of codewords[0]=" + numberOfCodewords + " codewords.length=" + codewords.length);\r
- throw ReaderException.getInstance();\r
- }\r
- if (numberOfCodewords == 0) {\r
- // Reset to the length of the array - 8 (Allow for at least level 3 Error Correction (8 Error Codewords)\r
- if (numECCodewords < codewords.length) {\r
- codewords[0] = codewords.length - numECCodewords;\r
- if (debug) System.out.println("Codewords[0] is zero, resetting to " +(codewords[0])); \r
- } else {\r
- if (debug) System.out.println("Codewords[0] is zero, no data codewords"); \r
- throw ReaderException.getInstance();\r
- }\r
- }\r
- return 1; // Index to first data codeword\r
- }\r
+ int ecLevel = parser.getECLevel();\r
+ int numECCodewords = 1 << (ecLevel + 1);\r
+ int[] erasures = parser.getErasures();\r
+\r
+ correctErrors(codewords, erasures, numECCodewords);\r
+ verifyCodewordCount(codewords, numECCodewords);\r
+\r
+ // Decode the codewords\r
+ return DecodedBitStreamParser.decode(codewords);\r
+ }\r
+\r
+ /**\r
+ * Verify that all is OK with the codeword array.\r
+ *\r
+ * @param codewords\r
+ * @return an index to the first data codeword.\r
+ * @throws ReaderException\r
+ */\r
+ private static int verifyCodewordCount(int[] codewords, int numECCodewords) throws ReaderException {\r
+ if (codewords.length < 4) {\r
+ // Codeword array size should be at least 4 allowing for\r
+ // Count CW, At least one Data CW, Error Correction CW, Error Correction CW\r
+ throw ReaderException.getInstance();\r
+ }\r
+ // The first codeword, the Symbol Length Descriptor, shall always encode the total number of data\r
+ // codewords in the symbol, including the Symbol Length Descriptor itself, data codewords and pad\r
+ // codewords, but excluding the number of error correction codewords.\r
+ int numberOfCodewords = codewords[0];\r
+ if (numberOfCodewords > codewords.length) {\r
+ throw ReaderException.getInstance();\r
+ }\r
+ if (numberOfCodewords == 0) {\r
+ // Reset to the length of the array - 8 (Allow for at least level 3 Error Correction (8 Error Codewords)\r
+ if (numECCodewords < codewords.length) {\r
+ codewords[0] = codewords.length - numECCodewords;\r
+ } else {\r
+ throw ReaderException.getInstance();\r
+ }\r
+ }\r
+ return 1; // Index to first data codeword\r
+ }\r
\r
- /**\r
- * <p>Given data and error-correction codewords received, possibly corrupted by errors, attempts to\r
- * correct the errors in-place using Reed-Solomon error correction.</p>\r
- *\r
- * @param codewordBytes data and error correction codewords\r
- * @param numDataCodewords number of codewords that are data bytes\r
- * @throws ReaderException if error correction fails\r
- */\r
- private int correctErrors(int[] codewords, int[] erasures, int numECCodewords) throws ReaderException {\r
- if ((erasures != null && erasures.length > numECCodewords/2 + MAX_ERRORS) ||\r
- (numECCodewords < 0 || numECCodewords > MAX_EC_CODEWORDS)) {\r
- // Too many errors or EC Codewords is corrupted\r
- throw ReaderException.getInstance(); \r
- }\r
- // Try to correct the errors\r
- int result = 0; // rsDecoder.correctErrors(codewords, numECCodewords);\r
- if (debug) {\r
- System.out.println("Corrected errors: " + result);\r
- }\r
- if (erasures != null) {\r
- int numErasures = erasures.length;\r
- if (result > 0) {\r
- numErasures = numErasures - result;\r
- } \r
- if (numErasures > MAX_ERRORS) {\r
- // Still too many errors\r
- throw ReaderException.getInstance();\r
- }\r
- } \r
- return result;\r
+ /**\r
+ * <p>Given data and error-correction codewords received, possibly corrupted by errors, attempts to\r
+ * correct the errors in-place using Reed-Solomon error correction.</p>\r
+ *\r
+ * @param codewords data and error correction codewords\r
+ * @throws ReaderException if error correction fails\r
+ */\r
+ private static int correctErrors(int[] codewords, int[] erasures, int numECCodewords) throws ReaderException {\r
+ if ((erasures != null && erasures.length > numECCodewords / 2 + MAX_ERRORS) ||\r
+ (numECCodewords < 0 || numECCodewords > MAX_EC_CODEWORDS)) {\r
+ // Too many errors or EC Codewords is corrupted\r
+ throw ReaderException.getInstance();\r
+ }\r
+ // Try to correct the errors\r
+ int result = 0; // rsDecoder.correctErrors(codewords, numECCodewords);\r
+ if (erasures != null) {\r
+ int numErasures = erasures.length;\r
+ if (result > 0) {\r
+ numErasures -= result;\r
+ }\r
+ if (numErasures > MAX_ERRORS) {\r
+ // Still too many errors\r
+ throw ReaderException.getInstance();\r
+ }\r
+ }\r
+ return result;\r
}\r
}\r