From 45e643cea495289f6e95112482a3fd3086ef4431 Mon Sep 17 00:00:00 2001 From: "dswitkin@google.com" Date: Mon, 16 Aug 2010 15:17:39 +0000 Subject: [PATCH 1/1] Removed as many exceptions as possible from the C++ product readers to improve performance. There is no change in the number of images which pass the unit tests. git-svn-id: http://zxing.googlecode.com/svn/trunk@1535 59b500cc-1b3d-0410-9834-0bbf25fbcc57 --- cpp/core/src/zxing/oned/EAN13Reader.cpp | 31 ++--- cpp/core/src/zxing/oned/EAN13Reader.h | 13 ++- cpp/core/src/zxing/oned/EAN8Reader.cpp | 17 +-- cpp/core/src/zxing/oned/EAN8Reader.h | 9 +- cpp/core/src/zxing/oned/OneDReader.cpp | 24 ++-- cpp/core/src/zxing/oned/UPCAReader.h | 19 ++-- cpp/core/src/zxing/oned/UPCEANReader.cpp | 139 +++++++++++------------ cpp/core/src/zxing/oned/UPCEANReader.h | 47 ++++---- cpp/core/src/zxing/oned/UPCEReader.cpp | 15 ++- cpp/core/src/zxing/oned/UPCEReader.h | 16 +-- 10 files changed, 172 insertions(+), 158 deletions(-) diff --git a/cpp/core/src/zxing/oned/EAN13Reader.cpp b/cpp/core/src/zxing/oned/EAN13Reader.cpp index 95a4584d..29a9a807 100644 --- a/cpp/core/src/zxing/oned/EAN13Reader.cpp +++ b/cpp/core/src/zxing/oned/EAN13Reader.cpp @@ -30,7 +30,7 @@ namespace zxing { EAN13Reader::EAN13Reader() { } int EAN13Reader::decodeMiddle(Ref row, int startRange[], int startRangeLen, - std::string& resultString){ + std::string& resultString) { const int countersLen = 4; int counters[countersLen] = { 0, 0, 0, 0 }; @@ -41,6 +41,9 @@ namespace zxing { for (int x = 0; x < 6 && rowOffset < end; x++) { int bestMatch = decodeDigit(row, counters, countersLen, rowOffset, UPC_EAN_PATTERNS_L_AND_G_PATTERNS); + if (bestMatch < 0) { + return -1; + } resultString.append(1, (char) ('0' + bestMatch % 10)); for (int i = 0; i < countersLen; i++) { rowOffset += counters[i]; @@ -50,39 +53,41 @@ namespace zxing { } } - determineFirstDigit(resultString, lgPatternFound); + if (!determineFirstDigit(resultString, lgPatternFound)) { + return -1; + } - int* middleRange = 0; - try { - middleRange = findGuardPattern(row, rowOffset, true, (int*)getMIDDLE_PATTERN(), + int* middleRange = findGuardPattern(row, rowOffset, true, (int*)getMIDDLE_PATTERN(), getMIDDLE_PATTERN_LEN()); + if (middleRange != NULL) { rowOffset = middleRange[1]; - for (int x = 0; x < 6 && rowOffset < end; x++) { int bestMatch = decodeDigit(row, counters, countersLen, rowOffset, UPC_EAN_PATTERNS_L_PATTERNS); + if (bestMatch < 0) { + delete [] middleRange; + return -1; + } resultString.append(1, (char) ('0' + bestMatch)); for (int i = 0; i < countersLen; i++) { - rowOffset += counters[i]; + rowOffset += counters[i]; } } delete [] middleRange; return rowOffset; - } catch (ReaderException const& re) { - delete [] middleRange; - throw re; } + return -1; } - void EAN13Reader::determineFirstDigit(std::string& resultString, int lgPatternFound) { + bool EAN13Reader::determineFirstDigit(std::string& resultString, int lgPatternFound) { for (int d = 0; d < 10; d++) { if (lgPatternFound == FIRST_DIGIT_ENCODINGS[d]) { resultString.insert(0, 1, (char) ('0' + d)); - return; + return true; } } - throw ReaderException("determineFirstDigit"); + return false; } BarcodeFormat EAN13Reader::getBarcodeFormat(){ diff --git a/cpp/core/src/zxing/oned/EAN13Reader.h b/cpp/core/src/zxing/oned/EAN13Reader.h index 95ffa0e5..fa7b7e81 100644 --- a/cpp/core/src/zxing/oned/EAN13Reader.h +++ b/cpp/core/src/zxing/oned/EAN13Reader.h @@ -26,15 +26,16 @@ namespace zxing { namespace oned { class EAN13Reader : public UPCEANReader { - + private: - static void determineFirstDigit(std::string& resultString, int lgPatternFound); //throws ReaderException - + static bool determineFirstDigit(std::string& resultString, int lgPatternFound); + public: EAN13Reader(); - - int decodeMiddle(Ref row, int startRange[], int startRangeLen, std::string& resultString); //throws ReaderException - + + int decodeMiddle(Ref row, int startRange[], int startRangeLen, + std::string& resultString); + BarcodeFormat getBarcodeFormat(); }; } diff --git a/cpp/core/src/zxing/oned/EAN8Reader.cpp b/cpp/core/src/zxing/oned/EAN8Reader.cpp index 75bc4ad2..fb94f150 100644 --- a/cpp/core/src/zxing/oned/EAN8Reader.cpp +++ b/cpp/core/src/zxing/oned/EAN8Reader.cpp @@ -36,21 +36,26 @@ namespace zxing { for (int x = 0; x < 4 && rowOffset < end; x++) { int bestMatch = decodeDigit(row, counters, countersLen, rowOffset, UPC_EAN_PATTERNS_L_PATTERNS); + if (bestMatch < 0) { + return -1; + } resultString.append(1, (char) ('0' + bestMatch)); for (int i = 0; i < countersLen; i++) { rowOffset += counters[i]; } } - int* middleRange = 0; - try { - middleRange = findGuardPattern(row, rowOffset, true, (int*)getMIDDLE_PATTERN(), + int* middleRange = findGuardPattern(row, rowOffset, true, (int*)getMIDDLE_PATTERN(), getMIDDLE_PATTERN_LEN()); + if (middleRange != NULL) { rowOffset = middleRange[1]; - for (int x = 0; x < 4 && rowOffset < end; x++) { int bestMatch = decodeDigit(row, counters, countersLen, rowOffset, UPC_EAN_PATTERNS_L_PATTERNS); + if (bestMatch < 0) { + delete [] middleRange; + return -1; + } resultString.append(1, (char) ('0' + bestMatch)); for (int i = 0; i < countersLen; i++) { rowOffset += counters[i]; @@ -59,10 +64,8 @@ namespace zxing { delete [] middleRange; return rowOffset; - } catch (ReaderException const& re) { - delete [] middleRange; - throw re; } + return -1; } BarcodeFormat EAN8Reader::getBarcodeFormat(){ diff --git a/cpp/core/src/zxing/oned/EAN8Reader.h b/cpp/core/src/zxing/oned/EAN8Reader.h index 0118eaa3..7d3e8c53 100644 --- a/cpp/core/src/zxing/oned/EAN8Reader.h +++ b/cpp/core/src/zxing/oned/EAN8Reader.h @@ -26,12 +26,13 @@ namespace zxing { namespace oned { class EAN8Reader : public UPCEANReader { - + public: EAN8Reader(); - - int decodeMiddle(Ref row, int startRange[], int startRangeLen, std::string& resultString); //throws ReaderException - + + int decodeMiddle(Ref row, int startRange[], int startRangeLen, + std::string& resultString); + BarcodeFormat getBarcodeFormat(); }; } diff --git a/cpp/core/src/zxing/oned/OneDReader.cpp b/cpp/core/src/zxing/oned/OneDReader.cpp index 706e4043..4ba73abb 100644 --- a/cpp/core/src/zxing/oned/OneDReader.cpp +++ b/cpp/core/src/zxing/oned/OneDReader.cpp @@ -31,13 +31,12 @@ namespace zxing { } Ref OneDReader::decode(Ref image, DecodeHints hints) { - try { - return doDecode(image, hints); - } catch (ReaderException re) { - if (hints.getTryHarder() && image->isRotateSupported()) { - Ref rotatedImage(image->rotateCounterClockwise()); - Ref result(doDecode(rotatedImage, hints)); - /* + Ref result = doDecode(image, hints); + if (result.empty() && hints.getTryHarder() && image->isRotateSupported()) { + Ref rotatedImage(image->rotateCounterClockwise()); + result = doDecode(rotatedImage, hints); + if (!result.empty()) { + /* // Record that we found it rotated 90 degrees CCW / 270 degrees CW Hashtable metadata = result.getResultMetadata(); int orientation = 270; @@ -54,11 +53,12 @@ namespace zxing { for (size_t i = 0; i < points.size(); i++) { points[i].reset(new OneDResultPoint(height - points[i]->getY() - 1, points[i]->getX())); } - return result; - } else { - throw re; } - } + } + if (result.empty()) { + throw ReaderException(""); + } + return result; } Ref OneDReader::doDecode(Ref image, DecodeHints hints) { @@ -127,7 +127,7 @@ namespace zxing { } } } - throw ReaderException("doDecode() failed"); + return Ref(); } unsigned int OneDReader::patternMatchVariance(int counters[], int countersSize, diff --git a/cpp/core/src/zxing/oned/UPCAReader.h b/cpp/core/src/zxing/oned/UPCAReader.h index 493f0f63..d0d794f8 100644 --- a/cpp/core/src/zxing/oned/UPCAReader.h +++ b/cpp/core/src/zxing/oned/UPCAReader.h @@ -25,20 +25,21 @@ namespace zxing { namespace oned { class UPCAReader : public UPCEANReader { - + private: EAN13Reader ean13Reader; - static Ref maybeReturnResult(Ref result); //throws ReaderException - + static Ref maybeReturnResult(Ref result); + public: UPCAReader(); - - int decodeMiddle(Ref row, int startRange[], int startRangeLen, std::string& resultString); //throws ReaderException - - Ref decodeRow(int rowNumber, Ref row); //throws ReaderException - Ref decodeRow(int rowNumber, Ref row, int startGuardRange[]); //throws ReaderException + + int decodeMiddle(Ref row, int startRange[], int startRangeLen, + std::string& resultString); + + Ref decodeRow(int rowNumber, Ref row); + Ref decodeRow(int rowNumber, Ref row, int startGuardRange[]); Ref decode(Ref image, DecodeHints hints); - + BarcodeFormat getBarcodeFormat(); }; } diff --git a/cpp/core/src/zxing/oned/UPCEANReader.cpp b/cpp/core/src/zxing/oned/UPCEANReader.cpp index b8a66d6d..6f08e750 100644 --- a/cpp/core/src/zxing/oned/UPCEANReader.cpp +++ b/cpp/core/src/zxing/oned/UPCEANReader.cpp @@ -95,86 +95,85 @@ namespace zxing { Ref UPCEANReader::decodeRow(int rowNumber, Ref row) { - int* start = NULL; - try { - start = findStartGuardPattern(row); - Ref result = decodeRow(rowNumber, row, start); - delete [] start; - return result; - } catch (ReaderException const& re) { - delete [] start; - return Ref(); + int* start = findStartGuardPattern(row); + if (start != NULL) { + try { + Ref result = decodeRow(rowNumber, row, start); + delete [] start; + return result; + } catch (ReaderException const& re) { + delete [] start; + } } + return Ref(); } Ref UPCEANReader::decodeRow(int rowNumber, Ref row, int startGuardRange[]) { - int* endRange = NULL; - try { - std::string tmpResultString; - std::string& tmpResultStringRef = tmpResultString; - int endStart = decodeMiddle(row, startGuardRange, 2 /*reference findGuardPattern*/ , - tmpResultStringRef); - endRange = decodeEnd(row, endStart); - - // Make sure there is a quiet zone at least as big as the end pattern after the barcode. - // The spec might want more whitespace, but in practice this is the maximum we can count on. - size_t end = endRange[1]; - size_t quietEnd = end + (end - endRange[0]); - if (quietEnd >= row->getSize() || !row->isRange(end, quietEnd, false)) { - throw ReaderException("Quiet zone asserrt fail."); - } + std::string tmpResultString; + std::string& tmpResultStringRef = tmpResultString; + int endStart = decodeMiddle(row, startGuardRange, 2 /*reference findGuardPattern*/ , + tmpResultStringRef); + if (endStart < 0) { + return Ref(); + } + int* endRange = decodeEnd(row, endStart); + if (endRange == NULL) { + return Ref(); + } - if (!checkChecksum(tmpResultString)) { - throw ReaderException("Checksum fail."); - } + // Make sure there is a quiet zone at least as big as the end pattern after the barcode. + // The spec might want more whitespace, but in practice this is the maximum we can count on. + size_t end = endRange[1]; + size_t quietEnd = end + (end - endRange[0]); + if (quietEnd >= row->getSize() || !row->isRange(end, quietEnd, false)) { + delete [] endRange; + return Ref(); + } - Ref resultString(new String(tmpResultString)); + if (!checkChecksum(tmpResultString)) { + delete [] endRange; + return Ref(); + } - float left = (float) (startGuardRange[1] + startGuardRange[0]) / 2.0f; - float right = (float) (endRange[1] + endRange[0]) / 2.0f; + Ref resultString(new String(tmpResultString)); - std::vector< Ref > resultPoints(2); - Ref resultPoint1(new OneDResultPoint(left, (float) rowNumber)); - Ref resultPoint2(new OneDResultPoint(right, (float) rowNumber)); - resultPoints[0] = resultPoint1; - resultPoints[1] = resultPoint2; + float left = (float) (startGuardRange[1] + startGuardRange[0]) / 2.0f; + float right = (float) (endRange[1] + endRange[0]) / 2.0f; - ArrayRef resultBytes(1); + std::vector< Ref > resultPoints(2); + Ref resultPoint1(new OneDResultPoint(left, (float) rowNumber)); + Ref resultPoint2(new OneDResultPoint(right, (float) rowNumber)); + resultPoints[0] = resultPoint1; + resultPoints[1] = resultPoint2; - Ref res(new Result(resultString, resultBytes, resultPoints, getBarcodeFormat())); - delete [] endRange; - return res; - } catch (ReaderException const& re) { - delete [] endRange; - throw re; - } + ArrayRef resultBytes(1); + Ref res(new Result(resultString, resultBytes, resultPoints, getBarcodeFormat())); + delete [] endRange; + return res; } int* UPCEANReader::findStartGuardPattern(Ref row) { bool foundStart = false; int* startRange = NULL; int nextStart = 0; - try { - while (!foundStart) { - delete [] startRange; - startRange = NULL; - startRange = findGuardPattern(row, nextStart, false, START_END_PATTERN, - sizeof(START_END_PATTERN) / sizeof(int)); - int start = startRange[0]; - nextStart = startRange[1]; - // Make sure there is a quiet zone at least as big as the start pattern before the barcode. - // If this check would run off the left edge of the image, do not accept this barcode, - // as it is very likely to be a false positive. - int quietStart = start - (nextStart - start); - if (quietStart >= 0) { - foundStart = row->isRange(quietStart, start, false); - } - } - return startRange; - } catch (ReaderException const& re) { + while (!foundStart) { delete [] startRange; - throw re; + startRange = findGuardPattern(row, nextStart, false, START_END_PATTERN, + sizeof(START_END_PATTERN) / sizeof(int)); + if (startRange == NULL) { + return NULL; + } + int start = startRange[0]; + nextStart = startRange[1]; + // Make sure there is a quiet zone at least as big as the start pattern before the barcode. + // If this check would run off the left edge of the image, do not accept this barcode, + // as it is very likely to be a false positive. + int quietStart = start - (nextStart - start); + if (quietStart >= 0) { + foundStart = row->isRange(quietStart, start, false); + } } + return startRange; } // TODO(flyashi): Return a pair for return value to avoid using the heap. @@ -225,7 +224,7 @@ namespace zxing { isWhite = !isWhite; } } - throw ReaderException("findGuardPattern"); + return NULL; } int* UPCEANReader::decodeEnd(Ref row, int endStart) { @@ -236,7 +235,7 @@ namespace zxing { int UPCEANReader::decodeDigit(Ref row, int counters[], int countersLen, int rowOffset, UPC_EAN_PATTERNS patternType) { if (!recordPattern(row, rowOffset, counters, countersLen)) { - throw ReaderException(""); + return -1; } unsigned int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept int bestMatch = -1; @@ -278,14 +277,9 @@ namespace zxing { default: break; } - if (bestMatch >= 0) { - return bestMatch; - } else { - throw ReaderException("UPCEANReader::decodeDigit: No best mach"); - } + return bestMatch; } - /** * @return {@link #checkStandardUPCEANChecksum(String)} */ @@ -299,7 +293,6 @@ namespace zxing { * * @param s string of digits to check * @return true iff string of digits passes the UPC/EAN checksum algorithm - * @throws ReaderException if the string does not contain only digits */ bool UPCEANReader::checkStandardUPCEANChecksum(std::string s) { int length = s.length(); @@ -311,7 +304,7 @@ namespace zxing { for (int i = length - 2; i >= 0; i -= 2) { int digit = (int) s[i] - (int) '0'; if (digit < 0 || digit > 9) { - throw ReaderException("checkStandardUPCEANChecksum"); + return false; } sum += digit; } @@ -319,7 +312,7 @@ namespace zxing { for (int i = length - 1; i >= 0; i -= 2) { int digit = (int) s[i] - (int) '0'; if (digit < 0 || digit > 9) { - throw ReaderException("checkStandardUPCEANChecksum"); + return false; } sum += digit; } diff --git a/cpp/core/src/zxing/oned/UPCEANReader.h b/cpp/core/src/zxing/oned/UPCEANReader.h index 5ce7ab01..90766814 100644 --- a/cpp/core/src/zxing/oned/UPCEANReader.h +++ b/cpp/core/src/zxing/oned/UPCEANReader.h @@ -20,46 +20,53 @@ * limitations under the License. */ -#pragma once - #include #include #include + typedef enum UPC_EAN_PATTERNS { UPC_EAN_PATTERNS_L_PATTERNS = 0, UPC_EAN_PATTERNS_L_AND_G_PATTERNS } UPC_EAN_PATTERNS; + namespace zxing { namespace oned { class UPCEANReader : public OneDReader { - + private: static const unsigned int MAX_AVG_VARIANCE = (unsigned int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.42f); static const int MAX_INDIVIDUAL_VARIANCE = (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.7f); - - static int* findStartGuardPattern(Ref row); //throws ReaderException - - virtual int* decodeEnd(Ref row, int endStart); //throws ReaderException - - static bool checkStandardUPCEANChecksum(std::string s); //throws ReaderException + + static int* findStartGuardPattern(Ref row); + + virtual int* decodeEnd(Ref row, int endStart); + + static bool checkStandardUPCEANChecksum(std::string s); protected: - static int* findGuardPattern(Ref row, int rowOffset, bool whiteFirst, const int pattern[], int patternLen); //throws ReaderException - + static int* findGuardPattern(Ref row, int rowOffset, bool whiteFirst, + const int pattern[], int patternLen); + virtual const int getMIDDLE_PATTERN_LEN(); virtual const int* getMIDDLE_PATTERN(); - + public: UPCEANReader(); - - virtual int decodeMiddle(Ref row, int startRange[], int startRangeLen, std::string& resultString) = 0; //throws ReaderException - + + // Returns < 0 on failure, >= 0 on success. + virtual int decodeMiddle(Ref row, int startRange[], int startRangeLen, + std::string& resultString) = 0; + Ref decodeRow(int rowNumber, Ref row); + + // TODO(dswitkin): Should this be virtual so that UPCAReader can override it? Ref decodeRow(int rowNumber, Ref row, int startGuardRange[]); - - static int decodeDigit(Ref row, int counters[], int countersLen, int rowOffset, UPC_EAN_PATTERNS patternType); //throws ReaderException - - virtual bool checkChecksum(std::string s); //throws ReaderException - + + // Returns < 0 on failure, >= 0 on success. + static int decodeDigit(Ref row, int counters[], int countersLen, int rowOffset, + UPC_EAN_PATTERNS patternType); + + virtual bool checkChecksum(std::string s); + virtual BarcodeFormat getBarcodeFormat() = 0; virtual ~UPCEANReader(); }; diff --git a/cpp/core/src/zxing/oned/UPCEReader.cpp b/cpp/core/src/zxing/oned/UPCEReader.cpp index ad12c257..7772ed9b 100644 --- a/cpp/core/src/zxing/oned/UPCEReader.cpp +++ b/cpp/core/src/zxing/oned/UPCEReader.cpp @@ -49,12 +49,14 @@ namespace zxing { int end = row->getSize(); int rowOffset = startRange[1]; - int lgPatternFound = 0; for (int x = 0; x < 6 && rowOffset < end; x++) { int bestMatch = decodeDigit(row, counters, countersLen, rowOffset, UPC_EAN_PATTERNS_L_AND_G_PATTERNS); + if (bestMatch < 0) { + return -1; + } resultString.append(1, (char) ('0' + bestMatch % 10)); for (int i = 0; i < countersLen; i++) { rowOffset += counters[i]; @@ -64,8 +66,9 @@ namespace zxing { } } - determineNumSysAndCheckDigit(resultString, lgPatternFound); - + if (!determineNumSysAndCheckDigit(resultString, lgPatternFound)) { + return -1; + } return rowOffset; } @@ -79,17 +82,17 @@ namespace zxing { } - void UPCEReader::determineNumSysAndCheckDigit(std::string& resultString, int lgPatternFound) { + bool UPCEReader::determineNumSysAndCheckDigit(std::string& resultString, int lgPatternFound) { for (int numSys = 0; numSys <= 1; numSys++) { for (int d = 0; d < 10; d++) { if (lgPatternFound == NUMSYS_AND_CHECK_DIGIT_PATTERNS[numSys][d]) { resultString.insert(0, 1, (char) ('0' + numSys)); resultString.append(1, (char) ('0' + d)); - return; + return true; } } } - throw ReaderException("determineNumSysAndCheckDigit exception"); + return false; } /** diff --git a/cpp/core/src/zxing/oned/UPCEReader.h b/cpp/core/src/zxing/oned/UPCEReader.h index 2a9e89a0..a42f29f1 100644 --- a/cpp/core/src/zxing/oned/UPCEReader.h +++ b/cpp/core/src/zxing/oned/UPCEReader.h @@ -26,19 +26,19 @@ namespace zxing { namespace oned { class UPCEReader : public UPCEANReader { - + private: - static void determineFirstDigit(std::string& resultString, int lgPatternFound); //throws ReaderException - static void determineNumSysAndCheckDigit(std::string& resultString, int lgPatternFound); //throws ReaderException + static bool determineNumSysAndCheckDigit(std::string& resultString, int lgPatternFound); protected: - int* decodeEnd(Ref row, int endStart); //throws ReaderException - bool checkChecksum(std::string s); //throws ReaderException + int* decodeEnd(Ref row, int endStart); + bool checkChecksum(std::string s); public: UPCEReader(); - - int decodeMiddle(Ref row, int startRange[], int startRangeLen, std::string& resultString); //throws ReaderException + + int decodeMiddle(Ref row, int startRange[], int startRangeLen, + std::string& resultString); static std::string convertUPCEtoUPCA(std::string upce); - + BarcodeFormat getBarcodeFormat(); }; } -- 2.20.1