Added rendering fix from beyonddeath
[zxing.git] / csharp / datamatrix / decoder / DataBlock.cs
1 /*\r
2  * Copyright 2008 ZXing authors\r
3  *\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
7  *\r
8  *      http://www.apache.org/licenses/LICENSE-2.0\r
9  *\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
15  */\r
16 \r
17 using System;\r
18 using System.Collections.Generic;\r
19 using System.Linq;\r
20 using System.Text;\r
21 \r
22 namespace com.google.zxing.datamatrix.decoder\r
23 {\r
24 \r
25     /**\r
26      * <p>Encapsulates a block of data within a Data Matrix Code. Data Matrix Codes may split their data into\r
27      * multiple blocks, each of which is a unit of data and error-correction codewords. Each\r
28      * is represented by an instance of this class.</p>\r
29      *\r
30      * @author bbrown@google.com (Brian Brown)\r
31      */\r
32     public sealed class DataBlock\r
33     {\r
34           private  int numDataCodewords;\r
35           private  sbyte[] codewords;\r
36 \r
37           private DataBlock(int numDataCodewords, sbyte[] codewords) {\r
38             this.numDataCodewords = numDataCodewords;\r
39             this.codewords = codewords;\r
40           }\r
41 \r
42           /**\r
43            * <p>When Data Matrix Codes use multiple data blocks, they actually interleave the bytes of each of them.\r
44            * That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This\r
45            * method will separate the data into original blocks.</p>\r
46            *\r
47            * @param rawCodewords bytes as read directly from the Data Matrix Code\r
48            * @param version version of the Data Matrix Code\r
49            * @return {@link DataBlock}s containing original bytes, "de-interleaved" from representation in the\r
50            *         Data Matrix Code\r
51            */\r
52           public static DataBlock[] getDataBlocks(sbyte[] rawCodewords,\r
53                                            Version version) {\r
54             // Figure out the number and size of data blocks used by this version\r
55             Version.ECBlocks ecBlocks = version.getECBlocks();\r
56 \r
57             // First count the total number of data blocks\r
58             int totalBlocks = 0;\r
59             Version.ECB[] ecBlockArray = ecBlocks.getECBlocks();\r
60             for (int i = 0; i < ecBlockArray.Length; i++) {\r
61               totalBlocks += ecBlockArray[i].getCount();\r
62             }\r
63 \r
64             // Now establish DataBlocks of the appropriate size and number of data codewords\r
65             DataBlock[] result = new DataBlock[totalBlocks];\r
66             int numResultBlocks = 0;\r
67             for (int j = 0; j < ecBlockArray.Length; j++) {\r
68               Version.ECB ecBlock = ecBlockArray[j];\r
69               for (int i = 0; i < ecBlock.getCount(); i++) {\r
70                 int numDataCodewords = ecBlock.getDataCodewords();\r
71                 int numBlockCodewords = ecBlocks.getECCodewords() + numDataCodewords;\r
72                 result[numResultBlocks++] = new DataBlock(numDataCodewords, new sbyte[numBlockCodewords]);\r
73               }\r
74             }\r
75 \r
76             // All blocks have the same amount of data, except that the last n\r
77             // (where n may be 0) have 1 less byte. Figure out where these start.\r
78             // TODO(bbrown): There is only one case where there is a difference for Data Matrix for size 144\r
79             int longerBlocksTotalCodewords = result[0].codewords.Length;\r
80             //int shorterBlocksTotalCodewords = longerBlocksTotalCodewords - 1;\r
81 \r
82             int longerBlocksNumDataCodewords = longerBlocksTotalCodewords - ecBlocks.getECCodewords();\r
83             int shorterBlocksNumDataCodewords = longerBlocksNumDataCodewords - 1;\r
84             // The last elements of result may be 1 element shorter for 144 matrix\r
85             // first fill out as many elements as all of them have minus 1\r
86             int rawCodewordsOffset = 0;\r
87             for (int i = 0; i < shorterBlocksNumDataCodewords; i++) {\r
88               for (int j = 0; j < numResultBlocks; j++) {\r
89                 result[j].codewords[i] = rawCodewords[rawCodewordsOffset++];\r
90               }\r
91             }\r
92             \r
93             // Fill out the last data block in the longer ones\r
94             bool specialVersion = version.getVersionNumber() == 24;\r
95             int numLongerBlocks = specialVersion ? 8 : numResultBlocks;\r
96             for (int j = 0; j < numLongerBlocks; j++) {\r
97               result[j].codewords[longerBlocksNumDataCodewords - 1] = rawCodewords[rawCodewordsOffset++];\r
98             }\r
99             \r
100             // Now add in error correction blocks\r
101             int max = result[0].codewords.Length;\r
102             for (int i = longerBlocksNumDataCodewords; i < max; i++) {\r
103               for (int j = 0; j < numResultBlocks; j++) {\r
104                 int iOffset = (specialVersion && j > 7) ? i - 1 : i;\r
105                 result[j].codewords[iOffset] = rawCodewords[rawCodewordsOffset++];\r
106               }\r
107             }\r
108 \r
109             if (rawCodewordsOffset != rawCodewords.Length) {\r
110               throw new ArgumentException();\r
111             }\r
112 \r
113             return result;\r
114           }\r
115 \r
116           public int getNumDataCodewords() {\r
117             return numDataCodewords;\r
118           }\r
119 \r
120           public sbyte[] getCodewords() {\r
121             return codewords;\r
122           }\r
123     }\r
124 }\r