From: srowen Date: Mon, 14 Sep 2009 10:17:17 +0000 (+0000) Subject: Fix for old logic error in seeking format information -- actually was comparing unmas... X-Git-Url: http://git.rot13.org/?a=commitdiff_plain;ds=sidebyside;h=5d8e988365f63fe7217eddc2ebaeedbf51b60ef2;p=zxing.git Fix for old logic error in seeking format information -- actually was comparing unmasked rather than masked values, though it ended up working git-svn-id: http://zxing.googlecode.com/svn/trunk@1052 59b500cc-1b3d-0410-9834-0bbf25fbcc57 --- diff --git a/core/src/com/google/zxing/qrcode/decoder/FormatInformation.java b/core/src/com/google/zxing/qrcode/decoder/FormatInformation.java index 299768c2..f7980ee7 100644 --- a/core/src/com/google/zxing/qrcode/decoder/FormatInformation.java +++ b/core/src/com/google/zxing/qrcode/decoder/FormatInformation.java @@ -96,39 +96,40 @@ final class FormatInformation { } /** - * @param rawFormatInfo - * @return + * @param maskedFormatInfo format info indicator, with mask still applied + * @return information about the format it specifies, or null + * if doesn't seem to match any known pattern */ - static FormatInformation decodeFormatInformation(int rawFormatInfo) { - FormatInformation formatInfo = doDecodeFormatInformation(rawFormatInfo); + static FormatInformation decodeFormatInformation(int maskedFormatInfo) { + FormatInformation formatInfo = doDecodeFormatInformation(maskedFormatInfo); if (formatInfo != null) { return formatInfo; } // Should return null, but, some QR codes apparently - // do not mask this info. Try again, first masking the raw bits so - // the function will unmask - return doDecodeFormatInformation(rawFormatInfo ^ FORMAT_INFO_MASK_QR); + // do not mask this info. Try again by actually masking the pattern + // first + return doDecodeFormatInformation(maskedFormatInfo ^ FORMAT_INFO_MASK_QR); } - private static FormatInformation doDecodeFormatInformation(int rawFormatInfo) { - // Unmask: - int unmaskedFormatInfo = rawFormatInfo ^ FORMAT_INFO_MASK_QR; + private static FormatInformation doDecodeFormatInformation(int maskedFormatInfo) { // 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 == unmaskedFormatInfo) { + if (targetInfo == maskedFormatInfo) { // Found an exact match return new FormatInformation(decodeInfo[1]); } - int bitsDifference = numBitsDiffering(unmaskedFormatInfo, targetInfo); + int bitsDifference = numBitsDiffering(maskedFormatInfo, 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 if (bestDifference <= 3) { return new FormatInformation(bestFormatInfo); } diff --git a/core/test/src/com/google/zxing/qrcode/decoder/FormatInformationTestCase.java b/core/test/src/com/google/zxing/qrcode/decoder/FormatInformationTestCase.java index 99acb473..e737993e 100644 --- a/core/test/src/com/google/zxing/qrcode/decoder/FormatInformationTestCase.java +++ b/core/test/src/com/google/zxing/qrcode/decoder/FormatInformationTestCase.java @@ -16,7 +16,6 @@ package com.google.zxing.qrcode.decoder; -import com.google.zxing.ReaderException; import junit.framework.TestCase; /** @@ -24,6 +23,9 @@ import junit.framework.TestCase; */ public final class FormatInformationTestCase extends TestCase { + private static final int MASKED_TEST_FORMAT_INFO = 0x2BED; + private static final int UNMASKED_TEST_FORMAT_INFO = MASKED_TEST_FORMAT_INFO ^ 0x5412; + public void testBitsDiffering() { assertEquals(0, FormatInformation.numBitsDiffering(1, 1)); assertEquals(1, FormatInformation.numBitsDiffering(0, 2)); @@ -31,19 +33,19 @@ public final class FormatInformationTestCase extends TestCase { assertEquals(32, FormatInformation.numBitsDiffering(-1, 0)); } - public void testDecode() throws ReaderException { + public void testDecode() { // Normal case - FormatInformation expected = FormatInformation.decodeFormatInformation(0x2BED ^ 0x5412); + FormatInformation expected = FormatInformation.decodeFormatInformation(MASKED_TEST_FORMAT_INFO); assertEquals((byte) 0x07, expected.getDataMask()); assertEquals(ErrorCorrectionLevel.Q, expected.getErrorCorrectionLevel()); // where the code forgot the mask! - assertEquals(expected, FormatInformation.decodeFormatInformation(0x2BED)); + assertEquals(expected, FormatInformation.decodeFormatInformation(UNMASKED_TEST_FORMAT_INFO)); // 1,2,3,4 bits difference - assertEquals(expected, FormatInformation.decodeFormatInformation(0x2BEF ^ 0x5412)); - assertEquals(expected, FormatInformation.decodeFormatInformation(0x2BEE ^ 0x5412)); - assertEquals(expected, FormatInformation.decodeFormatInformation(0x2BEA ^ 0x5412)); - assertNull(FormatInformation.decodeFormatInformation(0x2BE2 ^ 0x5412)); + 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)); } } \ No newline at end of file