Related to Issue 205, but not the direct issue: read both copies of the format info...
authorsrowen <srowen@59b500cc-1b3d-0410-9834-0bbf25fbcc57>
Mon, 1 Mar 2010 11:04:22 +0000 (11:04 +0000)
committersrowen <srowen@59b500cc-1b3d-0410-9834-0bbf25fbcc57>
Mon, 1 Mar 2010 11:04:22 +0000 (11:04 +0000)
git-svn-id: http://zxing.googlecode.com/svn/trunk@1226 59b500cc-1b3d-0410-9834-0bbf25fbcc57

core/src/com/google/zxing/qrcode/decoder/BitMatrixParser.java
core/src/com/google/zxing/qrcode/decoder/FormatInformation.java
core/test/src/com/google/zxing/qrcode/decoder/FormatInformationTestCase.java
javase/src/com/google/zxing/client/j2se/MatrixToImageWriter.java

index c6f79b3..2a820ec 100644 (file)
@@ -54,36 +54,31 @@ final class BitMatrixParser {
     }\r
 \r
     // Read top-left format info bits\r
-    int formatInfoBits = 0;\r
+    int formatInfoBits1 = 0;\r
     for (int i = 0; i < 6; i++) {\r
-      formatInfoBits = copyBit(i, 8, formatInfoBits);\r
+      formatInfoBits1 = copyBit(i, 8, formatInfoBits1);\r
     }\r
     // .. and skip a bit in the timing pattern ...\r
-    formatInfoBits = copyBit(7, 8, formatInfoBits);\r
-    formatInfoBits = copyBit(8, 8, formatInfoBits);\r
-    formatInfoBits = copyBit(8, 7, formatInfoBits);\r
+    formatInfoBits1 = copyBit(7, 8, formatInfoBits1);\r
+    formatInfoBits1 = copyBit(8, 8, formatInfoBits1);\r
+    formatInfoBits1 = copyBit(8, 7, formatInfoBits1);\r
     // .. and skip a bit in the timing pattern ...\r
     for (int j = 5; j >= 0; j--) {\r
-      formatInfoBits = copyBit(8, j, formatInfoBits);\r
+      formatInfoBits1 = copyBit(8, j, formatInfoBits1);\r
     }\r
 \r
-    parsedFormatInfo = FormatInformation.decodeFormatInformation(formatInfoBits);\r
-    if (parsedFormatInfo != null) {\r
-      return parsedFormatInfo;\r
-    }\r
-\r
-    // Hmm, failed. Try the top-right/bottom-left pattern\r
+    // Read the top-right/bottom-left pattern too\r
     int dimension = bitMatrix.getDimension();\r
-    formatInfoBits = 0;\r
+    int formatInfoBits2 = 0;\r
     int iMin = dimension - 8;\r
     for (int i = dimension - 1; i >= iMin; i--) {\r
-      formatInfoBits = copyBit(i, 8, formatInfoBits);\r
+      formatInfoBits2 = copyBit(i, 8, formatInfoBits2);\r
     }\r
     for (int j = dimension - 7; j < dimension; j++) {\r
-      formatInfoBits = copyBit(8, j, formatInfoBits);\r
+      formatInfoBits2 = copyBit(8, j, formatInfoBits2);\r
     }\r
 \r
-    parsedFormatInfo = FormatInformation.decodeFormatInformation(formatInfoBits);\r
+    parsedFormatInfo = FormatInformation.decodeFormatInformation(formatInfoBits1, formatInfoBits2);\r
     if (parsedFormatInfo != null) {\r
       return parsedFormatInfo;\r
     }\r
index f7980ee..1b76b0d 100644 (file)
@@ -96,37 +96,48 @@ final class FormatInformation {
   }
 
   /**
-   * @param maskedFormatInfo format info indicator, with mask still applied
+   * @param maskedFormatInfo1 format info indicator, with mask still applied
+   * @param maskedFormatInfo2 second copy of same info; both are checked at the same time
+   *  to establish best match
    * @return information about the format it specifies, or <code>null</code>
    *  if doesn't seem to match any known pattern
    */
