C# port, add datamatrix code
[zxing.git] / csharp / datamatrix / decoder / Decoder.cs
diff --git a/csharp/datamatrix/decoder/Decoder.cs b/csharp/datamatrix/decoder/Decoder.cs
new file mode 100644 (file)
index 0000000..d30b4be
--- /dev/null
@@ -0,0 +1,132 @@
+/*\r
+ * Copyright 2007 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
+ * You may obtain a copy of the License at\r
+ *\r
+ *      http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using com.google.zxing.common;\r
+using com.google.zxing.common.reedsolomon; \r
+\r
+namespace com.google.zxing.datamatrix.decoder\r
+{\r
+    \r
+    /**\r
+     * <p>The main class which implements Data Matrix Code decoding -- as opposed to locating and extracting\r
+     * the Data Matrix Code from an image.</p>\r
+     *\r
+     * @author bbrown@google.com (Brian Brown)\r
+     */\r
+    public sealed class Decoder\r
+    {\r
+          private ReedSolomonDecoder rsDecoder;\r
+          public Decoder() {\r
+            rsDecoder = new ReedSolomonDecoder(GF256.DATA_MATRIX_FIELD);\r
+          }\r
+\r
+          /**\r
+           * <p>Convenience method that can decode a Data Matrix 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 Data Matrix Code modules\r
+           * @return text and bytes encoded within the Data Matrix Code\r
+           * @throws ReaderException if the Data Matrix Code cannot be decoded\r
+           */\r
+          public DecoderResult decode(bool[][] image) {\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
+\r
+          /**\r
+           * <p>Decodes a Data Matrix Code represented as a {@link BitMatrix}. A 1 or "true" is taken\r
+           * to mean a black module.</p>\r
+           *\r
+           * @param bits booleans representing white/black Data Matrix Code modules\r
+           * @return text and bytes encoded within the Data Matrix Code\r
+           * @throws ReaderException if the Data Matrix Code cannot be decoded\r
+           */\r
+          public DecoderResult decode(BitMatrix bits) {\r
+\r
+            // Construct a parser and read version, error-correction level\r
+            BitMatrixParser parser = new BitMatrixParser(bits);\r
+            Version version = parser.readVersion(bits);\r
+\r
+            // Read codewords\r
+            sbyte[] codewords = parser.readCodewords();\r
+            // Separate into data blocks\r
+            DataBlock[] dataBlocks = DataBlock.getDataBlocks(codewords, version);\r
+\r
+            // Count total number of data bytes\r
+            int totalBytes = 0;\r
+            for (int i = 0; i < dataBlocks.Length; i++) {\r
+              totalBytes += dataBlocks[i].getNumDataCodewords();\r
+            }\r
+            sbyte[] resultBytes = new sbyte[totalBytes];\r
+            int resultOffset = 0;\r
+\r
+            // Error-correct and copy data blocks together into a stream of bytes\r
+            for (int j = 0; j < dataBlocks.Length; j++) {\r
+              DataBlock dataBlock = dataBlocks[j];\r
+              sbyte[] codewordBytes = dataBlock.getCodewords();\r
+              int numDataCodewords = dataBlock.getNumDataCodewords();\r
+              correctErrors(codewordBytes, numDataCodewords);\r
+              for (int i = 0; i < numDataCodewords; i++) {\r
+                resultBytes[resultOffset++] = codewordBytes[i];\r
+              }\r
+            }\r
+\r
+            // Decode the contents of that stream of bytes\r
+            return DecodedBitStreamParser.decode(resultBytes);\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 void correctErrors(sbyte[] codewordBytes, int numDataCodewords) {\r
+            int numCodewords = codewordBytes.Length;\r
+            // First read into an array of ints\r
+            int[] codewordsInts = new int[numCodewords];\r
+            for (int i = 0; i < numCodewords; i++) {\r
+              codewordsInts[i] = codewordBytes[i] & 0xFF;\r
+            }\r
+            int numECCodewords = codewordBytes.Length - numDataCodewords;\r
+            try {\r
+              rsDecoder.decode(codewordsInts, numECCodewords);\r
+            } catch (ReedSolomonException rse) {\r
+              throw new ReaderException();\r
+            }\r
+            // Copy back into array of bytes -- only need to worry about the bytes that were data\r
+            // We don't care about errors in the error-correction codewords\r
+            for (int i = 0; i < numDataCodewords; i++) {\r
+              codewordBytes[i] = (sbyte) codewordsInts[i];\r
+            }\r
+          }\r
+\r
+    }\r
+}\r