Added rendering fix from beyonddeath
[zxing.git] / csharp / qrcode / decoder / DataMask.cs
1 /*\r
2 * Licensed under the Apache License, Version 2.0 (the "License");\r
3 * you may not use this file except in compliance with the License.\r
4 * You may obtain a copy of the License at\r
5 *\r
6 *      http://www.apache.org/licenses/LICENSE-2.0\r
7 *\r
8 * Unless required by applicable law or agreed to in writing, software\r
9 * distributed under the License is distributed on an "AS IS" BASIS,\r
10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
11 * See the License for the specific language governing permissions and\r
12 * limitations under the License.\r
13 */\r
14 \r
15 using System;\r
16 namespace com.google.zxing.qrcode.decoder\r
17 {\r
18 \r
19     /// <summary> <p>Encapsulates data masks for the data bits in a QR code, per ISO 18004:2006 6.8. Implementations\r
20     /// of this class can un-mask a raw BitMatrix. For simplicity, they will unmask the entire BitMatrix,\r
21     /// including areas used for finder patterns, timing patterns, etc. These areas should be unused\r
22     /// after the point they are unmasked anyway.</p>\r
23     /// \r
24     /// <p>Note that the diagram in section 6.8.1 is misleading since it indicates that i is column position\r
25     /// and j is row position. In fact, as the text says, i is row position and j is column position.</p>\r
26     /// \r
27     /// </summary>\r
28     /// <author>  srowen@google.com (Sean Owen)\r
29     /// </author>\r
30     abstract class DataMask\r
31     {\r
32 \r
33         /// <summary> See ISO 18004:2006 6.8.1</summary>\r
34         //UPGRADE_NOTE: Final was removed from the declaration of 'DATA_MASKS '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"\r
35         private static readonly DataMask[] DATA_MASKS = new DataMask[] { new DataMask000(), new DataMask001(), new DataMask010(), new DataMask011(), new DataMask100(), new DataMask101(), new DataMask110(), new DataMask111() };\r
36 \r
37         private DataMask()\r
38         {\r
39         }\r
40 \r
41         /// <summary> <p>Implementations of this method reverse the data masking process applied to a QR Code and\r
42         /// make its bits ready to read.</p>\r
43         /// \r
44         /// </summary>\r
45         /// <param name="bits">representation of QR Code bits from {@link com.google.zxing.common.BitMatrix#getBits()}\r
46         /// </param>\r
47         /// <param name="dimension">dimension of QR Code, represented by bits, being unmasked\r
48         /// </param>\r
49         internal abstract void unmaskBitMatrix(int[] bits, int dimension);\r
50 \r
51         /// <param name="reference">a value between 0 and 7 indicating one of the eight possible\r
52         /// data mask patterns a QR Code may use\r
53         /// </param>\r
54         /// <returns> {@link DataMask} encapsulating the data mask pattern\r
55         /// </returns>\r
56         internal static DataMask forReference(int reference)\r
57         {\r
58             if (reference < 0 || reference > 7)\r
59             {\r
60                 throw new System.ArgumentException();\r
61             }\r
62             return DATA_MASKS[reference];\r
63         }\r
64 \r
65         /// <summary> 000: mask bits for which (i + j) mod 2 == 0</summary>\r
66         private class DataMask000 : DataMask\r
67         {\r
68             private const int BITMASK = 0x55555555; // = 010101...\r
69 \r
70             internal override void unmaskBitMatrix(int[] bits, int dimension)\r
71             {\r
72                 // This one's easy. Because the dimension of BitMatrix is always odd,\r
73                 // we can merely flip every other bit\r
74                 int max = bits.Length;\r
75                 for (int i = 0; i < max; i++)\r
76                 {\r
77                     bits[i] ^= BITMASK;\r
78                 }\r
79             }\r
80         }\r
81 \r
82         /// <summary> 001: mask bits for which i mod 2 == 0</summary>\r
83         private class DataMask001 : DataMask\r
84         {\r
85             internal override void unmaskBitMatrix(int[] bits, int dimension)\r
86             {\r
87                 int bitMask = 0;\r
88                 int count = 0;\r
89                 int offset = 0;\r
90                 for (int j = 0; j < dimension; j++)\r
91                 {\r
92                     for (int i = 0; i < dimension; i++)\r
93                     {\r
94                         if ((i & 0x01) == 0)\r
95                         {\r
96                             bitMask |= 1 << count;\r
97                         }\r
98                         if (++count == 32)\r
99                         {\r
100                             bits[offset++] ^= bitMask;\r
101                             count = 0;\r
102                             bitMask = 0;\r
103                         }\r
104                     }\r
105                 }\r
106                 bits[offset] ^= bitMask;\r
107             }\r
108         }\r
109 \r
110         /// <summary> 010: mask bits for which j mod 3 == 0</summary>\r
111         private class DataMask010 : DataMask\r
112         {\r
113             internal override void unmaskBitMatrix(int[] bits, int dimension)\r
114             {\r
115                 int bitMask = 0;\r
116                 int count = 0;\r
117                 int offset = 0;\r
118                 for (int j = 0; j < dimension; j++)\r
119                 {\r
120                     bool columnMasked = j % 3 == 0;\r
121                     for (int i = 0; i < dimension; i++)\r
122                     {\r
123                         if (columnMasked)\r
124                         {\r
125                             bitMask |= 1 << count;\r
126                         }\r
127                         if (++count == 32)\r
128                         {\r
129                             bits[offset++] ^= bitMask;\r
130                             count = 0;\r
131                             bitMask = 0;\r
132                         }\r
133                     }\r
134                 }\r
135                 bits[offset] ^= bitMask;\r
136             }\r
137         }\r
138 \r
139         /// <summary> 011: mask bits for which (i + j) mod 3 == 0</summary>\r
140         private class DataMask011 : DataMask\r
141         {\r
142             internal override void unmaskBitMatrix(int[] bits, int dimension)\r
143             {\r
144                 int bitMask = 0;\r
145                 int count = 0;\r
146                 int offset = 0;\r
147                 for (int j = 0; j < dimension; j++)\r
148                 {\r
149                     for (int i = 0; i < dimension; i++)\r
150                     {\r
151                         if ((i + j) % 3 == 0)\r
152                         {\r
153                             bitMask |= 1 << count;\r
154                         }\r
155                         if (++count == 32)\r
156                         {\r
157                             bits[offset++] ^= bitMask;\r
158                             count = 0;\r
159                             bitMask = 0;\r
160                         }\r
161                     }\r
162                 }\r
163                 bits[offset] ^= bitMask;\r
164             }\r
165         }\r
166 \r
167         /// <summary> 100: mask bits for which (i/2 + j/3) mod 2 == 0</summary>\r
168         private class DataMask100 : DataMask\r
169         {\r
170             internal override void unmaskBitMatrix(int[] bits, int dimension)\r
171             {\r
172                 int bitMask = 0;\r
173                 int count = 0;\r
174                 int offset = 0;\r
175                 for (int j = 0; j < dimension; j++)\r
176                 {\r
177                     int jComponentParity = (j / 3) & 0x01;\r
178                     for (int i = 0; i < dimension; i++)\r
179                     {\r
180                         if (((i >> 1) & 0x01) == jComponentParity)\r
181                         {\r
182                             bitMask |= 1 << count;\r
183                         }\r
184                         if (++count == 32)\r
185                         {\r
186                             bits[offset++] ^= bitMask;\r
187                             count = 0;\r
188                             bitMask = 0;\r
189                         }\r
190                     }\r
191                 }\r
192                 bits[offset] ^= bitMask;\r
193             }\r
194         }\r
195 \r
196         /// <summary> 101: mask bits for which ij mod 2 + ij mod 3 == 0</summary>\r
197         private class DataMask101 : DataMask\r
198         {\r
199             internal override void unmaskBitMatrix(int[] bits, int dimension)\r
200             {\r
201                 int bitMask = 0;\r
202                 int count = 0;\r
203                 int offset = 0;\r
204                 for (int j = 0; j < dimension; j++)\r
205                 {\r
206                     for (int i = 0; i < dimension; i++)\r
207                     {\r
208                         int product = i * j;\r
209                         if (((product & 0x01) == 0) && product % 3 == 0)\r
210                         {\r
211                             bitMask |= 1 << count;\r
212                         }\r
213                         if (++count == 32)\r
214                         {\r
215                             bits[offset++] ^= bitMask;\r
216                             count = 0;\r
217                             bitMask = 0;\r
218                         }\r
219                     }\r
220                 }\r
221                 bits[offset] ^= bitMask;\r
222             }\r
223         }\r
224 \r
225         /// <summary> 110: mask bits for which (ij mod 2 + ij mod 3) mod 2 == 0</summary>\r
226         private class DataMask110 : DataMask\r
227         {\r
228             internal override void unmaskBitMatrix(int[] bits, int dimension)\r
229             {\r
230                 int bitMask = 0;\r
231                 int count = 0;\r
232                 int offset = 0;\r
233                 for (int j = 0; j < dimension; j++)\r
234                 {\r
235                     for (int i = 0; i < dimension; i++)\r
236                     {\r
237                         int product = i * j;\r
238                         if ((((product & 0x01) + product % 3) & 0x01) == 0)\r
239                         {\r
240                             bitMask |= 1 << count;\r
241                         }\r
242                         if (++count == 32)\r
243                         {\r
244                             bits[offset++] ^= bitMask;\r
245                             count = 0;\r
246                             bitMask = 0;\r
247                         }\r
248                     }\r
249                 }\r
250                 bits[offset] ^= bitMask;\r
251             }\r
252         }\r
253 \r
254         /// <summary> 111: mask bits for which ((i+j)mod 2 + ij mod 3) mod 2 == 0</summary>\r
255         private class DataMask111 : DataMask\r
256         {\r
257             internal override void unmaskBitMatrix(int[] bits, int dimension)\r
258             {\r
259                 int bitMask = 0;\r
260                 int count = 0;\r
261                 int offset = 0;\r
262                 for (int j = 0; j < dimension; j++)\r
263                 {\r
264                     for (int i = 0; i < dimension; i++)\r
265                     {\r
266                         if (((((i + j) & 0x01) + (i * j) % 3) & 0x01) == 0)\r
267                         {\r
268                             bitMask |= 1 << count;\r
269                         }\r
270                         if (++count == 32)\r
271                         {\r
272                             bits[offset++] ^= bitMask;\r
273                             count = 0;\r
274                             bitMask = 0;\r
275                         }\r
276                     }\r
277                 }\r
278                 bits[offset] ^= bitMask;\r
279             }\r
280         }\r
281     }\r
282 }