git-svn-id: http://zxing.googlecode.com/svn/trunk@6 59b500cc-1b3d-0410-9834-0bbf25fbcc57
[zxing.git] / core / src / com / google / zxing / qrcode / decoder / DataMask.java
diff --git a/core/src/com/google/zxing/qrcode/decoder/DataMask.java b/core/src/com/google/zxing/qrcode/decoder/DataMask.java
new file mode 100755 (executable)
index 0000000..68f1b67
--- /dev/null
@@ -0,0 +1,245 @@
+/*\r
+ * Copyright 2007 Google Inc.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *      http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+package com.google.zxing.qrcode.decoder;\r
+\r
+/**\r
+ * Encapsulates data masks for the data bits in a QR code, per ISO 18004:2006 6.8. Implementations\r
+ * of this class can un-mask a raw BitMatrix. For simplicity, they will unmask the entire BitMatrix,\r
+ * including areas used for finder patterns, timing patterns, etc. These areas should be unused\r
+ * after the point they are unmasked anyway.\r
+ *\r
+ * Note that the diagram in section 6.8.1 is misleading since it indicates that i is column position\r
+ * and j is row position. In fact, as the text says, i is row position and j is column position.\r
+ *\r
+ * @author srowen@google.com (Sean Owen)\r
+ */\r
+abstract class DataMask {\r
+\r
+  /**\r
+   * See ISO 18004:2006 6.8.1\r
+   */\r
+  private static final DataMask[] DATA_MASKS = new DataMask[]{\r
+      new DataMask000(),\r
+      new DataMask001(),\r
+      new DataMask010(),\r
+      new DataMask011(),\r
+      new DataMask100(),\r
+      new DataMask101(),\r
+      new DataMask110(),\r
+      new DataMask111(),\r
+  };\r
+\r
+  private DataMask() {\r
+  }\r
+\r
+  abstract void unmaskBitMatrix(int[] bits, int dimension);\r
+\r
+  static DataMask forReference(int reference) {\r
+    if (reference < 0 || reference > 7) {\r
+      throw new IllegalArgumentException();\r
+    }\r
+    return DATA_MASKS[reference];\r
+  }\r
+\r
+  /**\r
+   * 000: mask bits for which (i + j) mod 2 == 0\r
+   */\r
+  private static class DataMask000 extends DataMask {\r
+    private static final int BITMASK = 0x55555555; // = 010101...\r
+\r
+    void unmaskBitMatrix(int[] bits, int dimension) {\r
+      // This one's easy. Because the dimension of BitMatrix is always odd,\r
+      // we can merely flip every other bit\r
+      int max = bits.length;\r
+      for (int i = 0; i < max; i++) {\r
+        bits[i] ^= BITMASK;\r
+      }\r
+    }\r
+  }\r
+\r
+  /**\r
+   * 001: mask bits for which j mod 2 == 0\r
+   */\r
+  private static class DataMask001 extends DataMask {\r
+    void unmaskBitMatrix(int[] bits, int dimension) {\r
+      int bitMask = 0;\r
+      int count = 0;\r
+      int offset = 0;\r
+      for (int j = 0; j < dimension; j++) {\r
+        for (int i = 0; i < dimension; i++) {\r
+          if ((i & 0x01) == 0) {\r
+            bitMask |= 1 << count;\r
+          }\r
+          if (++count == 32) {\r
+            bits[offset++] ^= bitMask;\r
+            count = 0;\r
+            bitMask = 0;\r
+          }\r
+        }\r
+      }\r
+      bits[offset] ^= bitMask;\r
+    }\r
+  }\r
+\r
+  /**\r
+   * 010: mask bits for which j mod 3 == 0\r
+   */\r
+  private static class DataMask010 extends DataMask {\r
+    void unmaskBitMatrix(int[] bits, int dimension) {\r
+      int bitMask = 0;\r
+      int count = 0;\r
+      int offset = 0;\r
+      for (int j = 0; j < dimension; j++) {\r
+        boolean columnMasked = j % 3 == 0;\r
+        for (int i = 0; i < dimension; i++) {\r
+          if (columnMasked) {\r
+            bitMask |= 1 << count;\r
+          }\r
+          if (++count == 32) {\r
+            bits[offset++] ^= bitMask;\r
+            count = 0;\r
+            bitMask = 0;\r
+          }\r
+        }\r
+      }\r
+      bits[offset] ^= bitMask;\r
+    }\r
+  }\r
+\r
+  /**\r
+   * 011: mask bits for which (i + j) mod 3 == 0\r
+   */\r
+  private static class DataMask011 extends DataMask {\r
+    void unmaskBitMatrix(int[] bits, int dimension) {\r
+      int bitMask = 0;\r
+      int count = 0;\r
+      int offset = 0;\r
+      for (int j = 0; j < dimension; j++) {\r
+        for (int i = 0; i < dimension; i++) {\r
+          if ((i + j) % 3 == 0) {\r
+            bitMask |= 1 << count;\r
+          }\r
+          if (++count == 32) {\r
+            bits[offset++] ^= bitMask;\r
+            count = 0;\r
+            bitMask = 0;\r
+          }\r
+        }\r
+      }\r
+      bits[offset] ^= bitMask;\r
+    }\r
+  }\r
+\r
+  /**\r
+   * 100: mask bits for which (i/2 + j/3) mod 2 == 0\r
+   */\r
+  private static class DataMask100 extends DataMask {\r
+    void unmaskBitMatrix(int[] bits, int dimension) {\r
+      int bitMask = 0;\r
+      int count = 0;\r
+      int offset = 0;\r
+      for (int j = 0; j < dimension; j++) {\r
+        int jComponent = j / 3;\r
+        for (int i = 0; i < dimension; i++) {\r
+          if (((i >> 1 + jComponent) & 0x01) == 0) {\r
+            bitMask |= 1 << count;\r
+          }\r
+          if (++count == 32) {\r
+            bits[offset++] ^= bitMask;\r
+            count = 0;\r
+            bitMask = 0;\r
+          }\r
+        }\r
+      }\r
+      bits[offset] ^= bitMask;\r
+    }\r
+  }\r
+\r
+  /**\r
+   * 101: mask bits for which ij mod 2 + ij mod 3 == 0\r
+   */\r
+  private static class DataMask101 extends DataMask {\r
+    void unmaskBitMatrix(int[] bits, int dimension) {\r
+      int bitMask = 0;\r
+      int count = 0;\r
+      int offset = 0;\r
+      for (int j = 0; j < dimension; j++) {\r
+        for (int i = 0; i < dimension; i++) {\r
+          int product = i * j;\r
+          if (((product & 0x01) == 0) && product % 3 == 0) {\r
+            bitMask |= 1 << count;\r
+          }\r
+          if (++count == 32) {\r
+            bits[offset++] ^= bitMask;\r
+            count = 0;\r
+            bitMask = 0;\r
+          }\r
+        }\r
+      }\r
+      bits[offset] ^= bitMask;\r
+    }\r
+  }\r
+\r
+  /**\r
+   * 110: mask bits for which (ij mod 2 + ij mod 3) mod 2 == 0\r
+   */\r
+  private static class DataMask110 extends DataMask {\r
+    void unmaskBitMatrix(int[] bits, int dimension) {\r
+      int bitMask = 0;\r
+      int count = 0;\r
+      int offset = 0;\r
+      for (int j = 0; j < dimension; j++) {\r
+        for (int i = 0; i < dimension; i++) {\r
+          int product = i * j;\r
+          if ((((product & 0x01) + product % 3) & 0x01) == 0) {\r
+            bitMask |= 1 << count;\r
+          }\r
+          if (++count == 32) {\r
+            bits[offset++] ^= bitMask;\r
+            count = 0;\r
+            bitMask = 0;\r
+          }\r
+        }\r
+      }\r
+      bits[offset] ^= bitMask;\r
+    }\r
+  }\r
+\r
+  /**\r
+   * 111: mask bits for which ((i+j)mod 2 + ij mod 3) mod 2 == 0\r
+   */\r
+  private static class DataMask111 extends DataMask {\r
+    void unmaskBitMatrix(int[] bits, int dimension) {\r
+      int bitMask = 0;\r
+      int count = 0;\r
+      int offset = 0;\r
+      for (int j = 0; j < dimension; j++) {\r
+        for (int i = 0; i < dimension; i++) {\r
+          if (((((i + j) & 0x01) + (i * j) % 3) & 0x01) == 0) {\r
+            bitMask |= 1 << count;\r
+          }\r
+          if (++count == 32) {\r
+            bits[offset++] ^= bitMask;\r
+            count = 0;\r
+            bitMask = 0;\r
+          }\r
+        }\r
+      }\r
+      bits[offset] ^= bitMask;\r
+    }\r
+  }\r
+}\r