--- /dev/null
+/*\r
+ * Copyright 2008 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
+\r
+namespace com.google.zxing.datamatrix.decoder\r
+{\r
+\r
+ /**\r
+ * <p>Encapsulates a block of data within a Data Matrix Code. Data Matrix Codes may split their data into\r
+ * multiple blocks, each of which is a unit of data and error-correction codewords. Each\r
+ * is represented by an instance of this class.</p>\r
+ *\r
+ * @author bbrown@google.com (Brian Brown)\r
+ */\r
+ public sealed class DataBlock\r
+ {\r
+ private int numDataCodewords;\r
+ private sbyte[] codewords;\r
+\r
+ private DataBlock(int numDataCodewords, sbyte[] codewords) {\r
+ this.numDataCodewords = numDataCodewords;\r
+ this.codewords = codewords;\r
+ }\r
+\r
+ /**\r
+ * <p>When Data Matrix Codes use multiple data blocks, they actually interleave the bytes of each of them.\r
+ * That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This\r
+ * method will separate the data into original blocks.</p>\r
+ *\r
+ * @param rawCodewords bytes as read directly from the Data Matrix Code\r
+ * @param version version of the Data Matrix Code\r
+ * @return {@link DataBlock}s containing original bytes, "de-interleaved" from representation in the\r
+ * Data Matrix Code\r
+ */\r
+ public static DataBlock[] getDataBlocks(sbyte[] rawCodewords,\r
+ Version version) {\r
+ // Figure out the number and size of data blocks used by this version\r
+ Version.ECBlocks ecBlocks = version.getECBlocks();\r
+\r
+ // First count the total number of data blocks\r
+ int totalBlocks = 0;\r
+ Version.ECB[] ecBlockArray = ecBlocks.getECBlocks();\r
+ for (int i = 0; i < ecBlockArray.Length; i++) {\r
+ totalBlocks += ecBlockArray[i].getCount();\r
+ }\r
+\r
+ // Now establish DataBlocks of the appropriate size and number of data codewords\r
+ DataBlock[] result = new DataBlock[totalBlocks];\r
+ int numResultBlocks = 0;\r
+ for (int j = 0; j < ecBlockArray.Length; j++) {\r
+ Version.ECB ecBlock = ecBlockArray[j];\r
+ for (int i = 0; i < ecBlock.getCount(); i++) {\r
+ int numDataCodewords = ecBlock.getDataCodewords();\r
+ int numBlockCodewords = ecBlocks.getECCodewords() + numDataCodewords;\r
+ result[numResultBlocks++] = new DataBlock(numDataCodewords, new sbyte[numBlockCodewords]);\r
+ }\r
+ }\r
+\r
+ // All blocks have the same amount of data, except that the last n\r
+ // (where n may be 0) have 1 less byte. Figure out where these start.\r
+ // TODO(bbrown): There is only one case where there is a difference for Data Matrix for size 144\r
+ int longerBlocksTotalCodewords = result[0].codewords.Length;\r
+ //int shorterBlocksTotalCodewords = longerBlocksTotalCodewords - 1;\r
+\r
+ int longerBlocksNumDataCodewords = longerBlocksTotalCodewords - ecBlocks.getECCodewords();\r
+ int shorterBlocksNumDataCodewords = longerBlocksNumDataCodewords - 1;\r
+ // The last elements of result may be 1 element shorter for 144 matrix\r
+ // first fill out as many elements as all of them have minus 1\r
+ int rawCodewordsOffset = 0;\r
+ for (int i = 0; i < shorterBlocksNumDataCodewords; i++) {\r
+ for (int j = 0; j < numResultBlocks; j++) {\r
+ result[j].codewords[i] = rawCodewords[rawCodewordsOffset++];\r
+ }\r
+ }\r
+ \r
+ // Fill out the last data block in the longer ones\r
+ bool specialVersion = version.getVersionNumber() == 24;\r
+ int numLongerBlocks = specialVersion ? 8 : numResultBlocks;\r
+ for (int j = 0; j < numLongerBlocks; j++) {\r
+ result[j].codewords[longerBlocksNumDataCodewords - 1] = rawCodewords[rawCodewordsOffset++];\r
+ }\r
+ \r
+ // Now add in error correction blocks\r
+ int max = result[0].codewords.Length;\r
+ for (int i = longerBlocksNumDataCodewords; i < max; i++) {\r
+ for (int j = 0; j < numResultBlocks; j++) {\r
+ int iOffset = (specialVersion && j > 7) ? i - 1 : i;\r
+ result[j].codewords[iOffset] = rawCodewords[rawCodewordsOffset++];\r
+ }\r
+ }\r
+\r
+ if (rawCodewordsOffset != rawCodewords.Length) {\r
+ throw new ArgumentException();\r
+ }\r
+\r
+ return result;\r
+ }\r
+\r
+ public int getNumDataCodewords() {\r
+ return numDataCodewords;\r
+ }\r
+\r
+ public sbyte[] getCodewords() {\r
+ return codewords;\r
+ }\r
+ }\r
+}\r