68f1b67e6a4d695ee23993a3ba6b5f42de7a841e
[zxing.git] / src / com / google / zxing / qrcode / decoder / DataMask.java
1 /*\r
2  * Copyright 2007 Google Inc.\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 package com.google.zxing.qrcode.decoder;\r
18 \r
19 /**\r
20  * Encapsulates data masks for the data bits in a QR code, per ISO 18004:2006 6.8. Implementations\r
21  * of this class can un-mask a raw BitMatrix. For simplicity, they will unmask the entire BitMatrix,\r
22  * including areas used for finder patterns, timing patterns, etc. These areas should be unused\r
23  * after the point they are unmasked anyway.\r
24  *\r
25  * Note that the diagram in section 6.8.1 is misleading since it indicates that i is column position\r
26  * and j is row position. In fact, as the text says, i is row position and j is column position.\r
27  *\r
28  * @author srowen@google.com (Sean Owen)\r
29  */\r
30 abstract class DataMask {\r
31 \r
32   /**\r
33    * See ISO 18004:2006 6.8.1\r
34    */\r
35   private static final DataMask[] DATA_MASKS = new DataMask[]{\r
36       new DataMask000(),\r
37       new DataMask001(),\r
38       new DataMask010(),\r
39       new DataMask011(),\r
40       new DataMask100(),\r
41       new DataMask101(),\r
42       new DataMask110(),\r
43       new DataMask111(),\r
44   };\r
45 \r
46   private DataMask() {\r
47   }\r
48 \r
49   abstract void unmaskBitMatrix(int[] bits, int dimension);\r
50 \r
51   static DataMask forReference(int reference) {\r
52     if (reference < 0 || reference > 7) {\r
53       throw new IllegalArgumentException();\r
54     }\r
55     return DATA_MASKS[reference];\r
56   }\r
57 \r
58   /**\r
59    * 000: mask bits for which (i + j) mod 2 == 0\r
60    */\r
61   private static class DataMask000 extends DataMask {\r
62     private static final int BITMASK = 0x55555555; // = 010101...\r
63 \r
64     void unmaskBitMatrix(int[] bits, int dimension) {\r
65       // This one's easy. Because the dimension of BitMatrix is always odd,\r
66       // we can merely flip every other bit\r
67       int max = bits.length;\r
68       for (int i = 0; i < max; i++) {\r
69         bits[i] ^= BITMASK;\r
70       }\r
71     }\r
72   }\r
73 \r
74   /**\r
75    * 001: mask bits for which j mod 2 == 0\r
76    */\r
77   private static class DataMask001 extends DataMask {\r
78     void unmaskBitMatrix(int[] bits, int dimension) {\r
79       int bitMask = 0;\r
80       int count = 0;\r
81       int offset = 0;\r
82       for (int j = 0; j < dimension; j++) {\r
83         for (int i = 0; i < dimension; i++) {\r
84           if ((i & 0x01) == 0) {\r
85             bitMask |= 1 << count;\r
86           }\r
87           if (++count == 32) {\r
88             bits[offset++] ^= bitMask;\r
89             count = 0;\r
90             bitMask = 0;\r
91           }\r
92         }\r
93       }\r
94       bits[offset] ^= bitMask;\r
95     }\r
96   }\r
97 \r
98   /**\r
99    * 010: mask bits for which j mod 3 == 0\r
100    */\r
101   private static class DataMask010 extends DataMask {\r
102     void unmaskBitMatrix(int[] bits, int dimension) {\r
103       int bitMask = 0;\r
104       int count = 0;\r
105       int offset = 0;\r
106       for (int j = 0; j < dimension; j++) {\r
107         boolean columnMasked = j % 3 == 0;\r
108         for (int i = 0; i < dimension; i++) {\r
109           if (columnMasked) {\r
110             bitMask |= 1 << count;\r
111           }\r
112           if (++count == 32) {\r
113             bits[offset++] ^= bitMask;\r
114             count = 0;\r
115             bitMask = 0;\r
116           }\r
117         }\r
118       }\r
119       bits[offset] ^= bitMask;\r
120     }\r
121   }\r
122 \r
123   /**\r
124    * 011: mask bits for which (i + j) mod 3 == 0\r
125    */\r
126   private static class DataMask011 extends DataMask {\r
127     void unmaskBitMatrix(int[] bits, int dimension) {\r
128       int bitMask = 0;\r
129       int count = 0;\r
130       int offset = 0;\r
131       for (int j = 0; j < dimension; j++) {\r
132         for (int i = 0; i < dimension; i++) {\r
133           if ((i + j) % 3 == 0) {\r
134             bitMask |= 1 << count;\r
135           }\r
136           if (++count == 32) {\r
137             bits[offset++] ^= bitMask;\r
138             count = 0;\r
139             bitMask = 0;\r
140           }\r
141         }\r
142       }\r
143       bits[offset] ^= bitMask;\r
144     }\r
145   }\r
146 \r
147   /**\r
148    * 100: mask bits for which (i/2 + j/3) mod 2 == 0\r
149    */\r
150   private static class DataMask100 extends DataMask {\r
151     void unmaskBitMatrix(int[] bits, int dimension) {\r
152       int bitMask = 0;\r
153       int count = 0;\r
154       int offset = 0;\r
155       for (int j = 0; j < dimension; j++) {\r
156         int jComponent = j / 3;\r
157         for (int i = 0; i < dimension; i++) {\r
158           if (((i >> 1 + jComponent) & 0x01) == 0) {\r
159             bitMask |= 1 << count;\r
160           }\r
161           if (++count == 32) {\r
162             bits[offset++] ^= bitMask;\r
163             count = 0;\r
164             bitMask = 0;\r
165           }\r
166         }\r
167       }\r
168       bits[offset] ^= bitMask;\r
169     }\r
170   }\r
171 \r
172   /**\r
173    * 101: mask bits for which ij mod 2 + ij mod 3 == 0\r
174    */\r
175   private static class DataMask101 extends DataMask {\r
176     void unmaskBitMatrix(int[] bits, int dimension) {\r
177       int bitMask = 0;\r
178       int count = 0;\r
179       int offset = 0;\r
180       for (int j = 0; j < dimension; j++) {\r
181         for (int i = 0; i < dimension; i++) {\r
182           int product = i * j;\r
183           if (((product & 0x01) == 0) && product % 3 == 0) {\r
184             bitMask |= 1 << count;\r
185           }\r
186           if (++count == 32) {\r
187             bits[offset++] ^= bitMask;\r
188             count = 0;\r
189             bitMask = 0;\r
190           }\r
191         }\r
192       }\r
193       bits[offset] ^= bitMask;\r
194     }\r
195   }\r
196 \r
197   /**\r
198    * 110: mask bits for which (ij mod 2 + ij mod 3) mod 2 == 0\r
199    */\r
200   private static class DataMask110 extends DataMask {\r
201     void unmaskBitMatrix(int[] bits, int dimension) {\r
202       int bitMask = 0;\r
203       int count = 0;\r
204       int offset = 0;\r
205       for (int j = 0; j < dimension; j++) {\r
206         for (int i = 0; i < dimension; i++) {\r
207           int product = i * j;\r
208           if ((((product & 0x01) + product % 3) & 0x01) == 0) {\r
209             bitMask |= 1 << count;\r
210           }\r
211           if (++count == 32) {\r
212             bits[offset++] ^= bitMask;\r
213             count = 0;\r
214             bitMask = 0;\r
215           }\r
216         }\r
217       }\r
218       bits[offset] ^= bitMask;\r
219     }\r
220   }\r
221 \r
222   /**\r
223    * 111: mask bits for which ((i+j)mod 2 + ij mod 3) mod 2 == 0\r
224    */\r
225   private static class DataMask111 extends DataMask {\r
226     void unmaskBitMatrix(int[] bits, int dimension) {\r
227       int bitMask = 0;\r
228       int count = 0;\r
229       int offset = 0;\r
230       for (int j = 0; j < dimension; j++) {\r
231         for (int i = 0; i < dimension; i++) {\r
232           if (((((i + j) & 0x01) + (i * j) % 3) & 0x01) == 0) {\r
233             bitMask |= 1 << count;\r
234           }\r
235           if (++count == 32) {\r
236             bits[offset++] ^= bitMask;\r
237             count = 0;\r
238             bitMask = 0;\r
239           }\r
240         }\r
241       }\r
242       bits[offset] ^= bitMask;\r
243     }\r
244   }\r
245 }\r