Issues 155.2 -- add %f for format
[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 using System;\r
17 namespace com.google.zxing.datamatrix.decoder\r
18 {\r
19         \r
20         /// <summary> <p>Encapsulates a block of data within a Data Matrix Code. Data Matrix Codes may split their data into\r
21         /// multiple blocks, each of which is a unit of data and error-correction codewords. Each\r
22         /// is represented by an instance of this class.</p>\r
23         /// \r
24         /// </summary>\r
25         /// <author>  bbrown@google.com (Brian Brown)\r
26         /// </author>\r
27         /// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source \r
28         /// </author>\r
29         sealed class DataBlock\r
30         {\r
31                 internal int NumDataCodewords\r
32                 {\r
33                         get\r
34                         {\r
35                                 return numDataCodewords;\r
36                         }\r
37                         \r
38                 }\r
39                 internal sbyte[] Codewords\r
40                 {\r
41                         get\r
42                         {\r
43                                 return codewords;\r
44                         }\r
45                         \r
46                 }\r
47                 \r
48                 //UPGRADE_NOTE: Final was removed from the declaration of 'numDataCodewords '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"\r
49                 private int numDataCodewords;\r
50                 //UPGRADE_NOTE: Final was removed from the declaration of 'codewords '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"\r
51                 private sbyte[] codewords;\r
52                 \r
53                 private DataBlock(int numDataCodewords, sbyte[] codewords)\r
54                 {\r
55                         this.numDataCodewords = numDataCodewords;\r
56                         this.codewords = codewords;\r
57                 }\r
58                 \r
59                 /// <summary> <p>When Data Matrix Codes use multiple data blocks, they actually interleave the bytes of each of them.\r
60                 /// That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This\r
61                 /// method will separate the data into original blocks.</p>\r
62                 /// \r
63                 /// </summary>\r
64                 /// <param name="rawCodewords">bytes as read directly from the Data Matrix Code\r
65                 /// </param>\r
66                 /// <param name="version">version of the Data Matrix Code\r
67                 /// </param>\r
68                 /// <returns> {@link DataBlock}s containing original bytes, "de-interleaved" from representation in the\r
69                 /// Data Matrix Code\r
70                 /// </returns>\r
71                 internal static DataBlock[] getDataBlocks(sbyte[] rawCodewords, Version version)\r
72                 {\r
73                         // Figure out the number and size of data blocks used by this version\r
74                         Version.ECBlocks ecBlocks = version.getECBlocks();\r
75                         \r
76                         // First count the total number of data blocks\r
77                         int totalBlocks = 0;\r
78                         Version.ECB[] ecBlockArray = ecBlocks.getECBlocks();\r
79                         for (int i = 0; i < ecBlockArray.Length; i++)\r
80                         {\r
81                                 totalBlocks += ecBlockArray[i].Count;\r
82                         }\r
83                         \r
84                         // Now establish DataBlocks of the appropriate size and number of data codewords\r
85                         DataBlock[] result = new DataBlock[totalBlocks];\r
86                         int numResultBlocks = 0;\r
87                         for (int j = 0; j < ecBlockArray.Length; j++)\r
88                         {\r
89                                 Version.ECB ecBlock = ecBlockArray[j];\r
90                                 for (int i = 0; i < ecBlock.Count; i++)\r
91                                 {\r
92                                         int numDataCodewords = ecBlock.DataCodewords;\r
93                                         int numBlockCodewords = ecBlocks.ECCodewords + numDataCodewords;\r
94                                         result[numResultBlocks++] = new DataBlock(numDataCodewords, new sbyte[numBlockCodewords]);\r
95                                 }\r
96                         }\r
97                         \r
98                         // All blocks have the same amount of data, except that the last n\r
99                         // (where n may be 0) have 1 less byte. Figure out where these start.\r
100                         // TODO(bbrown): There is only one case where there is a difference for Data Matrix for size 144\r
101                         int longerBlocksTotalCodewords = result[0].codewords.Length;\r
102                         //int shorterBlocksTotalCodewords = longerBlocksTotalCodewords - 1;\r
103                         \r
104                         int longerBlocksNumDataCodewords = longerBlocksTotalCodewords - ecBlocks.ECCodewords;\r
105                         int shorterBlocksNumDataCodewords = longerBlocksNumDataCodewords - 1;\r
106                         // The last elements of result may be 1 element shorter for 144 matrix\r
107                         // first fill out as many elements as all of them have minus 1\r
108                         int rawCodewordsOffset = 0;\r
109                         for (int i = 0; i < shorterBlocksNumDataCodewords; i++)\r
110                         {\r
111                                 for (int j = 0; j < numResultBlocks; j++)\r
112                                 {\r
113                                         result[j].codewords[i] = rawCodewords[rawCodewordsOffset++];\r
114                                 }\r
115                         }\r
116                         \r
117                         // Fill out the last data block in the longer ones\r
118                         bool specialVersion = version.VersionNumber == 24;\r
119                         int numLongerBlocks = specialVersion?8:numResultBlocks;\r
120                         for (int j = 0; j < numLongerBlocks; j++)\r
121                         {\r
122                                 result[j].codewords[longerBlocksNumDataCodewords - 1] = rawCodewords[rawCodewordsOffset++];\r
123                         }\r
124                         \r
125                         // Now add in error correction blocks\r
126                         int max = result[0].codewords.Length;\r
127                         for (int i = longerBlocksNumDataCodewords; i < max; i++)\r
128                         {\r
129                                 for (int j = 0; j < numResultBlocks; j++)\r
130                                 {\r
131                                         int iOffset = (specialVersion && j > 7)?i - 1:i;\r
132                                         result[j].codewords[iOffset] = rawCodewords[rawCodewordsOffset++];\r
133                                 }\r
134                         }\r
135                         \r
136                         if (rawCodewordsOffset != rawCodewords.Length)\r
137                         {\r
138                                 throw new System.ArgumentException();\r
139                         }\r
140                         \r
141                         return result;\r
142                 }\r
143         }\r
144 }