From 6e0972273ac347430f4c413b8817083d9d4bde29 Mon Sep 17 00:00:00 2001 From: favoritas37 Date: Thu, 4 Jul 2013 16:52:02 +0300 Subject: [PATCH] finished updating the library files of zxing library. haven't complied it yet. --- source/QZXing.pro | 2 - ...FoundException.cpp => NotFoundException.h} | 19 +- source/zxing/qrcode/FormatInformation.h | 6 +- source/zxing/qrcode/QRCodeReader.cpp | 38 +- source/zxing/qrcode/QRCodeReader.h | 25 +- source/zxing/qrcode/QRFormatInformation.cpp | 7 +- source/zxing/qrcode/QRVersion.cpp | 21 +- source/zxing/qrcode/decoder/BitMatrixParser.h | 2 +- source/zxing/qrcode/decoder/DataBlock.h | 8 +- .../qrcode/decoder/DecodedBitStreamParser.h | 6 +- source/zxing/qrcode/decoder/Decoder.h | 2 +- source/zxing/qrcode/decoder/Mode.h | 1 - .../qrcode/decoder/QRBitMatrixParser.cpp | 17 +- source/zxing/qrcode/decoder/QRDataBlock.cpp | 16 +- .../decoder/QRDecodedBitStreamParser.cpp | 579 +++++++++--------- source/zxing/qrcode/decoder/QRDecoder.cpp | 33 +- source/zxing/qrcode/decoder/QRMode.cpp | 64 +- .../qrcode/detector/AlignmentPatternFinder.h | 14 +- source/zxing/qrcode/detector/Detector.h | 9 +- source/zxing/qrcode/detector/FinderPattern.h | 3 +- .../qrcode/detector/FinderPatternFinder.h | 5 + .../qrcode/detector/QRAlignmentPattern.cpp | 12 +- .../detector/QRAlignmentPatternFinder.cpp | 59 +- source/zxing/qrcode/detector/QRDetector.cpp | 212 ++++--- .../zxing/qrcode/detector/QREdgeDetector.cpp | 168 ----- source/zxing/qrcode/detector/QREdgeDetector.h | 48 -- .../zxing/qrcode/detector/QRFinderPattern.cpp | 78 ++- .../qrcode/detector/QRFinderPatternFinder.cpp | 66 +- 28 files changed, 664 insertions(+), 856 deletions(-) rename source/zxing/{NotFoundException.cpp => NotFoundException.h} (67%) delete mode 100644 source/zxing/qrcode/detector/QREdgeDetector.cpp delete mode 100644 source/zxing/qrcode/detector/QREdgeDetector.h diff --git a/source/QZXing.pro b/source/QZXing.pro index 60c42dc..fd3a73c 100644 --- a/source/QZXing.pro +++ b/source/QZXing.pro @@ -106,7 +106,6 @@ HEADERS += QZXing_global.h \ zxing/qrcode/decoder/DataMask.h \ zxing/qrcode/decoder/DataBlock.h \ zxing/qrcode/decoder/BitMatrixParser.h \ - zxing/qrcode/detector/QREdgeDetector.h \ zxing/qrcode/detector/FinderPatternInfo.h \ zxing/qrcode/detector/FinderPatternFinder.h \ zxing/qrcode/detector/FinderPattern.h \ @@ -187,7 +186,6 @@ SOURCES += CameraImageWrapper.cpp \ zxing/oned/CodaBarReader.cpp \ zxing/oned/Code93Reader.cpp \ zxing/qrcode/QRCodeReader.cpp \ - zxing/qrcode/detector/QREdgeDetector.cpp \ zxing/multi/MultipleBarcodeReader.cpp \ zxing/multi/GenericMultipleBarcodeReader.cpp \ zxing/multi/ByQuadrantReader.cpp \ diff --git a/source/zxing/NotFoundException.cpp b/source/zxing/NotFoundException.h similarity index 67% rename from source/zxing/NotFoundException.cpp rename to source/zxing/NotFoundException.h index 7d60ac7..d443362 100644 --- a/source/zxing/NotFoundException.cpp +++ b/source/zxing/NotFoundException.h @@ -1,4 +1,8 @@ // -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- + +#ifndef __NOT_FOUND_EXCEPTION_H__ +#define __NOT_FOUND_EXCEPTION_H__ + /* * Copyright 20011 ZXing authors * @@ -15,14 +19,17 @@ * limitations under the License. */ -#include +#include namespace zxing { - NotFoundException::NotFoundException(const char *msg) - : ReaderException(msg) {} - - NotFoundException::~NotFoundException() throw() { - } +class NotFoundException : public ReaderException { +public: + NotFoundException() throw() {} + NotFoundException(const char *msg) throw() : ReaderException(msg) {} + ~NotFoundException() throw() {} +}; } + +#endif // __NOT_FOUND_EXCEPTION_H__ diff --git a/source/zxing/qrcode/FormatInformation.h b/source/zxing/qrcode/FormatInformation.h index 5a07bbb..7770472 100644 --- a/source/zxing/qrcode/FormatInformation.h +++ b/source/zxing/qrcode/FormatInformation.h @@ -35,16 +35,16 @@ private: static int BITS_SET_IN_HALF_BYTE[]; ErrorCorrectionLevel &errorCorrectionLevel_; - unsigned char dataMask_; + char dataMask_; FormatInformation(int formatInfo); public: - static int numBitsDiffering(unsigned int a, unsigned int b); + static int numBitsDiffering(int a, int b); static Ref decodeFormatInformation(int maskedFormatInfo1, int maskedFormatInfo2); static Ref doDecodeFormatInformation(int maskedFormatInfo1, int maskedFormatInfo2); ErrorCorrectionLevel &getErrorCorrectionLevel(); - unsigned char getDataMask(); + char getDataMask(); friend bool operator==(const FormatInformation &a, const FormatInformation &b); friend std::ostream& operator<<(std::ostream& out, const FormatInformation& fi); }; diff --git a/source/zxing/qrcode/QRCodeReader.cpp b/source/zxing/qrcode/QRCodeReader.cpp index e79a3e0..0e647ea 100644 --- a/source/zxing/qrcode/QRCodeReader.cpp +++ b/source/zxing/qrcode/QRCodeReader.cpp @@ -33,46 +33,12 @@ namespace zxing { } //TODO: see if any of the other files in the qrcode tree need tryHarder Ref QRCodeReader::decode(Ref image, DecodeHints hints) { -#ifdef DEBUG - cout << "decoding image " << image.object_ << ":\n" << flush; -#endif - Detector detector(image->getBlackMatrix()); - - -#ifdef DEBUG - cout << "(1) created detector " << &detector << "\n" << flush; -#endif - Ref detectorResult(detector.detect(hints)); -#ifdef DEBUG - cout << "(2) detected, have detectorResult " << detectorResult.object_ << "\n" << flush; -#endif - - std::vector > points(detectorResult->getPoints()); - - -#ifdef DEBUG - cout << "(3) extracted points " << &points << "\n" << flush; - cout << "found " << points.size() << " points:\n"; - for (size_t i = 0; i < points.size(); i++) { - cout << " " << points[i]->getX() << "," << points[i]->getY() << "\n"; - } - cout << "bits:\n"; - cout << *(detectorResult->getBits()) << "\n"; -#endif - + ArrayRef< Ref > points (detectorResult->getPoints()); Ref decoderResult(decoder_.decode(detectorResult->getBits())); -#ifdef DEBUG - cout << "(4) decoded, have decoderResult " << decoderResult.object_ << "\n" << flush; -#endif - Ref result( - new Result(decoderResult->getText(), decoderResult->getRawBytes(), points, BarcodeFormat_QR_CODE)); -#ifdef DEBUG - cout << "(5) created result " << result.object_ << ", returning\n" << flush; -#endif - + new Result(decoderResult->getText(), decoderResult->getRawBytes(), points, BarcodeFormat::QR_CODE)); return result; } diff --git a/source/zxing/qrcode/QRCodeReader.h b/source/zxing/qrcode/QRCodeReader.h index b245be6..d5f9b86 100644 --- a/source/zxing/qrcode/QRCodeReader.h +++ b/source/zxing/qrcode/QRCodeReader.h @@ -26,22 +26,23 @@ #include namespace zxing { - namespace qrcode { +namespace qrcode { - class QRCodeReader : public Reader { - private: - Decoder decoder_; +class QRCodeReader : public Reader { + private: + Decoder decoder_; - protected: - Decoder& getDecoder(); + protected: + Decoder& getDecoder(); - public: - QRCodeReader(); - virtual Ref decode(Ref image, DecodeHints hints); - virtual ~QRCodeReader(); + public: + QRCodeReader(); + virtual ~QRCodeReader(); - }; - } + Ref decode(Ref image, DecodeHints hints); +}; + +} } #endif // __QR_CODE_READER_H__ diff --git a/source/zxing/qrcode/QRFormatInformation.cpp b/source/zxing/qrcode/QRFormatInformation.cpp index 6f04de8..a2b653c 100644 --- a/source/zxing/qrcode/QRFormatInformation.cpp +++ b/source/zxing/qrcode/QRFormatInformation.cpp @@ -39,19 +39,18 @@ int FormatInformation::N_FORMAT_INFO_DECODE_LOOKUPS = 32; int FormatInformation::BITS_SET_IN_HALF_BYTE[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; FormatInformation::FormatInformation(int formatInfo) : - errorCorrectionLevel_(ErrorCorrectionLevel::forBits((formatInfo >> 3) & 0x03)), dataMask_( - (unsigned char)(formatInfo & 0x07)) { + errorCorrectionLevel_(ErrorCorrectionLevel::forBits((formatInfo >> 3) & 0x03)), dataMask_((char)(formatInfo & 0x07)) { } ErrorCorrectionLevel& FormatInformation::getErrorCorrectionLevel() { return errorCorrectionLevel_; } -unsigned char FormatInformation::getDataMask() { +char FormatInformation::getDataMask() { return dataMask_; } -int FormatInformation::numBitsDiffering(unsigned int a, unsigned int b) { +int FormatInformation::numBitsDiffering(int a, int b) { a ^= b; return BITS_SET_IN_HALF_BYTE[a & 0x0F] + BITS_SET_IN_HALF_BYTE[(a >> 4 & 0x0F)] + BITS_SET_IN_HALF_BYTE[(a >> 8 & 0x0F)] + BITS_SET_IN_HALF_BYTE[(a >> 12 & 0x0F)] + BITS_SET_IN_HALF_BYTE[(a >> 16 & 0x0F)] diff --git a/source/zxing/qrcode/QRVersion.cpp b/source/zxing/qrcode/QRVersion.cpp index 339f79f..39d6e8f 100644 --- a/source/zxing/qrcode/QRVersion.cpp +++ b/source/zxing/qrcode/QRVersion.cpp @@ -20,13 +20,16 @@ #include #include +#include #include #include #include +using std::vector; +using std::numeric_limits; + namespace zxing { namespace qrcode { -using namespace std; ECB::ECB(int count, int dataCodewords) : count_(count), dataCodewords_(dataCodewords) { @@ -94,9 +97,14 @@ ECBlocks& Version::getECBlocksForLevel(ErrorCorrectionLevel &ecLevel) { Version *Version::getProvisionalVersionForDimension(int dimension) { if (dimension % 4 != 1) { - throw ReaderException("Dimension must be 1 mod 4"); + throw FormatException(); + } + try { + return Version::getVersionForNumber((dimension - 17) >> 2); + } catch (IllegalArgumentException const& ignored) { + (void)ignored; + throw FormatException(); } - return Version::getVersionForNumber((dimension - 17) >> 2); } Version *Version::getVersionForNumber(int versionNumber) { @@ -196,12 +204,6 @@ Ref Version::buildFunctionPattern() { functionPattern->setRegion(0, dimension - 11, 6, 3); } - - //#ifdef DEBUG - // cout << "version " << versionNumber_ << " built function pattern:\n"; - // cout << *functionPattern; - //#endif - return functionPattern; } @@ -553,5 +555,6 @@ int Version::buildVersions() { new ECB(61, 16))))); return VERSIONS.size(); } + } } diff --git a/source/zxing/qrcode/decoder/BitMatrixParser.h b/source/zxing/qrcode/decoder/BitMatrixParser.h index 50d170a..877d895 100644 --- a/source/zxing/qrcode/decoder/BitMatrixParser.h +++ b/source/zxing/qrcode/decoder/BitMatrixParser.h @@ -42,7 +42,7 @@ public: BitMatrixParser(Ref bitMatrix); Ref readFormatInformation(); Version *readVersion(); - ArrayRef readCodewords(); + ArrayRef readCodewords(); private: BitMatrixParser(const BitMatrixParser&); diff --git a/source/zxing/qrcode/decoder/DataBlock.h b/source/zxing/qrcode/decoder/DataBlock.h index 6c8b462..f314530 100644 --- a/source/zxing/qrcode/decoder/DataBlock.h +++ b/source/zxing/qrcode/decoder/DataBlock.h @@ -32,16 +32,16 @@ namespace qrcode { class DataBlock : public Counted { private: int numDataCodewords_; - ArrayRef codewords_; + ArrayRef codewords_; - DataBlock(int numDataCodewords, ArrayRef codewords); + DataBlock(int numDataCodewords, ArrayRef codewords); public: static std::vector > - getDataBlocks(ArrayRef rawCodewords, Version *version, ErrorCorrectionLevel &ecLevel); + getDataBlocks(ArrayRef rawCodewords, Version *version, ErrorCorrectionLevel &ecLevel); int getNumDataCodewords(); - ArrayRef getCodewords(); + ArrayRef getCodewords(); }; } diff --git a/source/zxing/qrcode/decoder/DecodedBitStreamParser.h b/source/zxing/qrcode/decoder/DecodedBitStreamParser.h index 086c31c..6f4d7d3 100644 --- a/source/zxing/qrcode/decoder/DecodedBitStreamParser.h +++ b/source/zxing/qrcode/decoder/DecodedBitStreamParser.h @@ -51,16 +51,16 @@ private: std::string& result, int count, zxing::common::CharacterSetECI* currentCharacterSetECI, - ArrayRef< ArrayRef >& byteSegments, + ArrayRef< ArrayRef >& byteSegments, Hashtable const& hints); static void decodeAlphanumericSegment(Ref bits, std::string &result, int count, bool fc1InEffect); static void decodeNumericSegment(Ref bits, std::string &result, int count); - static void append(std::string &ost, const unsigned char *bufIn, size_t nIn, const char *src); + static void append(std::string &ost, const char *bufIn, size_t nIn, const char *src); static void append(std::string &ost, std::string const& in, const char *src); public: - static Ref decode(ArrayRef bytes, + static Ref decode(ArrayRef bytes, Version *version, ErrorCorrectionLevel const& ecLevel, Hashtable const& hints); diff --git a/source/zxing/qrcode/decoder/Decoder.h b/source/zxing/qrcode/decoder/Decoder.h index bbfd9b7..31ca6bd 100644 --- a/source/zxing/qrcode/decoder/Decoder.h +++ b/source/zxing/qrcode/decoder/Decoder.h @@ -33,7 +33,7 @@ class Decoder { private: ReedSolomonDecoder rsDecoder_; - void correctErrors(ArrayRef bytes, int numDataCodewords); + void correctErrors(ArrayRef bytes, int numDataCodewords); public: Decoder(); diff --git a/source/zxing/qrcode/decoder/Mode.h b/source/zxing/qrcode/decoder/Mode.h index e75a10b..a94a356 100644 --- a/source/zxing/qrcode/decoder/Mode.h +++ b/source/zxing/qrcode/decoder/Mode.h @@ -32,7 +32,6 @@ private: int characterCountBitsForVersions0To9_; int characterCountBitsForVersions10To26_; int characterCountBitsForVersions27AndHigher_; - int bits_; std::string name_; Mode(int cbv0_9, int cbv10_26, int cbv27, int bits, char const* name); diff --git a/source/zxing/qrcode/decoder/QRBitMatrixParser.cpp b/source/zxing/qrcode/decoder/QRBitMatrixParser.cpp index 8554a1c..467d8fc 100644 --- a/source/zxing/qrcode/decoder/QRBitMatrixParser.cpp +++ b/source/zxing/qrcode/decoder/QRBitMatrixParser.cpp @@ -31,7 +31,7 @@ int BitMatrixParser::copyBit(size_t x, size_t y, int versionBits) { BitMatrixParser::BitMatrixParser(Ref bitMatrix) : bitMatrix_(bitMatrix), parsedVersion_(0), parsedFormatInfo_() { - size_t dimension = bitMatrix->getDimension(); + size_t dimension = bitMatrix->getHeight(); if ((dimension < 21) || (dimension & 0x03) != 1) { throw ReaderException("Dimension must be 1 mod 4 and >= 21"); } @@ -57,7 +57,7 @@ Ref BitMatrixParser::readFormatInformation() { } // Read the top-right/bottom-left pattern - int dimension = bitMatrix_->getDimension(); + int dimension = bitMatrix_->getHeight(); int formatInfoBits2 = 0; int jMin = dimension - 7; for (int j = dimension - 1; j >= jMin; j--) { @@ -79,7 +79,7 @@ Version *BitMatrixParser::readVersion() { return parsedVersion_; } - int dimension = bitMatrix_->getDimension(); + int dimension = bitMatrix_->getHeight(); int provisionalVersion = (dimension - 17) >> 2; if (provisionalVersion <= 6) { @@ -116,19 +116,16 @@ Version *BitMatrixParser::readVersion() { throw ReaderException("Could not decode version"); } -ArrayRef BitMatrixParser::readCodewords() { +ArrayRef BitMatrixParser::readCodewords() { Ref formatInfo = readFormatInformation(); Version *version = readVersion(); - // cerr << *bitMatrix_ << endl; - // cerr << bitMatrix_->getDimension() << endl; - // Get the data mask for the format used in this QR Code. This will exclude // some bits from reading as we wind through the bit matrix. DataMask &dataMask = DataMask::forReference((int)formatInfo->getDataMask()); // cout << (int)formatInfo->getDataMask() << endl; - int dimension = bitMatrix_->getDimension(); + int dimension = bitMatrix_->getHeight(); dataMask.unmaskBitMatrix(*bitMatrix_, dimension); @@ -141,7 +138,7 @@ ArrayRef BitMatrixParser::readCodewords() { // cout << *functionPattern << endl; bool readingUp = true; - ArrayRef result(version->getTotalCodewords()); + ArrayRef result(version->getTotalCodewords()); int resultOffset = 0; int currentByte = 0; int bitsRead = 0; @@ -166,7 +163,7 @@ ArrayRef BitMatrixParser::readCodewords() { } // If we've made a whole byte, save it off if (bitsRead == 8) { - result[resultOffset++] = (unsigned char)currentByte; + result[resultOffset++] = (char)currentByte; bitsRead = 0; currentByte = 0; } diff --git a/source/zxing/qrcode/decoder/QRDataBlock.cpp b/source/zxing/qrcode/decoder/QRDataBlock.cpp index 1ea6602..469b958 100644 --- a/source/zxing/qrcode/decoder/QRDataBlock.cpp +++ b/source/zxing/qrcode/decoder/QRDataBlock.cpp @@ -26,7 +26,7 @@ namespace qrcode { using namespace std; -DataBlock::DataBlock(int numDataCodewords, ArrayRef codewords) : +DataBlock::DataBlock(int numDataCodewords, ArrayRef codewords) : numDataCodewords_(numDataCodewords), codewords_(codewords) { } @@ -34,12 +34,12 @@ int DataBlock::getNumDataCodewords() { return numDataCodewords_; } -ArrayRef DataBlock::getCodewords() { +ArrayRef DataBlock::getCodewords() { return codewords_; } -std::vector > DataBlock::getDataBlocks(ArrayRef rawCodewords, Version *version, +std::vector > DataBlock::getDataBlocks(ArrayRef rawCodewords, Version *version, ErrorCorrectionLevel &ecLevel) { @@ -63,7 +63,7 @@ std::vector > DataBlock::getDataBlocks(ArrayRef ra for (int i = 0; i < ecBlock->getCount(); i++) { int numDataCodewords = ecBlock->getDataCodewords(); int numBlockCodewords = ecBlocks.getECCodewords() + numDataCodewords; - ArrayRef buffer(numBlockCodewords); + ArrayRef buffer(numBlockCodewords); Ref blockRef(new DataBlock(numDataCodewords, buffer)); result[numResultBlocks++] = blockRef; } @@ -71,10 +71,10 @@ std::vector > DataBlock::getDataBlocks(ArrayRef ra // All blocks have the same amount of data, except that the last n // (where n may be 0) have 1 more byte. Figure out where these start. - int shorterBlocksTotalCodewords = result[0]->codewords_.size(); + int shorterBlocksTotalCodewords = result[0]->codewords_->size(); int longerBlocksStartAt = result.size() - 1; while (longerBlocksStartAt >= 0) { - int numCodewords = result[longerBlocksStartAt]->codewords_.size(); + int numCodewords = result[longerBlocksStartAt]->codewords_->size(); if (numCodewords == shorterBlocksTotalCodewords) { break; } @@ -99,7 +99,7 @@ std::vector > DataBlock::getDataBlocks(ArrayRef ra result[j]->codewords_[shorterBlocksNumDataCodewords] = rawCodewords[rawCodewordsOffset++]; } // Now add in error correction blocks - int max = result[0]->codewords_.size(); + int max = result[0]->codewords_->size(); for (int i = shorterBlocksNumDataCodewords; i < max; i++) { for (int j = 0; j < numResultBlocks; j++) { int iOffset = j < longerBlocksStartAt ? i : i + 1; @@ -107,7 +107,7 @@ std::vector > DataBlock::getDataBlocks(ArrayRef ra } } - if ((size_t)rawCodewordsOffset != rawCodewords.size()) { + if (rawCodewordsOffset != rawCodewords->size()) { throw IllegalArgumentException("rawCodewordsOffset != rawCodewords.length"); } diff --git a/source/zxing/qrcode/decoder/QRDecodedBitStreamParser.cpp b/source/zxing/qrcode/decoder/QRDecodedBitStreamParser.cpp index 0743d45..41c587d 100644 --- a/source/zxing/qrcode/decoder/QRDecodedBitStreamParser.cpp +++ b/source/zxing/qrcode/decoder/QRDecodedBitStreamParser.cpp @@ -24,9 +24,6 @@ #include #include #include - -#include - #ifndef NO_ICONV #include #endif @@ -47,370 +44,382 @@ using namespace zxing::qrcode; using namespace zxing::common; const char DecodedBitStreamParser::ALPHANUMERIC_CHARS[] = -{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', - 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', - 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', ' ', '$', '%', '*', '+', '-', '.', '/', ':' -}; + { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', + 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', + 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', ' ', '$', '%', '*', '+', '-', '.', '/', ':' + }; namespace {int GB2312_SUBSET = 1;} void DecodedBitStreamParser::append(std::string &result, string const& in, const char *src) { - append(result, (unsigned char const*)in.c_str(), in.length(), src); + append(result, (char const*)in.c_str(), in.length(), src); } void DecodedBitStreamParser::append(std::string &result, - const unsigned char *bufIn, + const char *bufIn, size_t nIn, const char *src) { #ifndef NO_ICONV - if (nIn == 0) { - return; - } + if (nIn == 0) { + return; + } - iconv_t cd = iconv_open(StringUtils::UTF8, src); - if (cd == (iconv_t)-1) { - result.append((const char *)bufIn, nIn); - return; - } - - const int maxOut = 4 * nIn + 1; - unsigned char* bufOut = new unsigned char[maxOut]; - - /*ICONV_CONST*/ char *fromPtr = (/*ICONV_CONST*/ char *)bufIn; - size_t nFrom = nIn; - char *toPtr = (char *)bufOut; - size_t nTo = maxOut; - - while (nFrom > 0) { -#if defined(Q_OS_SYMBIAN) - size_t oneway = iconv(cd, (const char**)&fromPtr, &nFrom, &toPtr, &nTo); // for Symbian and Mingw -#else - size_t oneway = iconv(cd, (char**)&fromPtr, &nFrom, &toPtr, &nTo); // for Harmattan -#endif - - if (oneway == (size_t)(-1)) { - iconv_close(cd); - delete[] bufOut; - throw ReaderException("error converting characters"); - } - } - iconv_close(cd); - - int nResult = maxOut - nTo; - bufOut[nResult] = '\0'; - result.append((const char *)bufOut); - delete[] bufOut; -#else + iconv_t cd = iconv_open(StringUtils::UTF8, src); + if (cd == (iconv_t)-1) { result.append((const char *)bufIn, nIn); + return; + } + + const int maxOut = 4 * nIn + 1; + char* bufOut = new char[maxOut]; + + ICONV_CONST char *fromPtr = (ICONV_CONST char *)bufIn; + size_t nFrom = nIn; + char *toPtr = (char *)bufOut; + size_t nTo = maxOut; + + while (nFrom > 0) { + size_t oneway = iconv(cd, &fromPtr, &nFrom, &toPtr, &nTo); + if (oneway == (size_t)(-1)) { + iconv_close(cd); + delete[] bufOut; + throw ReaderException("error converting characters"); + } + } + iconv_close(cd); + + int nResult = maxOut - nTo; + bufOut[nResult] = '\0'; + result.append((const char *)bufOut); + delete[] bufOut; +#else + result.append((const char *)bufIn, nIn); #endif } void DecodedBitStreamParser::decodeHanziSegment(Ref bits_, string& result, int count) { - BitSource& bits (*bits_); - // Don't crash trying to read more bits than we have available. - if (count * 13 > bits.available()) { - throw FormatException(); - } + BitSource& bits (*bits_); + // Don't crash trying to read more bits than we have available. + if (count * 13 > bits.available()) { + throw FormatException(); + } - // Each character will require 2 bytes. Read the characters as 2-byte pairs - // and decode as GB2312 afterwards - size_t nBytes = 2 * count; - unsigned char* buffer = new unsigned char[nBytes]; - int offset = 0; - while (count > 0) { - // Each 13 bits encodes a 2-byte character - int twoBytes = bits.readBits(13); - int assembledTwoBytes = ((twoBytes / 0x060) << 8) | (twoBytes % 0x060); - if (assembledTwoBytes < 0x003BF) { - // In the 0xA1A1 to 0xAAFE range - assembledTwoBytes += 0x0A1A1; - } else { - // In the 0xB0A1 to 0xFAFE range - assembledTwoBytes += 0x0A6A1; - } - buffer[offset] = (unsigned char) ((assembledTwoBytes >> 8) & 0xFF); - buffer[offset + 1] = (unsigned char) (assembledTwoBytes & 0xFF); - offset += 2; - count--; - } - - try { - append(result, buffer, nBytes, StringUtils::GB2312); - } catch (ReaderException const& re) { - delete [] buffer; - throw FormatException(); + // Each character will require 2 bytes. Read the characters as 2-byte pairs + // and decode as GB2312 afterwards + size_t nBytes = 2 * count; + char* buffer = new char[nBytes]; + int offset = 0; + while (count > 0) { + // Each 13 bits encodes a 2-byte character + int twoBytes = bits.readBits(13); + int assembledTwoBytes = ((twoBytes / 0x060) << 8) | (twoBytes % 0x060); + if (assembledTwoBytes < 0x003BF) { + // In the 0xA1A1 to 0xAAFE range + assembledTwoBytes += 0x0A1A1; + } else { + // In the 0xB0A1 to 0xFAFE range + assembledTwoBytes += 0x0A6A1; } + buffer[offset] = (char) ((assembledTwoBytes >> 8) & 0xFF); + buffer[offset + 1] = (char) (assembledTwoBytes & 0xFF); + offset += 2; + count--; + } + try { + append(result, buffer, nBytes, StringUtils::GB2312); + } catch (ReaderException const& ignored) { + (void)ignored; delete [] buffer; + throw FormatException(); + } + + delete [] buffer; } void DecodedBitStreamParser::decodeKanjiSegment(Ref bits, std::string &result, int count) { - // Each character will require 2 bytes. Read the characters as 2-byte pairs - // and decode as Shift_JIS afterwards - size_t nBytes = 2 * count; - unsigned char* buffer = new unsigned char[nBytes]; - int offset = 0; - while (count > 0) { - // Each 13 bits encodes a 2-byte character + // Each character will require 2 bytes. Read the characters as 2-byte pairs + // and decode as Shift_JIS afterwards + size_t nBytes = 2 * count; + char* buffer = new char[nBytes]; + int offset = 0; + while (count > 0) { + // Each 13 bits encodes a 2-byte character - int twoBytes = bits->readBits(13); - int assembledTwoBytes = ((twoBytes / 0x0C0) << 8) | (twoBytes % 0x0C0); - if (assembledTwoBytes < 0x01F00) { - // In the 0x8140 to 0x9FFC range - assembledTwoBytes += 0x08140; - } else { - // In the 0xE040 to 0xEBBF range - assembledTwoBytes += 0x0C140; - } - buffer[offset] = (unsigned char)(assembledTwoBytes >> 8); - buffer[offset + 1] = (unsigned char)assembledTwoBytes; - offset += 2; - count--; + int twoBytes = bits->readBits(13); + int assembledTwoBytes = ((twoBytes / 0x0C0) << 8) | (twoBytes % 0x0C0); + if (assembledTwoBytes < 0x01F00) { + // In the 0x8140 to 0x9FFC range + assembledTwoBytes += 0x08140; + } else { + // In the 0xE040 to 0xEBBF range + assembledTwoBytes += 0x0C140; } - + buffer[offset] = (char)(assembledTwoBytes >> 8); + buffer[offset + 1] = (char)assembledTwoBytes; + offset += 2; + count--; + } + try { append(result, buffer, nBytes, StringUtils::SHIFT_JIS); - delete[] buffer; + } catch (ReaderException const& ignored) { + (void)ignored; + delete [] buffer; + throw FormatException(); + } + delete[] buffer; } void DecodedBitStreamParser::decodeByteSegment(Ref bits_, string& result, int count, CharacterSetECI* currentCharacterSetECI, - ArrayRef< ArrayRef >& byteSegments, + ArrayRef< ArrayRef >& byteSegments, Hashtable const& hints) { - int nBytes = count; - BitSource& bits (*bits_); - // Don't crash trying to read more bits than we have available. - if (count << 3 > bits.available()) { - throw FormatException(); - } + int nBytes = count; + BitSource& bits (*bits_); + // Don't crash trying to read more bits than we have available. + if (count << 3 > bits.available()) { + throw FormatException(); + } - ArrayRef bytes_ (count); - unsigned char* readBytes = &(*bytes_)[0]; - for (int i = 0; i < count; i++) { - readBytes[i] = (unsigned char) bits.readBits(8); - } - string encoding; - if (currentCharacterSetECI == 0) { - // The spec isn't clear on this mode; see - // section 6.4.5: t does not say which encoding to assuming - // upon decoding. I have seen ISO-8859-1 used as well as - // Shift_JIS -- without anything like an ECI designator to - // give a hint. - encoding = StringUtils::guessEncoding(readBytes, count, hints); - } else { - encoding = currentCharacterSetECI->name(); - } - try { - append(result, readBytes, nBytes, encoding.c_str()); - } catch (ReaderException const& re) { - throw FormatException(); - } - byteSegments->values().push_back(bytes_); + ArrayRef bytes_ (count); + char* readBytes = &(*bytes_)[0]; + for (int i = 0; i < count; i++) { + readBytes[i] = (char) bits.readBits(8); + } + string encoding; + if (currentCharacterSetECI == 0) { + // The spec isn't clear on this mode; see + // section 6.4.5: t does not say which encoding to assuming + // upon decoding. I have seen ISO-8859-1 used as well as + // Shift_JIS -- without anything like an ECI designator to + // give a hint. + encoding = StringUtils::guessEncoding(readBytes, count, hints); + } else { + encoding = currentCharacterSetECI->name(); + } + try { + append(result, readBytes, nBytes, encoding.c_str()); + } catch (ReaderException const& ignored) { + (void)ignored; + throw FormatException(); + } + byteSegments->values().push_back(bytes_); } void DecodedBitStreamParser::decodeNumericSegment(Ref bits, std::string &result, int count) { - int nBytes = count; - unsigned char* bytes = new unsigned char[nBytes]; - int i = 0; - // Read three digits at a time - while (count >= 3) { - // Each 10 bits encodes three digits - if (bits->available() < 10) { - throw ReaderException("format exception"); - } - int threeDigitsBits = bits->readBits(10); - if (threeDigitsBits >= 1000) { - ostringstream s; - s << "Illegal value for 3-digit unit: " << threeDigitsBits; - delete[] bytes; - throw ReaderException(s.str().c_str()); - } - bytes[i++] = ALPHANUMERIC_CHARS[threeDigitsBits / 100]; - bytes[i++] = ALPHANUMERIC_CHARS[(threeDigitsBits / 10) % 10]; - bytes[i++] = ALPHANUMERIC_CHARS[threeDigitsBits % 10]; - count -= 3; + int nBytes = count; + char* bytes = new char[nBytes]; + int i = 0; + // Read three digits at a time + while (count >= 3) { + // Each 10 bits encodes three digits + if (bits->available() < 10) { + throw ReaderException("format exception"); } - if (count == 2) { - if (bits->available() < 7) { - throw ReaderException("format exception"); - } - // Two digits left over to read, encoded in 7 bits - int twoDigitsBits = bits->readBits(7); - if (twoDigitsBits >= 100) { - ostringstream s; - s << "Illegal value for 2-digit unit: " << twoDigitsBits; - delete[] bytes; - throw ReaderException(s.str().c_str()); - } - bytes[i++] = ALPHANUMERIC_CHARS[twoDigitsBits / 10]; - bytes[i++] = ALPHANUMERIC_CHARS[twoDigitsBits % 10]; - } else if (count == 1) { - if (bits->available() < 4) { - throw ReaderException("format exception"); - } - // One digit left over to read - int digitBits = bits->readBits(4); - if (digitBits >= 10) { - ostringstream s; - s << "Illegal value for digit unit: " << digitBits; - delete[] bytes; - throw ReaderException(s.str().c_str()); - } - bytes[i++] = ALPHANUMERIC_CHARS[digitBits]; + int threeDigitsBits = bits->readBits(10); + if (threeDigitsBits >= 1000) { + ostringstream s; + s << "Illegal value for 3-digit unit: " << threeDigitsBits; + delete[] bytes; + throw ReaderException(s.str().c_str()); } - append(result, bytes, nBytes, StringUtils::ASCII); - delete[] bytes; + bytes[i++] = ALPHANUMERIC_CHARS[threeDigitsBits / 100]; + bytes[i++] = ALPHANUMERIC_CHARS[(threeDigitsBits / 10) % 10]; + bytes[i++] = ALPHANUMERIC_CHARS[threeDigitsBits % 10]; + count -= 3; + } + if (count == 2) { + if (bits->available() < 7) { + throw ReaderException("format exception"); + } + // Two digits left over to read, encoded in 7 bits + int twoDigitsBits = bits->readBits(7); + if (twoDigitsBits >= 100) { + ostringstream s; + s << "Illegal value for 2-digit unit: " << twoDigitsBits; + delete[] bytes; + throw ReaderException(s.str().c_str()); + } + bytes[i++] = ALPHANUMERIC_CHARS[twoDigitsBits / 10]; + bytes[i++] = ALPHANUMERIC_CHARS[twoDigitsBits % 10]; + } else if (count == 1) { + if (bits->available() < 4) { + throw ReaderException("format exception"); + } + // One digit left over to read + int digitBits = bits->readBits(4); + if (digitBits >= 10) { + ostringstream s; + s << "Illegal value for digit unit: " << digitBits; + delete[] bytes; + throw ReaderException(s.str().c_str()); + } + bytes[i++] = ALPHANUMERIC_CHARS[digitBits]; + } + append(result, bytes, nBytes, StringUtils::ASCII); + delete[] bytes; } char DecodedBitStreamParser::toAlphaNumericChar(size_t value) { - if (value >= sizeof(DecodedBitStreamParser::ALPHANUMERIC_CHARS)) { - throw FormatException(); - } - return ALPHANUMERIC_CHARS[value]; + if (value >= sizeof(DecodedBitStreamParser::ALPHANUMERIC_CHARS)) { + throw FormatException(); + } + return ALPHANUMERIC_CHARS[value]; } void DecodedBitStreamParser::decodeAlphanumericSegment(Ref bits_, string& result, int count, bool fc1InEffect) { - BitSource& bits (*bits_); - ostringstream bytes; - // Read two characters at a time - while (count > 1) { - if (bits.available() < 11) { - throw FormatException(); - } - int nextTwoCharsBits = bits.readBits(11); - bytes << toAlphaNumericChar(nextTwoCharsBits / 45); - bytes << toAlphaNumericChar(nextTwoCharsBits % 45); - count -= 2; + BitSource& bits (*bits_); + ostringstream bytes; + // Read two characters at a time + while (count > 1) { + if (bits.available() < 11) { + throw FormatException(); } - if (count == 1) { - // special case: one character left - if (bits.available() < 6) { - throw FormatException(); - } - bytes << toAlphaNumericChar(bits.readBits(6)); + int nextTwoCharsBits = bits.readBits(11); + bytes << toAlphaNumericChar(nextTwoCharsBits / 45); + bytes << toAlphaNumericChar(nextTwoCharsBits % 45); + count -= 2; + } + if (count == 1) { + // special case: one character left + if (bits.available() < 6) { + throw FormatException(); } - // See section 6.4.8.1, 6.4.8.2 - string s = bytes.str(); - if (fc1InEffect) { - // We need to massage the result a bit if in an FNC1 mode: - ostringstream r; - for (size_t i = 0; i < s.length(); i++) { - if (s[i] != '%') { - r << s[i]; - } else { - if (i < s.length() - 1 && s[i + 1] == '%') { - // %% is rendered as % - r << s[i++]; - } else { - // In alpha mode, % should be converted to FNC1 separator 0x1D - r << (char)0x1D; - } - } + bytes << toAlphaNumericChar(bits.readBits(6)); + } + // See section 6.4.8.1, 6.4.8.2 + string s = bytes.str(); + if (fc1InEffect) { + // We need to massage the result a bit if in an FNC1 mode: + ostringstream r; + for (size_t i = 0; i < s.length(); i++) { + if (s[i] != '%') { + r << s[i]; + } else { + if (i < s.length() - 1 && s[i + 1] == '%') { + // %% is rendered as % + r << s[i++]; + } else { + // In alpha mode, % should be converted to FNC1 separator 0x1D + r << (char)0x1D; } - s = r.str(); + } } - append(result, s, StringUtils::ASCII); + s = r.str(); + } + append(result, s, StringUtils::ASCII); } namespace { -int parseECIValue(BitSource bits) { + int parseECIValue(BitSource& bits) { int firstByte = bits.readBits(8); if ((firstByte & 0x80) == 0) { - // just one byte - return firstByte & 0x7F; + // just one byte + return firstByte & 0x7F; } if ((firstByte & 0xC0) == 0x80) { - // two bytes - int secondByte = bits.readBits(8); - return ((firstByte & 0x3F) << 8) | secondByte; + // two bytes + int secondByte = bits.readBits(8); + return ((firstByte & 0x3F) << 8) | secondByte; } if ((firstByte & 0xE0) == 0xC0) { - // three bytes - int secondThirdBytes = bits.readBits(16); - return ((firstByte & 0x1F) << 16) | secondThirdBytes; + // three bytes + int secondThirdBytes = bits.readBits(16); + return ((firstByte & 0x1F) << 16) | secondThirdBytes; } throw FormatException(); -} + } } Ref -DecodedBitStreamParser::decode(ArrayRef bytes, +DecodedBitStreamParser::decode(ArrayRef bytes, Version* version, ErrorCorrectionLevel const& ecLevel, Hashtable const& hints) { - Ref bits_ (new BitSource(bytes)); - BitSource& bits (*bits_); - string result; + Ref bits_ (new BitSource(bytes)); + BitSource& bits (*bits_); + string result; + result.reserve(50); + ArrayRef< ArrayRef > byteSegments (0); + try { CharacterSetECI* currentCharacterSetECI = 0; bool fc1InEffect = false; - ArrayRef< ArrayRef > byteSegments (size_t(0)); Mode* mode = 0; do { - // While still another segment to read... - if (bits.available() < 4) { - // OK, assume we're done. Really, a TERMINATOR mode should have been recorded here - mode = &Mode::TERMINATOR; + // While still another segment to read... + if (bits.available() < 4) { + // OK, assume we're done. Really, a TERMINATOR mode should have been recorded here + mode = &Mode::TERMINATOR; + } else { + try { + mode = &Mode::forBits(bits.readBits(4)); // mode is encoded by 4 bits + } catch (IllegalArgumentException const& iae) { + throw iae; + // throw FormatException.getFormatInstance(); + } + } + if (mode != &Mode::TERMINATOR) { + if ((mode == &Mode::FNC1_FIRST_POSITION) || (mode == &Mode::FNC1_SECOND_POSITION)) { + // We do little with FNC1 except alter the parsed result a bit according to the spec + fc1InEffect = true; + } else if (mode == &Mode::STRUCTURED_APPEND) { + if (bits.available() < 16) { + throw FormatException(); + } + // not really supported; all we do is ignore it + // Read next 8 bits (symbol sequence #) and 8 bits (parity data), then continue + bits.readBits(16); + } else if (mode == &Mode::ECI) { + // Count doesn't apply to ECI + int value = parseECIValue(bits); + currentCharacterSetECI = CharacterSetECI::getCharacterSetECIByValue(value); + if (currentCharacterSetECI == 0) { + throw FormatException(); + } } else { - try { - mode = &Mode::forBits(bits.readBits(4)); // mode is encoded by 4 bits - } catch (IllegalArgumentException const& iae) { - throw iae; - // throw FormatException.getFormatInstance(); + // First handle Hanzi mode which does not start with character count + if (mode == &Mode::HANZI) { + //chinese mode contains a sub set indicator right after mode indicator + int subset = bits.readBits(4); + int countHanzi = bits.readBits(mode->getCharacterCountBits(version)); + if (subset == GB2312_SUBSET) { + decodeHanziSegment(bits_, result, countHanzi); } - } - if (mode != &Mode::TERMINATOR) { - if ((mode == &Mode::FNC1_FIRST_POSITION) || (mode == &Mode::FNC1_SECOND_POSITION)) { - // We do little with FNC1 except alter the parsed result a bit according to the spec - fc1InEffect = true; - } else if (mode == &Mode::STRUCTURED_APPEND) { - // not really supported; all we do is ignore it - // Read next 8 bits (symbol sequence #) and 8 bits (parity data), then continue - bits.readBits(16); - } else if (mode == &Mode::ECI) { - // Count doesn't apply to ECI - int value = parseECIValue(bits); - currentCharacterSetECI = CharacterSetECI::getCharacterSetECIByValue(value); - if (currentCharacterSetECI == 0) { - throw FormatException(); - } + } else { + // "Normal" QR code modes: + // How many characters will follow, encoded in this mode? + int count = bits.readBits(mode->getCharacterCountBits(version)); + if (mode == &Mode::NUMERIC) { + decodeNumericSegment(bits_, result, count); + } else if (mode == &Mode::ALPHANUMERIC) { + decodeAlphanumericSegment(bits_, result, count, fc1InEffect); + } else if (mode == &Mode::BYTE) { + decodeByteSegment(bits_, result, count, currentCharacterSetECI, byteSegments, hints); + } else if (mode == &Mode::KANJI) { + decodeKanjiSegment(bits_, result, count); } else { - // First handle Hanzi mode which does not start with character count - if (mode == &Mode::HANZI) { - //chinese mode contains a sub set indicator right after mode indicator - int subset = bits.readBits(4); - int countHanzi = bits.readBits(mode->getCharacterCountBits(version)); - if (subset == GB2312_SUBSET) { - decodeHanziSegment(bits_, result, countHanzi); - } - } else { - // "Normal" QR code modes: - // How many characters will follow, encoded in this mode? - int count = bits.readBits(mode->getCharacterCountBits(version)); - if (mode == &Mode::NUMERIC) { - decodeNumericSegment(bits_, result, count); - } else if (mode == &Mode::ALPHANUMERIC) { - decodeAlphanumericSegment(bits_, result, count, fc1InEffect); - } else if (mode == &Mode::BYTE) { - decodeByteSegment(bits_, result, count, currentCharacterSetECI, byteSegments, hints); - } else if (mode == &Mode::KANJI) { - decodeKanjiSegment(bits_, result, count); - } else { - throw FormatException(); - } - } + throw FormatException(); } + } } + } } while (mode != &Mode::TERMINATOR); - - return Ref(new DecoderResult(bytes, Ref(new String(result)), byteSegments, (string)ecLevel)); + } catch (IllegalArgumentException const& iae) { + (void)iae; + // from readBits() calls + throw FormatException(); + } + + return Ref(new DecoderResult(bytes, Ref(new String(result)), byteSegments, (string)ecLevel)); } diff --git a/source/zxing/qrcode/decoder/QRDecoder.cpp b/source/zxing/qrcode/decoder/QRDecoder.cpp index 5834df8..d6cfe7b 100644 --- a/source/zxing/qrcode/decoder/QRDecoder.cpp +++ b/source/zxing/qrcode/decoder/QRDecoder.cpp @@ -1,3 +1,4 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- /* * Decoder.cpp * zxing @@ -25,18 +26,22 @@ #include #include #include +#include #include -namespace zxing { -namespace qrcode { +using zxing::qrcode::Decoder; +using zxing::DecoderResult; +using zxing::Ref; -using namespace std; +// VC++ +using zxing::ArrayRef; +using zxing::BitMatrix; Decoder::Decoder() : - rsDecoder_(GenericGF::QR_CODE_FIELD_256) { + rsDecoder_(GenericGF::QR_CODE_FIELD_256) { } -void Decoder::correctErrors(ArrayRef codewordBytes, int numDataCodewords) { +void Decoder::correctErrors(ArrayRef codewordBytes, int numDataCodewords) { int numCodewords = codewordBytes->size(); ArrayRef codewordInts(numCodewords); for (int i = 0; i < numCodewords; i++) { @@ -46,13 +51,13 @@ void Decoder::correctErrors(ArrayRef codewordBytes, int numDataCo try { rsDecoder_.decode(codewordInts, numECCodewords); - } catch (ReedSolomonException const& ex) { - ReaderException rex(ex.what()); - throw rex; + } catch (ReedSolomonException const& ignored) { + (void)ignored; + throw ChecksumException(); } for (int i = 0; i < numDataCodewords; i++) { - codewordBytes[i] = (unsigned char)codewordInts[i]; + codewordBytes[i] = (char)codewordInts[i]; } } @@ -60,12 +65,14 @@ Ref Decoder::decode(Ref bits) { // Construct a parser and read version, error-correction level BitMatrixParser parser(bits); + // std::cerr << *bits << std::endl; + Version *version = parser.readVersion(); ErrorCorrectionLevel &ecLevel = parser.readFormatInformation()->getErrorCorrectionLevel(); // Read codewords - ArrayRef codewords(parser.readCodewords()); + ArrayRef codewords(parser.readCodewords()); // Separate into data blocks @@ -77,14 +84,14 @@ Ref Decoder::decode(Ref bits) { for (size_t i = 0; i < dataBlocks.size(); i++) { totalBytes += dataBlocks[i]->getNumDataCodewords(); } - ArrayRef resultBytes(totalBytes); + ArrayRef resultBytes(totalBytes); int resultOffset = 0; // Error-correct and copy data blocks together into a stream of bytes for (size_t j = 0; j < dataBlocks.size(); j++) { Ref dataBlock(dataBlocks[j]); - ArrayRef codewordBytes = dataBlock->getCodewords(); + ArrayRef codewordBytes = dataBlock->getCodewords(); int numDataCodewords = dataBlock->getNumDataCodewords(); correctErrors(codewordBytes, numDataCodewords); for (int i = 0; i < numDataCodewords; i++) { @@ -98,5 +105,3 @@ Ref Decoder::decode(Ref bits) { DecodedBitStreamParser::Hashtable()); } -} -} diff --git a/source/zxing/qrcode/decoder/QRMode.cpp b/source/zxing/qrcode/decoder/QRMode.cpp index 67b2f27..25e4483 100644 --- a/source/zxing/qrcode/decoder/QRMode.cpp +++ b/source/zxing/qrcode/decoder/QRMode.cpp @@ -19,6 +19,7 @@ * limitations under the License. */ +#include #include #include #include @@ -28,6 +29,9 @@ using zxing::qrcode::Mode; using std::ostringstream; +// VC++ +using zxing::qrcode::Version; + Mode Mode::TERMINATOR(0, 0, 0, 0x00, "TERMINATOR"); Mode Mode::NUMERIC(10, 12, 14, 0x01, "NUMERIC"); Mode Mode::ALPHANUMERIC(9, 11, 13, 0x02, "ALPHANUMERIC"); @@ -39,39 +43,39 @@ Mode Mode::FNC1_FIRST_POSITION(0, 0, 0, 0x05, "FNC1_FIRST_POSITION"); Mode Mode::FNC1_SECOND_POSITION(0, 0, 0, 0x09, "FNC1_SECOND_POSITION"); Mode Mode::HANZI(8, 10, 12, 0x0D, "HANZI"); -Mode::Mode(int cbv0_9, int cbv10_26, int cbv27, int bits, char const* name) : - characterCountBitsForVersions0To9_(cbv0_9), characterCountBitsForVersions10To26_(cbv10_26), - characterCountBitsForVersions27AndHigher_(cbv27), bits_(bits), name_(name) { +Mode::Mode(int cbv0_9, int cbv10_26, int cbv27, int /* bits */, char const* name) : + characterCountBitsForVersions0To9_(cbv0_9), characterCountBitsForVersions10To26_(cbv10_26), + characterCountBitsForVersions27AndHigher_(cbv27), name_(name) { } Mode& Mode::forBits(int bits) { - switch (bits) { - case 0x0: - return TERMINATOR; - case 0x1: - return NUMERIC; - case 0x2: - return ALPHANUMERIC; - case 0x3: - return STRUCTURED_APPEND; - case 0x4: - return BYTE; - case 0x5: - return FNC1_FIRST_POSITION; - case 0x7: - return ECI; - case 0x8: - return KANJI; - case 0x9: - return FNC1_SECOND_POSITION; - case 0xD: - // 0xD is defined in GBT 18284-2000, may not be supported in foreign country - return HANZI; - default: - ostringstream s; - s << "Illegal mode bits: " << bits; - throw ReaderException(s.str().c_str()); - } + switch (bits) { + case 0x0: + return TERMINATOR; + case 0x1: + return NUMERIC; + case 0x2: + return ALPHANUMERIC; + case 0x3: + return STRUCTURED_APPEND; + case 0x4: + return BYTE; + case 0x5: + return FNC1_FIRST_POSITION; + case 0x7: + return ECI; + case 0x8: + return KANJI; + case 0x9: + return FNC1_SECOND_POSITION; + case 0xD: + // 0xD is defined in GBT 18284-2000, may not be supported in foreign country + return HANZI; + default: + ostringstream s; + s << "Illegal mode bits: " << bits; + throw ReaderException(s.str().c_str()); + } } int Mode::getCharacterCountBits(Version *version) { diff --git a/source/zxing/qrcode/detector/AlignmentPatternFinder.h b/source/zxing/qrcode/detector/AlignmentPatternFinder.h index dbc7b0a..6bd9487 100644 --- a/source/zxing/qrcode/detector/AlignmentPatternFinder.h +++ b/source/zxing/qrcode/detector/AlignmentPatternFinder.h @@ -37,21 +37,21 @@ private: Ref image_; std::vector *possibleCenters_; - size_t startX_; - size_t startY_; - size_t width_; - size_t height_; + int startX_; + int startY_; + int width_; + int height_; float moduleSize_; static float centerFromEnd(std::vector &stateCount, int end); bool foundPatternCross(std::vector &stateCount); - float crossCheckVertical(size_t startI, size_t centerJ, int maxCount, int originalStateCountTotal); + float crossCheckVertical(int startI, int centerJ, int maxCount, int originalStateCountTotal); - Ref handlePossibleCenter(std::vector &stateCount, size_t i, size_t j); + Ref handlePossibleCenter(std::vector &stateCount, int i, int j); public: - AlignmentPatternFinder(Ref image, size_t startX, size_t startY, size_t width, size_t height, + AlignmentPatternFinder(Ref image, int startX, int startY, int width, int height, float moduleSize, Refconst& callback); ~AlignmentPatternFinder(); Ref find(); diff --git a/source/zxing/qrcode/detector/Detector.h b/source/zxing/qrcode/detector/Detector.h index b33852f..05ef044 100644 --- a/source/zxing/qrcode/detector/Detector.h +++ b/source/zxing/qrcode/detector/Detector.h @@ -1,3 +1,4 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- #ifndef __DETECTOR_H__ #define __DETECTOR_H__ @@ -40,7 +41,8 @@ private: Ref callback_; protected: - Ref getImage(); + Ref getImage() const; + Ref getResultPointCallback() const; static Ref sampleGrid(Ref image, int dimension, Ref); static int computeDimension(Ref topLeft, Ref topRight, Ref bottomLeft, @@ -53,14 +55,15 @@ protected: float allowanceFactor); Ref processFinderPatternInfo(Ref info); public: - virtual Ref createTransform(Ref topLeft, Ref topRight, Ref < ResultPoint > bottomLeft, Ref alignmentPattern, int dimension); Detector(Ref image); Ref detect(DecodeHints const& hints); + + }; } } -#endif // __DETECTOR_H__ \ No newline at end of file +#endif // __DETECTOR_H__ diff --git a/source/zxing/qrcode/detector/FinderPattern.h b/source/zxing/qrcode/detector/FinderPattern.h index e23ba5d..87b61c8 100644 --- a/source/zxing/qrcode/detector/FinderPattern.h +++ b/source/zxing/qrcode/detector/FinderPattern.h @@ -32,9 +32,10 @@ namespace zxing { float estimatedModuleSize_; int count_; + FinderPattern(float posX, float posY, float estimatedModuleSize, int count); + public: FinderPattern(float posX, float posY, float estimatedModuleSize); - FinderPattern(float posX, float posY, float estimatedModuleSize, int count); int getCount() const; float getEstimatedModuleSize() const; void incrementCount(); diff --git a/source/zxing/qrcode/detector/FinderPatternFinder.h b/source/zxing/qrcode/detector/FinderPatternFinder.h index 1d85f9b..82d4365 100644 --- a/source/zxing/qrcode/detector/FinderPatternFinder.h +++ b/source/zxing/qrcode/detector/FinderPatternFinder.h @@ -1,3 +1,4 @@ +// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- #ifndef __FINDER_PATTERN_FINDER_H__ #define __FINDER_PATTERN_FINDER_H__ @@ -60,6 +61,10 @@ protected: bool haveMultiplyConfirmedCenters(); std::vector > selectBestPatterns(); static std::vector > orderBestPatterns(std::vector > patterns); + + Ref getImage(); + std::vector >& getPossibleCenters(); + public: static float distance(Ref p1, Ref p2); FinderPatternFinder(Ref image, Refconst&); diff --git a/source/zxing/qrcode/detector/QRAlignmentPattern.cpp b/source/zxing/qrcode/detector/QRAlignmentPattern.cpp index d874493..9ab35eb 100644 --- a/source/zxing/qrcode/detector/QRAlignmentPattern.cpp +++ b/source/zxing/qrcode/detector/QRAlignmentPattern.cpp @@ -21,10 +21,9 @@ #include -namespace zxing { -namespace qrcode { - -using namespace std; +using std::abs; +using zxing::Ref; +using zxing::qrcode::AlignmentPattern; AlignmentPattern::AlignmentPattern(float posX, float posY, float estimatedModuleSize) : ResultPoint(posX,posY), estimatedModuleSize_(estimatedModuleSize) { @@ -43,9 +42,6 @@ Ref AlignmentPattern::combineEstimate(float i, float j, float float combinedY = (getY() + i) / 2.0f; float combinedModuleSize = (estimatedModuleSize_ + newModuleSize) / 2.0f; Ref result - (new AlignmentPattern(combinedX, combinedY, combinedModuleSize)); + (new AlignmentPattern(combinedX, combinedY, combinedModuleSize)); return result; } - -} -} diff --git a/source/zxing/qrcode/detector/QRAlignmentPatternFinder.cpp b/source/zxing/qrcode/detector/QRAlignmentPatternFinder.cpp index 8aecb2f..8ce4321 100644 --- a/source/zxing/qrcode/detector/QRAlignmentPatternFinder.cpp +++ b/source/zxing/qrcode/detector/QRAlignmentPatternFinder.cpp @@ -1,9 +1,5 @@ // -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- /* - * AlignmentPatternFinder.cpp - * zxing - * - * Created by Christian Brunschen on 14/05/2008. * Copyright 2008 ZXing authors All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,25 +15,31 @@ * limitations under the License. */ -#include "AlignmentPatternFinder.h" +#include #include #include #include #include #include -namespace zxing { -namespace qrcode { +using std::abs; +using std::vector; +using zxing::Ref; +using zxing::qrcode::AlignmentPatternFinder; +using zxing::qrcode::AlignmentPattern; -using namespace std; +// VC++ -float AlignmentPatternFinder::centerFromEnd(vector &stateCount, int end) { +using zxing::BitMatrix; +using zxing::ResultPointCallback; + +float AlignmentPatternFinder::centerFromEnd(vector& stateCount, int end) { return (float)(end - stateCount[2]) - stateCount[1] / 2.0f; } bool AlignmentPatternFinder::foundPatternCross(vector &stateCount) { float maxVariance = moduleSize_ / 2.0f; - for (size_t i = 0; i < 3; i++) { + for (int i = 0; i < 3; i++) { if (abs(moduleSize_ - stateCount[i]) >= maxVariance) { return false; } @@ -45,8 +47,8 @@ bool AlignmentPatternFinder::foundPatternCross(vector &stateCount) { return true; } -float AlignmentPatternFinder::crossCheckVertical(size_t startI, size_t centerJ, int maxCount, - int originalStateCountTotal) { +float AlignmentPatternFinder::crossCheckVertical(int startI, int centerJ, int maxCount, + int originalStateCountTotal) { int maxI = image_->getHeight(); vector stateCount(3, 0); @@ -59,14 +61,14 @@ float AlignmentPatternFinder::crossCheckVertical(size_t startI, size_t centerJ, } // If already too many modules in this state or ran off the edge: if (i < 0 || stateCount[1] > maxCount) { - return NAN; + return nan(); } while (i >= 0 && !image_->get(centerJ, i) && stateCount[0] <= maxCount) { stateCount[0]++; i--; } if (stateCount[0] > maxCount) { - return NAN; + return nan(); } // Now also count down from center @@ -76,25 +78,25 @@ float AlignmentPatternFinder::crossCheckVertical(size_t startI, size_t centerJ, i++; } if (i == maxI || stateCount[1] > maxCount) { - return NAN; + return nan(); } while (i < maxI && !image_->get(centerJ, i) && stateCount[2] <= maxCount) { stateCount[2]++; i++; } if (stateCount[2] > maxCount) { - return NAN; + return nan(); } int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2]; if (5 * abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal) { - return NAN; + return nan(); } - return foundPatternCross(stateCount) ? centerFromEnd(stateCount, i) : NAN; + return foundPatternCross(stateCount) ? centerFromEnd(stateCount, i) : nan(); } -Ref AlignmentPatternFinder::handlePossibleCenter(vector &stateCount, size_t i, size_t j) { +Ref AlignmentPatternFinder::handlePossibleCenter(vector &stateCount, int i, int j) { int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2]; float centerJ = centerFromEnd(stateCount, j); float centerI = crossCheckVertical(i, (int)centerJ, 2 * stateCount[1], stateCountTotal); @@ -120,15 +122,15 @@ Ref AlignmentPatternFinder::handlePossibleCenter(vector & return result; } -AlignmentPatternFinder::AlignmentPatternFinder(Ref image, size_t startX, size_t startY, size_t width, - size_t height, float moduleSize, +AlignmentPatternFinder::AlignmentPatternFinder(Ref image, int startX, int startY, int width, + int height, float moduleSize, Refconst& callback) : image_(image), possibleCenters_(new vector ()), startX_(startX), startY_(startY), width_(width), height_(height), moduleSize_(moduleSize), callback_(callback) { } AlignmentPatternFinder::~AlignmentPatternFinder() { - for (size_t i = 0; i < possibleCenters_->size(); i++) { + for (int i = 0; i < int(possibleCenters_->size()); i++) { (*possibleCenters_)[i]->release(); (*possibleCenters_)[i] = 0; } @@ -136,20 +138,20 @@ AlignmentPatternFinder::~AlignmentPatternFinder() { } Ref AlignmentPatternFinder::find() { - size_t maxJ = startX_ + width_; - size_t middleI = startY_ + (height_ >> 1); + int maxJ = startX_ + width_; + int middleI = startY_ + (height_ >> 1); // Ref luminanceRow(new BitArray(width_)); // We are looking for black/white/black modules in 1:1:1 ratio; // this tracks the number of black/white/black modules seen so far vector stateCount(3, 0); - for (size_t iGen = 0; iGen < height_; iGen++) { + for (int iGen = 0; iGen < height_; iGen++) { // Search from middle outwards - size_t i = middleI + ((iGen & 0x01) == 0 ? ((iGen + 1) >> 1) : -((iGen + 1) >> 1)); + int i = middleI + ((iGen & 0x01) == 0 ? ((iGen + 1) >> 1) : -((iGen + 1) >> 1)); // image_->getBlackRow(i, luminanceRow, startX_, width_); stateCount[0] = 0; stateCount[1] = 0; stateCount[2] = 0; - size_t j = startX_; + int j = startX_; // Burn off leading white pixels before anything else; if we start in the middle of // a white run, it doesn't make sense to count its length, since we don't know if the // white run continued to the left of the start point @@ -204,6 +206,3 @@ Ref AlignmentPatternFinder::find() { throw zxing::ReaderException("Could not find alignment pattern"); } - -} -} diff --git a/source/zxing/qrcode/detector/QRDetector.cpp b/source/zxing/qrcode/detector/QRDetector.cpp index 1ff6f4c..d1e5506 100644 --- a/source/zxing/qrcode/detector/QRDetector.cpp +++ b/source/zxing/qrcode/detector/QRDetector.cpp @@ -27,21 +27,39 @@ #include #include #include -#include +#include #include #include -namespace zxing { -namespace qrcode { +using std::ostringstream; +using std::abs; +using std::min; +using std::max; +using zxing::qrcode::Detector; +using zxing::Ref; +using zxing::BitMatrix; +using zxing::ResultPointCallback; +using zxing::DetectorResult; +using zxing::PerspectiveTransform; +using zxing::qrcode::AlignmentPattern; +using zxing::common::detector::MathUtils; -using namespace std; +// VC++ +using zxing::DecodeHints; +using zxing::qrcode::FinderPatternFinder; +using zxing::qrcode::FinderPatternInfo; +using zxing::ResultPoint; Detector::Detector(Ref image) : - image_(image) { + image_(image) { } -Ref Detector::getImage() { - return image_; +Ref Detector::getImage() const { + return image_; +} + +Ref Detector::getResultPointCallback() const { + return callback_; } Ref Detector::detect(DecodeHints const& hints) { @@ -87,6 +105,7 @@ Ref Detector::processFinderPatternInfo(Ref in alignmentPattern = findAlignmentInRegion(moduleSize, estAlignmentX, estAlignmentY, (float)i); break; } catch (zxing::ReaderException const& re) { + (void)re; // try next round } } @@ -98,7 +117,7 @@ Ref Detector::processFinderPatternInfo(Ref in Ref transform = createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension); Ref bits(sampleGrid(image_, dimension, transform)); - std::vector > points(alignmentPattern == 0 ? 3 : 4); + ArrayRef< Ref > points(new Array< Ref >(alignmentPattern == 0 ? 3 : 4)); points[0].reset(bottomLeft); points[1].reset(topLeft); points[2].reset(topRight); @@ -106,12 +125,12 @@ Ref Detector::processFinderPatternInfo(Ref in points[3].reset(alignmentPattern); } - Ref result(new DetectorResult(bits, points)); + Ref result(new DetectorResult(bits, points)); return result; } Ref Detector::createTransform(Ref topLeft, Ref topRight, Ref < - ResultPoint > bottomLeft, Ref alignmentPattern, int dimension) { + ResultPoint > bottomLeft, Ref alignmentPattern, int dimension) { float dimMinusThree = (float)dimension - 3.5f; float bottomRightX; @@ -121,17 +140,19 @@ Ref Detector::createTransform(Ref topLeft, Re if (alignmentPattern != 0) { bottomRightX = alignmentPattern->getX(); bottomRightY = alignmentPattern->getY(); - sourceBottomRightX = sourceBottomRightY = dimMinusThree - 3.0f; + sourceBottomRightX = dimMinusThree - 3.0f; + sourceBottomRightY = sourceBottomRightX; } else { // Don't have an alignment pattern, just make up the bottom-right point bottomRightX = (topRight->getX() - topLeft->getX()) + bottomLeft->getX(); bottomRightY = (topRight->getY() - topLeft->getY()) + bottomLeft->getY(); - sourceBottomRightX = sourceBottomRightY = dimMinusThree; + sourceBottomRightX = dimMinusThree; + sourceBottomRightY = dimMinusThree; } Ref transform(PerspectiveTransform::quadrilateralToQuadrilateral(3.5f, 3.5f, dimMinusThree, 3.5f, sourceBottomRightX, - sourceBottomRightY, 3.5f, dimMinusThree, topLeft->getX(), topLeft->getY(), topRight->getX(), - topRight->getY(), bottomRightX, bottomRightY, bottomLeft->getX(), bottomLeft->getY())); + sourceBottomRightY, 3.5f, dimMinusThree, topLeft->getX(), topLeft->getY(), topRight->getX(), + topRight->getY(), bottomRightX, bottomRightY, bottomLeft->getX(), bottomLeft->getY())); return transform; } @@ -143,8 +164,10 @@ Ref Detector::sampleGrid(Ref image, int dimension, Ref topLeft, Ref topRight, Ref bottomLeft, float moduleSize) { - int tltrCentersDimension = int(FinderPatternFinder::distance(topLeft, topRight) / moduleSize + 0.5f); - int tlblCentersDimension = int(FinderPatternFinder::distance(topLeft, bottomLeft) / moduleSize + 0.5f); + int tltrCentersDimension = + MathUtils::round(ResultPoint::distance(topLeft, topRight) / moduleSize); + int tlblCentersDimension = + MathUtils::round(ResultPoint::distance(topLeft, bottomLeft) / moduleSize); int dimension = ((tltrCentersDimension + tlblCentersDimension) >> 1) + 7; switch (dimension & 0x03) { // mod 4 case 0: @@ -169,13 +192,13 @@ float Detector::calculateModuleSize(Ref topLeft, Ref t float Detector::calculateModuleSizeOneWay(Ref pattern, Ref otherPattern) { float moduleSizeEst1 = sizeOfBlackWhiteBlackRunBothWays((int)pattern->getX(), (int)pattern->getY(), - (int)otherPattern->getX(), (int)otherPattern->getY()); + (int)otherPattern->getX(), (int)otherPattern->getY()); float moduleSizeEst2 = sizeOfBlackWhiteBlackRunBothWays((int)otherPattern->getX(), (int)otherPattern->getY(), - (int)pattern->getX(), (int)pattern->getY()); - if (isnan(moduleSizeEst1)) { + (int)pattern->getX(), (int)pattern->getY()); + if (zxing::isnan(moduleSizeEst1)) { return moduleSizeEst2; } - if (isnan(moduleSizeEst2)) { + if (zxing::isnan(moduleSizeEst2)) { return moduleSizeEst1; } // Average them, and divide by 7 since we've counted the width of 3 black modules, @@ -185,114 +208,107 @@ float Detector::calculateModuleSizeOneWay(Ref pattern, Ref= (int)image_->getWidth()) { - scale = (float) (image_->getWidth() - 1 - fromX) / (float) (otherToX - fromX); - otherToX = image_->getWidth() - 1; - } - int otherToY = (int) (fromY - (toY - fromY) * scale); + // Now count other way -- don't run off image though of course + float scale = 1.0f; + int otherToX = fromX - (toX - fromX); + if (otherToX < 0) { + scale = (float) fromX / (float) (fromX - otherToX); + otherToX = 0; + } else if (otherToX >= (int)image_->getWidth()) { + scale = (float) (image_->getWidth() - 1 - fromX) / (float) (otherToX - fromX); + otherToX = image_->getWidth() - 1; + } + int otherToY = (int) (fromY - (toY - fromY) * scale); - scale = 1.0f; - if (otherToY < 0) { - scale = (float) fromY / (float) (fromY - otherToY); - otherToY = 0; - } else if (otherToY >= (int)image_->getHeight()) { - scale = (float) (image_->getHeight() - 1 - fromY) / (float) (otherToY - fromY); - otherToY = image_->getHeight() - 1; - } - otherToX = (int) (fromX + (otherToX - fromX) * scale); + scale = 1.0f; + if (otherToY < 0) { + scale = (float) fromY / (float) (fromY - otherToY); + otherToY = 0; + } else if (otherToY >= (int)image_->getHeight()) { + scale = (float) (image_->getHeight() - 1 - fromY) / (float) (otherToY - fromY); + otherToY = image_->getHeight() - 1; + } + otherToX = (int) (fromX + (otherToX - fromX) * scale); - result += sizeOfBlackWhiteBlackRun(fromX, fromY, otherToX, otherToY); + result += sizeOfBlackWhiteBlackRun(fromX, fromY, otherToX, otherToY); - // Middle pixel is double-counted this way; subtract 1 - return result - 1.0f; + // Middle pixel is double-counted this way; subtract 1 + return result - 1.0f; } float Detector::sizeOfBlackWhiteBlackRun(int fromX, int fromY, int toX, int toY) { - // Mild variant of Bresenham's algorithm; - // see http://en.wikipedia.org/wiki/Bresenham's_line_algorithm - bool steep = abs(toY - fromY) > abs(toX - fromX); - if (steep) { - int temp = fromX; - fromX = fromY; - fromY = temp; - temp = toX; - toX = toY; - toY = temp; - } + // Mild variant of Bresenham's algorithm; + // see http://en.wikipedia.org/wiki/Bresenham's_line_algorithm + bool steep = abs(toY - fromY) > abs(toX - fromX); + if (steep) { + int temp = fromX; + fromX = fromY; + fromY = temp; + temp = toX; + toX = toY; + toY = temp; + } - int dx = abs(toX - fromX); - int dy = abs(toY - fromY); - int error = -dx >> 1; - int xstep = fromX < toX ? 1 : -1; - int ystep = fromY < toY ? 1 : -1; + int dx = abs(toX - fromX); + int dy = abs(toY - fromY); + int error = -dx >> 1; + int xstep = fromX < toX ? 1 : -1; + int ystep = fromY < toY ? 1 : -1; - // In black pixels, looking for white, first or second time. - int state = 0; - // Loop up until x == toX, but not beyond - int xLimit = toX + xstep; - for (int x = fromX, y = fromY; x != xLimit; x += xstep) { - int realX = steep ? y : x; - int realY = steep ? x : y; + // In black pixels, looking for white, first or second time. + int state = 0; + // Loop up until x == toX, but not beyond + int xLimit = toX + xstep; + for (int x = fromX, y = fromY; x != xLimit; x += xstep) { + int realX = steep ? y : x; + int realY = steep ? x : y; - // Does current pixel mean we have moved white to black or vice versa? - if (!((state == 1) ^ image_->get(realX, realY))) { - if (state == 2) { - int diffX = x - fromX; - int diffY = y - fromY; - return (float) sqrt((double) (diffX * diffX + diffY * diffY)); - } - state++; + // Does current pixel mean we have moved white to black or vice versa? + if (!((state == 1) ^ image_->get(realX, realY))) { + if (state == 2) { + return MathUtils::distance(x, y, fromX, fromY); } + state++; + } - error += dy; - if (error > 0) { - if (y == toY) { - break; - } - y += ystep; - error -= dx; + error += dy; + if (error > 0) { + if (y == toY) { + break; } + y += ystep; + error -= dx; } - // Found black-white-black; give the benefit of the doubt that the next pixel outside the image - // is "white" so this last point at (toX+xStep,toY) is the right ending. This is really a - // small approximation; (toX+xStep,toY+yStep) might be really correct. Ignore this. - if (state == 2) { - int diffX = toX + xstep - fromX; - int diffY = toY - fromY; - return (float) sqrt((double) (diffX * diffX + diffY * diffY)); - } - // else we didn't find even black-white-black; no estimate is really possible - return NAN; + } + // Found black-white-black; give the benefit of the doubt that the next pixel outside the image + // is "white" so this last point at (toX+xStep,toY) is the right ending. This is really a + // small approximation; (toX+xStep,toY+yStep) might be really correct. Ignore this. + if (state == 2) { + return MathUtils::distance(toX + xstep, toY, fromX, fromY); + } + // else we didn't find even black-white-black; no estimate is really possible + return nan(); } Ref Detector::findAlignmentInRegion(float overallEstModuleSize, int estAlignmentX, int estAlignmentY, - float allowanceFactor) { + float allowanceFactor) { // Look for an alignment pattern (3 modules in size) around where it // should be int allowance = (int)(allowanceFactor * overallEstModuleSize); int alignmentAreaLeftX = max(0, estAlignmentX - allowance); int alignmentAreaRightX = min((int)(image_->getWidth() - 1), estAlignmentX + allowance); if (alignmentAreaRightX - alignmentAreaLeftX < overallEstModuleSize * 3) { - throw zxing::ReaderException("region too small to hold alignment pattern"); + throw zxing::ReaderException("region too small to hold alignment pattern"); } int alignmentAreaTopY = max(0, estAlignmentY - allowance); int alignmentAreaBottomY = min((int)(image_->getHeight() - 1), estAlignmentY + allowance); if (alignmentAreaBottomY - alignmentAreaTopY < overallEstModuleSize * 3) { - throw zxing::ReaderException("region too small to hold alignment pattern"); + throw zxing::ReaderException("region too small to hold alignment pattern"); } AlignmentPatternFinder alignmentFinder(image_, alignmentAreaLeftX, alignmentAreaTopY, alignmentAreaRightX - alignmentAreaLeftX, alignmentAreaBottomY - alignmentAreaTopY, overallEstModuleSize, callback_); return alignmentFinder.find(); } - -} -} diff --git a/source/zxing/qrcode/detector/QREdgeDetector.cpp b/source/zxing/qrcode/detector/QREdgeDetector.cpp deleted file mode 100644 index c24a072..0000000 --- a/source/zxing/qrcode/detector/QREdgeDetector.cpp +++ /dev/null @@ -1,168 +0,0 @@ -// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- -/* - * Created by Ralf Kistner on 7/12/2009. - * Copyright 2008 ZXing authors All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include - -using namespace std; - -namespace zxing { -namespace qrcode { - -static const float patternEdgeThreshold = 2; -static const int patternEdgeWidth = 3; -static const float patternEdgeSearchRatio = 1.1; -static const int patternEdgeSkip = 2; - -static const float accurateEdgeThreshold = 3.3; -static const int accurateEdgeWidth = 7; -static const int accurateEdgeSkip = 2; - -static Point guessLastPattern(Point topLeft, Point topRight, Point bottomLeft) { - return Point(topRight.x - topLeft.x + bottomLeft.x, topRight.y - topLeft.y + bottomLeft.y); -} - -static Point rp(Ref rp) { - return Point(rp->getX(), rp->getY()); -} - -QREdgeDetector::QREdgeDetector(Ref image) : Detector(image) { } - -Ref QREdgeDetector::createTransform(Ref topLeft, Ref topRight, Ref < - ResultPoint > bottomLeft, Ref alignmentPattern, int dimension) { - - if(alignmentPattern == NULL) { - Point corner = findCorner(*Detector::getImage(), rp(topLeft), rp(topRight), rp(bottomLeft), dimension); - return get1CornerTransform(rp(topLeft), rp(topRight), rp(bottomLeft), corner, dimension); - } else { - return Detector::createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension); - } -} - - - - -Point QREdgeDetector::findCorner(const BitMatrix& image, Point topLeft, Point topRight, Point bottomLeft, int dimension) { - (void)dimension; - Point bottomRight = guessLastPattern(topLeft, topRight, bottomLeft); - - Line bottomEst = findPatternEdge(image, bottomLeft, topLeft, bottomRight, false); - Line rightEst = findPatternEdge(image, topRight, topLeft, bottomRight, true); - - //return EdgeDetector::intersection(bottomEst, rightEst); - - Line bottom = EdgeDetector::findLine(image, bottomEst, false, accurateEdgeWidth, accurateEdgeThreshold, accurateEdgeSkip); - Line right = EdgeDetector::findLine(image, rightEst, true, accurateEdgeWidth, accurateEdgeThreshold, accurateEdgeSkip); - - - return EdgeDetector::intersection(bottom, right); -} - -Line QREdgeDetector::findPatternEdge(const BitMatrix& image, Point pattern, Point opposite, Point direction, bool invert) { - Point start = endOfReverseBlackWhiteBlackRun(image, pattern, opposite); - - float dx = pattern.x - start.x; - float dy = pattern.y - start.y; - float dist = sqrt(dx*dx + dy*dy); - - float dirX = direction.x - pattern.x; - float dirY = direction.y - pattern.y; - float dirSize = sqrt(dirX*dirX + dirY*dirY); - - float nx = dirX/dirSize; - float ny = dirY/dirSize; - - float search = dist * patternEdgeSearchRatio; - Point a(start.x + nx*search, start.y + ny*search); - Point b(start.x - nx*search, start.y - ny*search); - - return EdgeDetector::findLine(image, Line(a, b), invert, patternEdgeWidth, patternEdgeThreshold, patternEdgeSkip); -} - - -Ref QREdgeDetector::get1CornerTransform(Point topLeft, Point topRight, Point bottomLeft, Point corner, int dimension) { - float dimMinusThree = (float) dimension - 3.5f; - - Ref transform(PerspectiveTransform::quadrilateralToQuadrilateral(3.5f, 3.5f, dimMinusThree, 3.5f, dimension, - dimension, 3.5f, dimMinusThree, topLeft.x, topLeft.y, topRight.x, - topRight.y, corner.x, corner.y, bottomLeft.x, bottomLeft.y)); - - return transform; -} - -// Adapted from "sizeOfBlackWhiteBlackRun" in zxing::qrcode::Detector -Point QREdgeDetector::endOfReverseBlackWhiteBlackRun(const BitMatrix& image, Point from, Point to) { - int fromX = (int)from.x; - int fromY = (int)from.y; - int toX = (int)to.x; - int toY = (int)to.y; - - bool steep = abs(toY - fromY) > abs(toX - fromX); - if (steep) { - int temp = fromX; - fromX = fromY; - fromY = temp; - temp = toX; - toX = toY; - toY = temp; - } - - int dx = abs(toX - fromX); - int dy = abs(toY - fromY); - int error = -dx >> 1; - int ystep = fromY < toY ? -1 : 1; - int xstep = fromX < toX ? -1 : 1; - int state = 0; // In black pixels, looking for white, first or second time - - // In case there are no points, prepopulate to from - int realX = fromX; - int realY = fromY; - for (int x = fromX, y = fromY; x != toX; x += xstep) { - realX = steep ? y : x; - realY = steep ? x : y; - - if(realX < 0 || realY < 0 || realX >= (int)image.getWidth() || realY >= (int)image.getHeight()) - break; - - if (state == 1) { // In white pixels, looking for black - if (image.get(realX, realY)) { - state++; - } - } else { - if (!image.get(realX, realY)) { - state++; - } - } - - if (state == 3) { // Found black, white, black, and stumbled back onto white; done - return Point(realX, realY); - } - error += dy; - if (error > 0) { - y += ystep; - error -= dx; - } - } - - // B-W-B run not found, return the last point visited. - return Point(realX, realY); -} - -} // namespace qrcode -} // namespace zxing diff --git a/source/zxing/qrcode/detector/QREdgeDetector.h b/source/zxing/qrcode/detector/QREdgeDetector.h deleted file mode 100644 index d2f3fe1..0000000 --- a/source/zxing/qrcode/detector/QREdgeDetector.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef __QREDGEDETECTOR_H__ -#define __QREDGEDETECTOR_H__ -/* - * QREdgeDetector.h - * zxing - * - * Copyright 2010 ZXing authors All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - - -#include -#include - -namespace zxing { -namespace qrcode { - -class QREdgeDetector : public Detector { -public: - QREdgeDetector(Ref image); - - virtual Ref createTransform(Ref topLeft, Ref topRight, Ref < - ResultPoint > bottomLeft, Ref alignmentPattern, int dimension); - -private: - Point findCorner(const BitMatrix& image, Point topLeft, Point topRight, Point bottomLeft, int dimension); - Line findPatternEdge(const BitMatrix& image, Point pattern, Point opposite, Point direction, bool invert); - - Point endOfReverseBlackWhiteBlackRun(const BitMatrix& image, Point from, Point to); - - Ref get1CornerTransform(Point topLeft, Point topRight, Point bottomLeft, Point corner, int dimension); -}; - -} -} -#endif // QREDGEDETECTOR_H_ diff --git a/source/zxing/qrcode/detector/QRFinderPattern.cpp b/source/zxing/qrcode/detector/QRFinderPattern.cpp index 32c64da..f882cc0 100644 --- a/source/zxing/qrcode/detector/QRFinderPattern.cpp +++ b/source/zxing/qrcode/detector/QRFinderPattern.cpp @@ -21,51 +21,49 @@ #include -namespace zxing { - namespace qrcode { +using std::abs; +using zxing::Ref; +using zxing::qrcode::FinderPattern; + +FinderPattern::FinderPattern(float posX, float posY, float estimatedModuleSize) + : ResultPoint(posX,posY), estimatedModuleSize_(estimatedModuleSize), count_(1) {} - using namespace std; +FinderPattern::FinderPattern(float posX, float posY, float estimatedModuleSize, int count) + : ResultPoint(posX,posY), estimatedModuleSize_(estimatedModuleSize), count_(count) {} - FinderPattern::FinderPattern(float posX, float posY, float estimatedModuleSize) : - ResultPoint(posX,posY), estimatedModuleSize_(estimatedModuleSize), count_(1) { - } +int FinderPattern::getCount() const { + return count_; +} - FinderPattern::FinderPattern(float posX, float posY, float estimatedModuleSize, int count) : - ResultPoint(posX,posY), estimatedModuleSize_(estimatedModuleSize), count_(count) { - } +float FinderPattern::getEstimatedModuleSize() const { + return estimatedModuleSize_; +} - int FinderPattern::getCount() const { - return count_; - } - - float FinderPattern::getEstimatedModuleSize() const { - return estimatedModuleSize_; - } - - void FinderPattern::incrementCount() { - count_++; - } +void FinderPattern::incrementCount() { + count_++; + // cerr << "ic " << getX() << " " << getY() << " " << count_ << endl; +} /* - bool FinderPattern::aboutEquals(float moduleSize, float i, float j) const { - return abs(i - posY_) <= moduleSize && abs(j - posX_) <= moduleSize && (abs(moduleSize - estimatedModuleSize_) - <= 1.0f || abs(moduleSize - estimatedModuleSize_) / estimatedModuleSize_ <= 0.1f); - } + bool FinderPattern::aboutEquals(float moduleSize, float i, float j) const { + return abs(i - posY_) <= moduleSize && abs(j - posX_) <= moduleSize && (abs(moduleSize - estimatedModuleSize_) + <= 1.0f || abs(moduleSize - estimatedModuleSize_) / estimatedModuleSize_ <= 0.1f); + } */ - bool FinderPattern::aboutEquals(float moduleSize, float i, float j) const { - if (abs(i - getY()) <= moduleSize && abs(j - getX()) <= moduleSize) { - float moduleSizeDiff = abs(moduleSize - estimatedModuleSize_); - return moduleSizeDiff <= 1.0f || moduleSizeDiff <= estimatedModuleSize_; - } - return false; - } - - Ref FinderPattern::combineEstimate(float i, float j, float newModuleSize) const { - int combinedCount = count_ + 1; - float combinedX = (count_ * getX() + j) / combinedCount; - float combinedY = (count_ * getY() + i) / combinedCount; - float combinedModuleSize = (count_ * getEstimatedModuleSize() + newModuleSize) / combinedCount; - return Ref(new FinderPattern(combinedX, combinedY, combinedModuleSize, combinedCount)); - } - } +bool FinderPattern::aboutEquals(float moduleSize, float i, float j) const { + if (abs(i - getY()) <= moduleSize && abs(j - getX()) <= moduleSize) { + float moduleSizeDiff = abs(moduleSize - estimatedModuleSize_); + return moduleSizeDiff <= 1.0f || moduleSizeDiff <= estimatedModuleSize_; + } + return false; +} + +Ref FinderPattern::combineEstimate(float i, float j, float newModuleSize) const { + // fprintf(stderr, "ce %f %f %f\n", i, j, newModuleSize); + + int combinedCount = count_ + 1; + float combinedX = (count_ * getX() + j) / combinedCount; + float combinedY = (count_ * getY() + i) / combinedCount; + float combinedModuleSize = (count_ * getEstimatedModuleSize() + newModuleSize) / combinedCount; + return Ref(new FinderPattern(combinedX, combinedY, combinedModuleSize, combinedCount)); } diff --git a/source/zxing/qrcode/detector/QRFinderPatternFinder.cpp b/source/zxing/qrcode/detector/QRFinderPatternFinder.cpp index 35ce976..1f3228b 100644 --- a/source/zxing/qrcode/detector/QRFinderPatternFinder.cpp +++ b/source/zxing/qrcode/detector/QRFinderPatternFinder.cpp @@ -19,18 +19,28 @@ * limitations under the License. */ +#include #include #include #include -#include -#include -#include -#include -namespace zxing { -namespace qrcode { +using std::sort; +using std::max; +using std::abs; +using std::vector; +using zxing::Ref; +using zxing::qrcode::FinderPatternFinder; +using zxing::qrcode::FinderPattern; +using zxing::qrcode::FinderPatternInfo; -using namespace std; +// VC++ + +using zxing::BitMatrix; +using zxing::ResultPointCallback; +using zxing::ResultPoint; +using zxing::DecodeHints; + +namespace { class FurthestFromAverageComparator { private: @@ -64,6 +74,8 @@ public: } }; +} + int FinderPatternFinder::CENTER_QUORUM = 2; int FinderPatternFinder::MIN_SKIP = 3; int FinderPatternFinder::MAX_MODULES = 57; @@ -106,7 +118,7 @@ float FinderPatternFinder::crossCheckVertical(size_t startI, size_t centerJ, int i--; } if (i < 0) { - return NAN; + return nan(); } while (i >= 0 && !image_->get(centerJ, i) && stateCount[1] <= maxCount) { stateCount[1]++; @@ -114,14 +126,14 @@ float FinderPatternFinder::crossCheckVertical(size_t startI, size_t centerJ, int } // If already too many modules in this state or ran off the edge: if (i < 0 || stateCount[1] > maxCount) { - return NAN; + return nan(); } while (i >= 0 && image_->get(centerJ, i) && stateCount[0] <= maxCount) { stateCount[0]++; i--; } if (stateCount[0] > maxCount) { - return NAN; + return nan(); } // Now also count down from center @@ -131,31 +143,31 @@ float FinderPatternFinder::crossCheckVertical(size_t startI, size_t centerJ, int i++; } if (i == maxI) { - return NAN; + return nan(); } while (i < maxI && !image_->get(centerJ, i) && stateCount[3] < maxCount) { stateCount[3]++; i++; } if (i == maxI || stateCount[3] >= maxCount) { - return NAN; + return nan(); } while (i < maxI && image_->get(centerJ, i) && stateCount[4] < maxCount) { stateCount[4]++; i++; } if (stateCount[4] >= maxCount) { - return NAN; + return nan(); } // If we found a finder-pattern-like section, but its size is more than 40% different than // the original, assume it's a false positive int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + stateCount[4]; if (5 * abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal) { - return NAN; + return nan(); } - return foundPatternCross(stateCount) ? centerFromEnd(stateCount, i) : NAN; + return foundPatternCross(stateCount) ? centerFromEnd(stateCount, i) : nan(); } float FinderPatternFinder::crossCheckHorizontal(size_t startJ, size_t centerI, int maxCount, @@ -172,21 +184,21 @@ float FinderPatternFinder::crossCheckHorizontal(size_t startJ, size_t centerI, i j--; } if (j < 0) { - return NAN; + return nan(); } while (j >= 0 && !image_->get(j, centerI) && stateCount[1] <= maxCount) { stateCount[1]++; j--; } if (j < 0 || stateCount[1] > maxCount) { - return NAN; + return nan(); } while (j >= 0 && image_->get(j, centerI) && stateCount[0] <= maxCount) { stateCount[0]++; j--; } if (stateCount[0] > maxCount) { - return NAN; + return nan(); } j = startJ + 1; @@ -195,31 +207,31 @@ float FinderPatternFinder::crossCheckHorizontal(size_t startJ, size_t centerI, i j++; } if (j == maxJ) { - return NAN; + return nan(); } while (j < maxJ && !image_->get(j, centerI) && stateCount[3] < maxCount) { stateCount[3]++; j++; } if (j == maxJ || stateCount[3] >= maxCount) { - return NAN; + return nan(); } while (j < maxJ && image_->get(j, centerI) && stateCount[4] < maxCount) { stateCount[4]++; j++; } if (stateCount[4] >= maxCount) { - return NAN; + return nan(); } // If we found a finder-pattern-like section, but its size is significantly different than // the original, assume it's a false positive int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + stateCount[4]; if (5 * abs(stateCountTotal - originalStateCountTotal) >= originalStateCountTotal) { - return NAN; + return nan(); } - return foundPatternCross(stateCount) ? centerFromEnd(stateCount, j) : NAN; + return foundPatternCross(stateCount) ? centerFromEnd(stateCount, j) : nan(); } bool FinderPatternFinder::handlePossibleCenter(int* stateCount, size_t i, size_t j) { @@ -308,7 +320,7 @@ bool FinderPatternFinder::haveMultiplyConfirmedCenters() { return totalDeviation <= 0.05f * totalModuleSize; } -vector > FinderPatternFinder::selectBestPatterns() { +vector< Ref > FinderPatternFinder::selectBestPatterns() { size_t startSize = possibleCenters_.size(); if (startSize < 3) { @@ -537,5 +549,11 @@ Ref FinderPatternFinder::find(DecodeHints const& hints) { Ref result(new FinderPatternInfo(patternInfo)); return result; } + +Ref FinderPatternFinder::getImage() { + return image_; } + +vector >& FinderPatternFinder::getPossibleCenters() { + return possibleCenters_; }