-  static FormatInformation decodeFormatInformation(int maskedFormatInfo) {
-    FormatInformation formatInfo = doDecodeFormatInformation(maskedFormatInfo);
+  static FormatInformation decodeFormatInformation(int maskedFormatInfo1, int maskedFormatInfo2) {
+    FormatInformation formatInfo = doDecodeFormatInformation(maskedFormatInfo1, maskedFormatInfo2);
     if (formatInfo != null) {
       return formatInfo;
     }
     // Should return null, but, some QR codes apparently
     // do not mask this info. Try again by actually masking the pattern
     // first
-    return doDecodeFormatInformation(maskedFormatInfo ^ FORMAT_INFO_MASK_QR);
+    return doDecodeFormatInformation(maskedFormatInfo1 ^ FORMAT_INFO_MASK_QR,
+                                     maskedFormatInfo2 ^ FORMAT_INFO_MASK_QR);
   }
 
-  private static FormatInformation doDecodeFormatInformation(int maskedFormatInfo) {
+  private static FormatInformation doDecodeFormatInformation(int maskedFormatInfo1, int maskedFormatInfo2) {
     // Find the int in FORMAT_INFO_DECODE_LOOKUP with fewest bits differing
     int bestDifference = Integer.MAX_VALUE;
     int bestFormatInfo = 0;
     for (int i = 0; i < FORMAT_INFO_DECODE_LOOKUP.length; i++) {
       int[] decodeInfo = FORMAT_INFO_DECODE_LOOKUP[i];
       int targetInfo = decodeInfo[0];
-      if (targetInfo == maskedFormatInfo) {
+      if (targetInfo == maskedFormatInfo1 || targetInfo == maskedFormatInfo2) {
         // Found an exact match
         return new FormatInformation(decodeInfo[1]);
       }
-      int bitsDifference = numBitsDiffering(maskedFormatInfo, targetInfo);
+      int bitsDifference = numBitsDiffering(maskedFormatInfo1, targetInfo);
       if (bitsDifference < bestDifference) {
         bestFormatInfo = decodeInfo[1];
         bestDifference = bitsDifference;
       }
+      if (maskedFormatInfo1 != maskedFormatInfo2) {
+        // also try the other option
+        bitsDifference = numBitsDiffering(maskedFormatInfo2, targetInfo);
+        if (bitsDifference < bestDifference) {
+          bestFormatInfo = decodeInfo[1];
+          bestDifference = bitsDifference;
+        }
+      }
     }
     // Hamming distance of the 32 masked codes is 7, by construction, so <= 3 bits
     // differing means we found a match
index e737993..6bf1ef7 100644 (file)
@@ -35,17 +35,34 @@ public final class FormatInformationTestCase extends TestCase {
 
   public void testDecode() {
     // Normal case
-    FormatInformation expected = FormatInformation.decodeFormatInformation(MASKED_TEST_FORMAT_INFO);
+    FormatInformation expected =
+        FormatInformation.decodeFormatInformation(MASKED_TEST_FORMAT_INFO, MASKED_TEST_FORMAT_INFO);
     assertEquals((byte) 0x07, expected.getDataMask());
-    assertEquals(ErrorCorrectionLevel.Q, expected.getErrorCorrectionLevel());
+    assertSame(ErrorCorrectionLevel.Q, expected.getErrorCorrectionLevel());
     // where the code forgot the mask!
-    assertEquals(expected, FormatInformation.decodeFormatInformation(UNMASKED_TEST_FORMAT_INFO));
+    assertEquals(expected,
+                 FormatInformation.decodeFormatInformation(UNMASKED_TEST_FORMAT_INFO, MASKED_TEST_FORMAT_INFO));
+  }
 
+  public void testDecodeWithBitDifference() {
+    FormatInformation expected =
+        FormatInformation.decodeFormatInformation(MASKED_TEST_FORMAT_INFO, MASKED_TEST_FORMAT_INFO);
     // 1,2,3,4 bits difference
-    assertEquals(expected, FormatInformation.decodeFormatInformation(MASKED_TEST_FORMAT_INFO ^ 0x01));
-    assertEquals(expected, FormatInformation.decodeFormatInformation(MASKED_TEST_FORMAT_INFO ^ 0x03));
-    assertEquals(expected, FormatInformation.decodeFormatInformation(MASKED_TEST_FORMAT_INFO ^ 0x07));
-    assertNull(FormatInformation.decodeFormatInformation(MASKED_TEST_FORMAT_INFO ^ 0x0F));
+    assertEquals(expected, FormatInformation.decodeFormatInformation(
+        MASKED_TEST_FORMAT_INFO ^ 0x01, MASKED_TEST_FORMAT_INFO ^ 0x01));
+    assertEquals(expected, FormatInformation.decodeFormatInformation(
+        MASKED_TEST_FORMAT_INFO ^ 0x03, MASKED_TEST_FORMAT_INFO ^ 0x03));
+    assertEquals(expected, FormatInformation.decodeFormatInformation(
+        MASKED_TEST_FORMAT_INFO ^ 0x07, MASKED_TEST_FORMAT_INFO ^ 0x07));
+    assertNull(FormatInformation.decodeFormatInformation(
+        MASKED_TEST_FORMAT_INFO ^ 0x0F, MASKED_TEST_FORMAT_INFO ^ 0x0F));
+  }
+
+  public void testDecodeWithMisread() {
+    FormatInformation expected =
+        FormatInformation.decodeFormatInformation(MASKED_TEST_FORMAT_INFO, MASKED_TEST_FORMAT_INFO);
+    assertEquals(expected, FormatInformation.decodeFormatInformation(
+        MASKED_TEST_FORMAT_INFO ^ 0x03, MASKED_TEST_FORMAT_INFO ^ 0x0F));
   }
 
 }
\ No newline at end of file
index 3c82a56..4a65de1 100644 (file)
@@ -68,7 +68,7 @@ public final class MatrixToImageWriter {
     BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
     for (int x = 0; x < width; x++) {
       for (int y = 0; y < height; y++) {
-        image.setRGB(x, y, matrix.get(x, y) == 0 ? BLACK : WHITE);
+        image.setRGB(x, y, matrix.get(x, y) == 0 ? WHITE : BLACK);
       }
     }
     return image;