}\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
}
/**
- * @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
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
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;