• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2007 ZXing authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.zxing.qrcode.decoder;
18 
19 import com.google.zxing.common.BitMatrix;
20 
21 /**
22  * <p>Encapsulates data masks for the data bits in a QR code, per ISO 18004:2006 6.8. Implementations
23  * of this class can un-mask a raw BitMatrix. For simplicity, they will unmask the entire BitMatrix,
24  * including areas used for finder patterns, timing patterns, etc. These areas should be unused
25  * after the point they are unmasked anyway.</p>
26  *
27  * <p>Note that the diagram in section 6.8.1 is misleading since it indicates that i is column position
28  * and j is row position. In fact, as the text says, i is row position and j is column position.</p>
29  *
30  * @author Sean Owen
31  */
32 enum DataMask {
33 
34   // See ISO 18004:2006 6.8.1
35 
36   /**
37    * 000: mask bits for which (x + y) mod 2 == 0
38    */
DATA_MASK_000()39   DATA_MASK_000() {
40     @Override
41     boolean isMasked(int i, int j) {
42       return ((i + j) & 0x01) == 0;
43     }
44   },
45 
46   /**
47    * 001: mask bits for which x mod 2 == 0
48    */
DATA_MASK_001()49   DATA_MASK_001() {
50     @Override
51     boolean isMasked(int i, int j) {
52       return (i & 0x01) == 0;
53     }
54   },
55 
56   /**
57    * 010: mask bits for which y mod 3 == 0
58    */
DATA_MASK_010()59   DATA_MASK_010() {
60     @Override
61     boolean isMasked(int i, int j) {
62       return j % 3 == 0;
63     }
64   },
65 
66   /**
67    * 011: mask bits for which (x + y) mod 3 == 0
68    */
DATA_MASK_011()69   DATA_MASK_011() {
70     @Override
71     boolean isMasked(int i, int j) {
72       return (i + j) % 3 == 0;
73     }
74   },
75 
76   /**
77    * 100: mask bits for which (x/2 + y/3) mod 2 == 0
78    */
DATA_MASK_100()79   DATA_MASK_100() {
80     @Override
81     boolean isMasked(int i, int j) {
82       return (((i / 2) + (j / 3)) & 0x01) == 0;
83     }
84   },
85 
86   /**
87    * 101: mask bits for which xy mod 2 + xy mod 3 == 0
88    * equivalently, such that xy mod 6 == 0
89    */
DATA_MASK_101()90   DATA_MASK_101() {
91     @Override
92     boolean isMasked(int i, int j) {
93       return (i * j) % 6 == 0;
94     }
95   },
96 
97   /**
98    * 110: mask bits for which (xy mod 2 + xy mod 3) mod 2 == 0
99    * equivalently, such that xy mod 6 < 3
100    */
DATA_MASK_110()101   DATA_MASK_110() {
102     @Override
103     boolean isMasked(int i, int j) {
104       return ((i * j) % 6) < 3;
105     }
106   },
107 
108   /**
109    * 111: mask bits for which ((x+y)mod 2 + xy mod 3) mod 2 == 0
110    * equivalently, such that (x + y + xy mod 3) mod 2 == 0
111    */
DATA_MASK_111()112   DATA_MASK_111() {
113     @Override
114     boolean isMasked(int i, int j) {
115       return ((i + j + ((i * j) % 3)) & 0x01) == 0;
116     }
117   };
118 
119   // End of enum constants.
120 
121 
122   /**
123    * <p>Implementations of this method reverse the data masking process applied to a QR Code and
124    * make its bits ready to read.</p>
125    *
126    * @param bits representation of QR Code bits
127    * @param dimension dimension of QR Code, represented by bits, being unmasked
128    */
unmaskBitMatrix(BitMatrix bits, int dimension)129   final void unmaskBitMatrix(BitMatrix bits, int dimension) {
130     for (int i = 0; i < dimension; i++) {
131       for (int j = 0; j < dimension; j++) {
132         if (isMasked(i, j)) {
133           bits.flip(j, i);
134         }
135       }
136     }
137   }
138 
isMasked(int i, int j)139   abstract boolean isMasked(int i, int j);
140 
141 }
142