2 * Copyright 2007 Google Inc.
\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
8 * http://www.apache.org/licenses/LICENSE-2.0
\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
17 package com.google.zxing.qrcode.decoder;
\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
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
28 * @author srowen@google.com (Sean Owen)
\r
30 abstract class DataMask {
\r
33 * See ISO 18004:2006 6.8.1
\r
35 private static final DataMask[] DATA_MASKS = new DataMask[]{
\r
46 private DataMask() {
\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
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
56 abstract void unmaskBitMatrix(int[] bits, int dimension);
\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
63 static DataMask forReference(int reference) {
\r
64 if (reference < 0 || reference > 7) {
\r
65 throw new IllegalArgumentException();
\r
67 return DATA_MASKS[reference];
\r
71 * 000: mask bits for which (i + j) mod 2 == 0
\r
73 private static class DataMask000 extends DataMask {
\r
74 private static final int BITMASK = 0x55555555; // = 010101...
\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
87 * 001: mask bits for which i mod 2 == 0
\r
89 private static class DataMask001 extends DataMask {
\r
90 void unmaskBitMatrix(int[] bits, int dimension) {
\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
99 if (++count == 32) {
\r
100 bits[offset++] ^= bitMask;
\r
106 bits[offset] ^= bitMask;
\r
111 * 010: mask bits for which j mod 3 == 0
\r
113 private static class DataMask010 extends DataMask {
\r
114 void unmaskBitMatrix(int[] bits, int dimension) {
\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
124 if (++count == 32) {
\r
125 bits[offset++] ^= bitMask;
\r
131 bits[offset] ^= bitMask;
\r
136 * 011: mask bits for which (i + j) mod 3 == 0
\r
138 private static class DataMask011 extends DataMask {
\r
139 void unmaskBitMatrix(int[] bits, int dimension) {
\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
148 if (++count == 32) {
\r
149 bits[offset++] ^= bitMask;
\r
155 bits[offset] ^= bitMask;
\r
160 * 100: mask bits for which (i/2 + j/3) mod 2 == 0
\r
162 private static class DataMask100 extends DataMask {
\r
163 void unmaskBitMatrix(int[] bits, int dimension) {
\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
173 if (++count == 32) {
\r
174 bits[offset++] ^= bitMask;
\r
180 bits[offset] ^= bitMask;
\r
185 * 101: mask bits for which ij mod 2 + ij mod 3 == 0
\r
187 private static class DataMask101 extends DataMask {
\r
188 void unmaskBitMatrix(int[] bits, int dimension) {
\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
198 if (++count == 32) {
\r
199 bits[offset++] ^= bitMask;
\r
205 bits[offset] ^= bitMask;
\r
210 * 110: mask bits for which (ij mod 2 + ij mod 3) mod 2 == 0
\r
212 private static class DataMask110 extends DataMask {
\r
213 void unmaskBitMatrix(int[] bits, int dimension) {
\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
223 if (++count == 32) {
\r
224 bits[offset++] ^= bitMask;
\r
230 bits[offset] ^= bitMask;
\r
235 * 111: mask bits for which ((i+j)mod 2 + ij mod 3) mod 2 == 0
\r
237 private static class DataMask111 extends DataMask {
\r
238 void unmaskBitMatrix(int[] bits, int dimension) {
\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
247 if (++count == 32) {
\r
248 bits[offset++] ^= bitMask;
\r
254 bits[offset] ^= bitMask;
\r