ISSUE: http://code.google.com/p/zxing/issues/detail?id=42
[zxing.git] / core / src / com / google / zxing / pdf417 / decoder / Decoder.java
index ecb097d..d50fa53 100644 (file)
@@ -1,5 +1,5 @@
 /*\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
@@ -13,6 +13,7 @@
  * 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
@@ -21,152 +22,126 @@ import com.google.zxing.common.DecoderResult;
 //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