d55a086665021d9ad37f5737480f2f24e74b39b3
[zxing.git] / core / 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  * <p>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.</p>\r
24  *\r
25  * <p>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.</p>\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   /**\r
50    * <p>Implementations of this method reverse the data masking process applied to a QR Code and\r
51    * make its bits ready to read.</p>\r
52    *\r
53    * @param bits representation of QR Code bits from {@link com.google.zxing.common.BitMatrix#getBits()}\r
54    * @param dimension dimension of QR Code, represented by bits, being unmasked\r
55    */\r
56   abstract void unmaskBitMatrix(int[] bits, int dimension);\r
57 \r
58   /**\r
59    * @param reference a value between 0 and 7 indicating one of the eight possible\r
60    * data mask patterns a QR Code may use\r
61    * @return {@link DataMask} encapsulating the data mask pattern\r
62    */\r
63   static DataMask forReference(int reference) {\r
64     if (reference < 0 || reference > 7) {\r
65       throw new IllegalArgumentException();\r
66     }\r
67     return DATA_MASKS[reference];\r
68   }\r
69 \r
70   /**\r
71    * 000: mask bits for which (i + j) mod 2 == 0\r
72    */\r
73   private static class DataMask000 extends DataMask {\r
74     private static final int BITMASK = 0x55555555; // = 010101...\r
75 \r
76     void unmaskBitMatrix(int[] bits, int dimension) {\r
77       // This one's easy. Because the dimension of BitMatrix is always odd,\r
78       // we can merely flip every other bit\r
79       int max = bits.length;\r
80       for (int i = 0; i < max; i++) {\r
81         bits[i] ^= BITMASK;\r
82       }\r
83     }\r
84   }\r
85 \r
86   /**\r
87    * 001: mask bits for which i mod 2 == 0\r
88    */\r
89   private static class DataMask001 extends DataMask {\r
90     void unmaskBitMatrix(int[] bits, int dimension) {\r
91       int bitMask = 0;\r
92       int count = 0;\r
93       int offset = 0;\r
94       for (int j = 0; j < dimension; j++) {\r
95         for (int i = 0; i < dimension; i++) {\r
96           if ((i & 0x01) == 0) {\r
97             bitMask |= 1 << count;\r
98           }\r
99           if (++count == 32) {\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   /**\r
111    * 010: mask bits for which j mod 3 == 0\r
112    */\r
113   private static class DataMask010 extends DataMask {\r
114     void unmaskBitMatrix(int[] bits, int dimension) {\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         boolean columnMasked = j % 3 == 0;\r
120         for (int i = 0; i < dimension; i++) {\r
121           if (columnMasked) {\r
122             bitMask |= 1 << count;\r
123           }\r
124           if (++count == 32) {\r
125             bits[offset++] ^= bitMask;\r
126             count = 0;\r
127             bitMask = 0;\r
128           }\r
129         }\r
130       }\r
131       bits[offset] ^= bitMask;\r
132     }\r
133   }\r
134 \r
135   /**\r
136    * 011: mask bits for which (i + j) mod 3 == 0\r
137    */\r
138   private static class DataMask011 extends DataMask {\r
139     void unmaskBitMatrix(int[] bits, int dimension) {\r
140       int bitMask = 0;\r
141       int count = 0;\r
142       int offset = 0;\r
143       for (int j = 0; j < dimension; j++) {\r
144         for (int i = 0; i < dimension; i++) {\r
145           if ((i + j) % 3 == 0) {\r
146             bitMask |= 1 << count;\r
147           }\r
148           if (++count == 32) {\r
149             bits[offset++] ^= bitMask;\r
150             count = 0;\r
151             bitMask = 0;\r
152           }\r
153         }\r
154       }\r
155       bits[offset] ^= bitMask;\r
156     }\r
157   }\r
158 \r
159   /**\r
160    * 100: mask bits for which (i/2 + j/3) mod 2 == 0\r
161    */\r
162   private static class DataMask100 extends DataMask {\r
163     void unmaskBitMatrix(int[] bits, int dimension) {\r
164       int bitMask = 0;\r
165       int count = 0;\r
166       int offset = 0;\r
167       for (int j = 0; j < dimension; j++) {\r
168         int jComponentParity = (j / 3) & 0x01;\r
169         for (int i = 0; i < dimension; i++) {\r
170           if (((i >> 1) & 0x01) == jComponentParity) {\r
171             bitMask |= 1 << count;\r
172           }\r
173           if (++count == 32) {\r
174             bits[offset++] ^= bitMask;\r
175             count = 0;\r
176             bitMask = 0;\r
177           }\r
178         }\r
179       }\r
180       bits[offset] ^= bitMask;\r
181     }\r
182   }\r
183 \r
184   /**\r
185    * 101: mask bits for which ij mod 2 + ij mod 3 == 0\r
186    */\r
187   private static class DataMask101 extends DataMask {\r
188     void unmaskBitMatrix(int[] bits, int dimension) {\r
189       int bitMask = 0;\r
190       int count = 0;\r
191       int offset = 0;\r
192       for (int j = 0; j < dimension; j++) {\r
193         for (int i = 0; i < dimension; i++) {\r
194           int product = i * j;\r
195           if (((product & 0x01) == 0) && product % 3 == 0) {\r
196             bitMask |= 1 << count;\r
197           }\r
198           if (++count == 32) {\r
199             bits[offset++] ^= bitMask;\r
200             count = 0;\r
201             bitMask = 0;\r
202           }\r
203         }\r
204       }\r
205       bits[offset] ^= bitMask;\r
206     }\r
207   }\r
208 \r
209   /**\r
210    * 110: mask bits for which (ij mod 2 + ij mod 3) mod 2 == 0\r
211    */\r
212   private static class DataMask110 extends DataMask {\r
213     void unmaskBitMatrix(int[] bits, int dimension) {\r
214       int bitMask = 0;\r
215       int count = 0;\r
216       int offset = 0;\r
217       for (int j = 0; j < dimension; j++) {\r
218         for (int i = 0; i < dimension; i++) {\r
219           int product = i * j;\r
220           if ((((product & 0x01) + product % 3) & 0x01) == 0) {\r
221             bitMask |= 1 << count;\r
222           }\r
223           if (++count == 32) {\r
224             bits[offset++] ^= bitMask;\r
225             count = 0;\r
226             bitMask = 0;\r
227           }\r
228         }\r
229       }\r
230       bits[offset] ^= bitMask;\r
231     }\r
232   }\r
233 \r
234   /**\r
235    * 111: mask bits for which ((i+j)mod 2 + ij mod 3) mod 2 == 0\r
236    */\r
237   private static class DataMask111 extends DataMask {\r
238     void unmaskBitMatrix(int[] bits, int dimension) {\r
239       int bitMask = 0;\r
240       int count = 0;\r
241       int offset = 0;\r
242       for (int j = 0; j < dimension; j++) {\r
243         for (int i = 0; i < dimension; i++) {\r
244           if (((((i + j) & 0x01) + (i * j) % 3) & 0x01) == 0) {\r
245             bitMask |= 1 << count;\r
246           }\r
247           if (++count == 32) {\r
248             bits[offset++] ^= bitMask;\r
249             count = 0;\r
250             bitMask = 0;\r
251           }\r
252         }\r
253       }\r
254       bits[offset] ^= bitMask;\r
255     }\r
256   }\r
257 }\r