diff --git a/cpp/core/src/zxing/qrcode/FormatInformation.cpp b/cpp/core/src/zxing/qrcode/FormatInformation.cpp index 41332fb0f..6f04de890 100644 --- a/cpp/core/src/zxing/qrcode/FormatInformation.cpp +++ b/cpp/core/src/zxing/qrcode/FormatInformation.cpp @@ -59,32 +59,42 @@ int FormatInformation::numBitsDiffering(unsigned int a, unsigned int b) { + BITS_SET_IN_HALF_BYTE[(a >> 28 & 0x0F)]; } -Ref FormatInformation::decodeFormatInformation(int rawFormatInfo) { - Ref result(doDecodeFormatInformation(rawFormatInfo)); +Ref FormatInformation::decodeFormatInformation(int maskedFormatInfo1, int maskedFormatInfo2) { + Ref result(doDecodeFormatInformation(maskedFormatInfo1, maskedFormatInfo2)); if (result != 0) { return result; } - return doDecodeFormatInformation(rawFormatInfo ^ FORMAT_INFO_MASK_QR); + // Should return null, but, some QR codes apparently + // do not mask this info. Try again by actually masking the pattern + // first + return doDecodeFormatInformation(maskedFormatInfo1 ^ FORMAT_INFO_MASK_QR, + maskedFormatInfo2 ^ FORMAT_INFO_MASK_QR); } -Ref FormatInformation::doDecodeFormatInformation(int rawFormatInfo) { - // Unmask: - int unmaskedFormatInfo = rawFormatInfo ^ FORMAT_INFO_MASK_QR; +Ref FormatInformation::doDecodeFormatInformation(int maskedFormatInfo1, int maskedFormatInfo2) { // Find the int in FORMAT_INFO_DECODE_LOOKUP with fewest bits differing int bestDifference = numeric_limits::max(); int bestFormatInfo = 0; for (int i = 0; i < N_FORMAT_INFO_DECODE_LOOKUPS; i++) { int* decodeInfo = FORMAT_INFO_DECODE_LOOKUP[i]; int targetInfo = decodeInfo[0]; - if (targetInfo == unmaskedFormatInfo) { + if (targetInfo == maskedFormatInfo1 || targetInfo == maskedFormatInfo2) { // Found an exact match Ref result(new FormatInformation(decodeInfo[1])); return result; } - int bitsDifference = numBitsDiffering(unmaskedFormatInfo, 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; + } + } } if (bestDifference <= 3) { Ref result(new FormatInformation(bestFormatInfo)); diff --git a/cpp/core/src/zxing/qrcode/FormatInformation.h b/cpp/core/src/zxing/qrcode/FormatInformation.h index 39bfb5482..5a07bbbca 100644 --- a/cpp/core/src/zxing/qrcode/FormatInformation.h +++ b/cpp/core/src/zxing/qrcode/FormatInformation.h @@ -41,8 +41,8 @@ private: public: static int numBitsDiffering(unsigned int a, unsigned int b); - static Ref decodeFormatInformation(int rawFormatInfo); - static Ref doDecodeFormatInformation(int rawFormatInfo); + static Ref decodeFormatInformation(int maskedFormatInfo1, int maskedFormatInfo2); + static Ref doDecodeFormatInformation(int maskedFormatInfo1, int maskedFormatInfo2); ErrorCorrectionLevel &getErrorCorrectionLevel(); unsigned char getDataMask(); friend bool operator==(const FormatInformation &a, const FormatInformation &b); diff --git a/cpp/core/src/zxing/qrcode/decoder/BitMatrixParser.cpp b/cpp/core/src/zxing/qrcode/decoder/BitMatrixParser.cpp index 3e3a5ffab..8554a1cd3 100644 --- a/cpp/core/src/zxing/qrcode/decoder/BitMatrixParser.cpp +++ b/cpp/core/src/zxing/qrcode/decoder/BitMatrixParser.cpp @@ -43,36 +43,31 @@ Ref BitMatrixParser::readFormatInformation() { } // Read top-left format info bits - int formatInfoBits = 0; - for (int x = 0; x < 6; x++) { - formatInfoBits = copyBit(x, 8, formatInfoBits); + int formatInfoBits1 = 0; + for (int i = 0; i < 6; i++) { + formatInfoBits1 = copyBit(i, 8, formatInfoBits1); } // .. and skip a bit in the timing pattern ... - formatInfoBits = copyBit(7, 8, formatInfoBits); - formatInfoBits = copyBit(8, 8, formatInfoBits); - formatInfoBits = copyBit(8, 7, formatInfoBits); + formatInfoBits1 = copyBit(7, 8, formatInfoBits1); + formatInfoBits1 = copyBit(8, 8, formatInfoBits1); + formatInfoBits1 = copyBit(8, 7, formatInfoBits1); // .. and skip a bit in the timing pattern ... - for (int y = 5; y >= 0; y--) { - formatInfoBits = copyBit(8, y, formatInfoBits); + for (int j = 5; j >= 0; j--) { + formatInfoBits1 = copyBit(8, j, formatInfoBits1); } - parsedFormatInfo_ = FormatInformation::decodeFormatInformation(formatInfoBits); - if (parsedFormatInfo_ != 0) { - return parsedFormatInfo_; - } - - // Hmm, failed. Try the top-right/bottom-left pattern + // Read the top-right/bottom-left pattern int dimension = bitMatrix_->getDimension(); - formatInfoBits = 0; - int yMin = dimension - 8; - for (int y = dimension - 1; y >= yMin; y--) { - formatInfoBits = copyBit(8, y, formatInfoBits); + int formatInfoBits2 = 0; + int jMin = dimension - 7; + for (int j = dimension - 1; j >= jMin; j--) { + formatInfoBits2 = copyBit(8, j, formatInfoBits2); } - for (int x = dimension - 7; x < dimension; x++) { - formatInfoBits = copyBit(x, 8, formatInfoBits); + for (int i = dimension - 8; i < dimension; i++) { + formatInfoBits2 = copyBit(i, 8, formatInfoBits2); } - parsedFormatInfo_ = FormatInformation::decodeFormatInformation(formatInfoBits); + parsedFormatInfo_ = FormatInformation::decodeFormatInformation(formatInfoBits1,formatInfoBits2); if (parsedFormatInfo_ != 0) { return parsedFormatInfo_; }