2 * Copyright 2009 ZXing authors
\r
4 * Licensed under the Apache License, Version 2.0 (the "License");
\r
5 * you may not use this file except in compliance with the License.
\r
6 * You may obtain a copy of the License at
\r
8 * http://www.apache.org/licenses/LICENSE-2.0
\r
10 * Unless required by applicable law or agreed to in writing, software
\r
11 * distributed under the License is distributed on an "AS IS" BASIS,
\r
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
13 * See the License for the specific language governing permissions and
\r
14 * limitations under the License.
\r
17 using ReaderException = com.google.zxing.ReaderException;
\r
18 using BitMatrix = com.google.zxing.common.BitMatrix;
\r
19 using DecoderResult = com.google.zxing.common.DecoderResult;
\r
20 namespace com.google.zxing.pdf417.decoder
\r
22 //import com.google.zxing.pdf417.reedsolomon.ReedSolomonDecoder;
\r
24 /// <summary> <p>The main class which implements PDF417 Code decoding -- as
\r
25 /// opposed to locating and extracting the PDF417 Code from an image.</p>
\r
28 /// <author> SITA Lab (kevin.osullivan@sita.aero)
\r
30 /// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
\r
32 public sealed class Decoder
\r
35 private const int MAX_ERRORS = 3;
\r
36 private const int MAX_EC_CODEWORDS = 512;
\r
37 //private final ReedSolomonDecoder rsDecoder;
\r
42 //rsDecoder = new ReedSolomonDecoder();
\r
45 /// <summary> <p>Convenience method that can decode a PDF417 Code represented as a 2D array of booleans.
\r
46 /// "true" is taken to mean a black module.</p>
\r
49 /// <param name="image">booleans representing white/black PDF417 modules
\r
51 /// <returns> text and bytes encoded within the PDF417 Code
\r
53 /// <throws> ReaderException if the PDF417 Code cannot be decoded </throws>
\r
54 public DecoderResult decode(bool[][] image)
\r
56 int dimension = image.Length;
\r
57 BitMatrix bits = new BitMatrix(dimension);
\r
58 for (int i = 0; i < dimension; i++)
\r
60 for (int j = 0; j < dimension; j++)
\r
64 bits.set_Renamed(j, i);
\r
68 return decode(bits);
\r
71 /// <summary> <p>Decodes a PDF417 Code represented as a {@link BitMatrix}.
\r
72 /// A 1 or "true" is taken to mean a black module.</p>
\r
75 /// <param name="bits">booleans representing white/black PDF417 Code modules
\r
77 /// <returns> text and bytes encoded within the PDF417 Code
\r
79 /// <throws> ReaderException if the PDF417 Code cannot be decoded </throws>
\r
80 public DecoderResult decode(BitMatrix bits)
\r
82 // Construct a parser to read the data codewords and error-correction level
\r
83 BitMatrixParser parser = new BitMatrixParser(bits);
\r
84 int[] codewords = parser.readCodewords();
\r
85 if (codewords == null || codewords.Length == 0)
\r
87 throw ReaderException.Instance;
\r
90 int ecLevel = parser.ECLevel;
\r
91 int numECCodewords = 1 << (ecLevel + 1);
\r
92 int[] erasures = parser.Erasures;
\r
94 correctErrors(codewords, erasures, numECCodewords);
\r
95 verifyCodewordCount(codewords, numECCodewords);
\r
97 // Decode the codewords
\r
98 return DecodedBitStreamParser.decode(codewords);
\r
101 /// <summary> Verify that all is OK with the codeword array.
\r
104 /// <param name="codewords">
\r
106 /// <returns> an index to the first data codeword.
\r
108 /// <throws> ReaderException </throws>
\r
109 private static void verifyCodewordCount(int[] codewords, int numECCodewords)
\r
111 if (codewords.Length < 4)
\r
113 // Codeword array size should be at least 4 allowing for
\r
114 // Count CW, At least one Data CW, Error Correction CW, Error Correction CW
\r
115 throw ReaderException.Instance;
\r
117 // The first codeword, the Symbol Length Descriptor, shall always encode the total number of data
\r
118 // codewords in the symbol, including the Symbol Length Descriptor itself, data codewords and pad
\r
119 // codewords, but excluding the number of error correction codewords.
\r
120 int numberOfCodewords = codewords[0];
\r
121 if (numberOfCodewords > codewords.Length)
\r
123 throw ReaderException.Instance;
\r
125 if (numberOfCodewords == 0)
\r
127 // Reset to the length of the array - 8 (Allow for at least level 3 Error Correction (8 Error Codewords)
\r
128 if (numECCodewords < codewords.Length)
\r
130 codewords[0] = codewords.Length - numECCodewords;
\r
134 throw ReaderException.Instance;
\r
139 /// <summary> <p>Given data and error-correction codewords received, possibly corrupted by errors, attempts to
\r
140 /// correct the errors in-place using Reed-Solomon error correction.</p>
\r
143 /// <param name="codewords"> data and error correction codewords
\r
145 /// <throws> ReaderException if error correction fails </throws>
\r
146 private static int correctErrors(int[] codewords, int[] erasures, int numECCodewords)
\r
148 if ((erasures != null && erasures.Length > numECCodewords / 2 + MAX_ERRORS) || (numECCodewords < 0 || numECCodewords > MAX_EC_CODEWORDS))
\r
150 // Too many errors or EC Codewords is corrupted
\r
151 throw ReaderException.Instance;
\r
153 // Try to correct the errors
\r
154 int result = 0; // rsDecoder.correctErrors(codewords, numECCodewords);
\r
155 if (erasures != null)
\r
157 int numErasures = erasures.Length;
\r
160 numErasures -= result;
\r
162 if (numErasures > MAX_ERRORS)
\r
164 // Still too many errors
\r
165 throw ReaderException.Instance;
\r