Removed dynamic allocation of new int[2] when searching for
authordswitkin@google.com <dswitkin@google.com@59b500cc-1b3d-0410-9834-0bbf25fbcc57>
Wed, 25 Aug 2010 20:51:14 +0000 (20:51 +0000)
committerdswitkin@google.com <dswitkin@google.com@59b500cc-1b3d-0410-9834-0bbf25fbcc57>
Wed, 25 Aug 2010 20:51:14 +0000 (20:51 +0000)
guard patterns to improve performance.

git-svn-id: http://zxing.googlecode.com/svn/trunk@1563 59b500cc-1b3d-0410-9834-0bbf25fbcc57

cpp/core/src/zxing/oned/EAN13Reader.cpp
cpp/core/src/zxing/oned/EAN13Reader.h
cpp/core/src/zxing/oned/EAN8Reader.cpp
cpp/core/src/zxing/oned/EAN8Reader.h
cpp/core/src/zxing/oned/UPCAReader.cpp
cpp/core/src/zxing/oned/UPCAReader.h
cpp/core/src/zxing/oned/UPCEANReader.cpp
cpp/core/src/zxing/oned/UPCEANReader.h
cpp/core/src/zxing/oned/UPCEReader.cpp
cpp/core/src/zxing/oned/UPCEReader.h

index 29a9a80..223c79a 100644 (file)
@@ -29,13 +29,13 @@ namespace zxing {
 
     EAN13Reader::EAN13Reader() { }
 
-    int EAN13Reader::decodeMiddle(Ref<BitArray> row, int startRange[], int startRangeLen,
+    int EAN13Reader::decodeMiddle(Ref<BitArray> row, int startGuardBegin, int startGuardEnd,
         std::string& resultString) {
       const int countersLen = 4;
       int counters[countersLen] = { 0, 0, 0, 0 };
 
       int end = row->getSize();
-      int rowOffset = startRange[1];
+      int rowOffset = startGuardEnd;
       int lgPatternFound = 0;
 
       for (int x = 0; x < 6 && rowOffset < end; x++) {
@@ -57,15 +57,15 @@ namespace zxing {
         return -1;
       }
 
-      int* middleRange = findGuardPattern(row, rowOffset, true, (int*)getMIDDLE_PATTERN(),
-            getMIDDLE_PATTERN_LEN());
-      if (middleRange != NULL) {
-        rowOffset = middleRange[1];
+      int middleRangeStart;
+      int middleRangeEnd;
+      if (findGuardPattern(row, rowOffset, true, (int*)getMIDDLE_PATTERN(),
+            getMIDDLE_PATTERN_LEN(), &middleRangeStart, &middleRangeEnd)) {
+        rowOffset = middleRangeEnd;
         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));
@@ -73,8 +73,6 @@ namespace zxing {
             rowOffset += counters[i];
           }
         }
-
-        delete [] middleRange;
         return rowOffset;
       }
       return -1;
index 3942643..4ba4e0b 100644 (file)
@@ -33,7 +33,7 @@ namespace zxing {
     public:
       EAN13Reader();
 
-      int decodeMiddle(Ref<BitArray> row, int startRange[], int startRangeLen,
+      int decodeMiddle(Ref<BitArray> row, int startGuardBegin, int startGuardEnd,
           std::string& resultString);
 
       BarcodeFormat getBarcodeFormat();
index fb94f15..05ff5cb 100644 (file)
@@ -25,13 +25,13 @@ namespace zxing {
 
     EAN8Reader::EAN8Reader(){ }
 
-    int EAN8Reader::decodeMiddle(Ref<BitArray> row, int startRange[], int startRangeLen,
+    int EAN8Reader::decodeMiddle(Ref<BitArray> row, int startGuardBegin, int startGuardEnd,
         std::string& resultString){
       const int countersLen = 4;
       int counters[countersLen] = { 0, 0, 0, 0 };
 
       int end = row->getSize();
-      int rowOffset = startRange[1];
+      int rowOffset = startGuardEnd;
 
       for (int x = 0; x < 4 && rowOffset < end; x++) {
         int bestMatch = decodeDigit(row, counters, countersLen, rowOffset,
@@ -45,15 +45,15 @@ namespace zxing {
         }
       }
 
-      int* middleRange = findGuardPattern(row, rowOffset, true, (int*)getMIDDLE_PATTERN(),
-            getMIDDLE_PATTERN_LEN());
-      if (middleRange != NULL) {
-        rowOffset = middleRange[1];
+      int middleRangeStart;
+      int middleRangeEnd;
+      if (findGuardPattern(row, rowOffset, true, (int*)getMIDDLE_PATTERN(),
+            getMIDDLE_PATTERN_LEN(), &middleRangeStart, &middleRangeEnd)) {
+        rowOffset = middleRangeEnd;
         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));
@@ -61,8 +61,6 @@ namespace zxing {
             rowOffset += counters[i];
           }
         }
-
-        delete [] middleRange;
         return rowOffset;
       }
       return -1;
index 5709a6b..4db52fb 100644 (file)
@@ -30,7 +30,7 @@ namespace zxing {
     public:
       EAN8Reader();
 
-      int decodeMiddle(Ref<BitArray> row, int startRange[], int startRangeLen,
+      int decodeMiddle(Ref<BitArray> row, int startGuardBegin, int startGuardEnd,
           std::string& resultString);
 
       BarcodeFormat getBarcodeFormat();
index cc379a7..1eb2b6f 100644 (file)
@@ -29,17 +29,19 @@ namespace zxing {
       return maybeReturnResult(ean13Reader.decodeRow(rowNumber, row));
     }
 
-    Ref<Result> UPCAReader::decodeRow(int rowNumber, Ref<BitArray> row, int startGuardRange[]) {
-      return maybeReturnResult(ean13Reader.decodeRow(rowNumber, row, startGuardRange));
+    Ref<Result> UPCAReader::decodeRow(int rowNumber, Ref<BitArray> row, int startGuardBegin,
+        int startGuardEnd) {
+      return maybeReturnResult(ean13Reader.decodeRow(rowNumber, row, startGuardBegin,
+          startGuardEnd));
     }
 
     Ref<Result> UPCAReader::decode(Ref<BinaryBitmap> image, DecodeHints hints) {
       return maybeReturnResult(ean13Reader.decode(image, hints));
     }
 
-    int UPCAReader::decodeMiddle(Ref<BitArray> row, int startRange[], int startRangeLen,
+    int UPCAReader::decodeMiddle(Ref<BitArray> row, int startGuardBegin, int startGuardEnd,
         std::string& resultString) {
-      return ean13Reader.decodeMiddle(row, startRange, startRangeLen, resultString);
+      return ean13Reader.decodeMiddle(row, startGuardBegin, startGuardEnd, resultString);
     }
 
     Ref<Result> UPCAReader::maybeReturnResult(Ref<Result> result) {
index 4a06afd..7c61cf1 100644 (file)
@@ -33,11 +33,12 @@ namespace zxing {
     public:
       UPCAReader();
 
-      int decodeMiddle(Ref<BitArray> row, int startRange[], int startRangeLen,
+      int decodeMiddle(Ref<BitArray> row, int startGuardBegin, int startGuardEnd,
           std::string& resultString);
 
       Ref<Result> decodeRow(int rowNumber, Ref<BitArray> row);
-      Ref<Result> decodeRow(int rowNumber, Ref<BitArray> row, int startGuardRange[]);
+      Ref<Result> decodeRow(int rowNumber, Ref<BitArray> row, int startGuardBegin,
+          int startGuardEnd);
       Ref<Result> decode(Ref<BinaryBitmap> image, DecodeHints hints);
 
       BarcodeFormat getBarcodeFormat();
index 76defaf..9fe36db 100644 (file)
@@ -95,50 +95,46 @@ namespace zxing {
 
 
     Ref<Result> UPCEANReader::decodeRow(int rowNumber, Ref<BitArray> row) {
-                       int* start = findStartGuardPattern(row);
-                       if (start != NULL) {
+      int rangeStart;
+      int rangeEnd;
+                       if (findStartGuardPattern(row, &rangeStart, &rangeEnd)) {
         try {
-          Ref<Result> result = decodeRow(rowNumber, row, start);
-          delete [] start;
-          return result;
+          return decodeRow(rowNumber, row, rangeStart, rangeEnd);
         } catch (ReaderException const& re) {
-          delete [] start;
         }
                        }
                        return Ref<Result>();
     }
 
-    Ref<Result> UPCEANReader::decodeRow(int rowNumber, Ref<BitArray> row, int startGuardRange[]) {
+    Ref<Result> UPCEANReader::decodeRow(int rowNumber, Ref<BitArray> row, int startGuardBegin,
+        int startGuardEnd) {
       std::string tmpResultString;
       std::string& tmpResultStringRef = tmpResultString;
-      int endStart = decodeMiddle(row, startGuardRange, 2 /*reference findGuardPattern*/ ,
-          tmpResultStringRef);
+      int endStart = decodeMiddle(row, startGuardBegin, startGuardEnd, tmpResultStringRef);
       if (endStart < 0) {
         return Ref<Result>();
       }
-      int* endRange = decodeEnd(row, endStart);
-      if (endRange == NULL) {
+
+      int endGuardBegin;
+      int endGuardEnd;
+      if (!decodeEnd(row, endStart, &endGuardBegin, &endGuardEnd)) {
         return Ref<Result>();
       }
 
       // 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;
+      size_t quietEnd = endGuardEnd + (endGuardEnd - endGuardBegin);
+      if (quietEnd >= row->getSize() || !row->isRange(endGuardEnd, quietEnd, false)) {
         return Ref<Result>();
       }
 
       if (!checkChecksum(tmpResultString)) {
-        delete [] endRange;
         return Ref<Result>();
       }
 
       Ref<String> resultString(new String(tmpResultString));
-
-      float left = (float) (startGuardRange[1] + startGuardRange[0]) / 2.0f;
-      float right = (float) (endRange[1] + endRange[0]) / 2.0f;
+      float left = (float) (startGuardBegin + startGuardEnd) / 2.0f;
+      float right = (float) (endGuardBegin + endGuardEnd) / 2.0f;
 
       std::vector< Ref<ResultPoint> > resultPoints(2);
       Ref<OneDResultPoint> resultPoint1(new OneDResultPoint(left, (float) rowNumber));
@@ -147,38 +143,28 @@ namespace zxing {
       resultPoints[1] = resultPoint2;
 
       ArrayRef<unsigned char> resultBytes(1);
-      Ref<Result> res(new Result(resultString, resultBytes, resultPoints, getBarcodeFormat()));
-      delete [] endRange;
-      return res;
+      return Ref<Result>(new Result(resultString, resultBytes, resultPoints, getBarcodeFormat()));
     }
 
-    int* UPCEANReader::findStartGuardPattern(Ref<BitArray> row) {
-      bool foundStart = false;
-      int* startRange = NULL;
+    bool UPCEANReader::findStartGuardPattern(Ref<BitArray> row, int* rangeStart, int* rangeEnd) {
       int nextStart = 0;
-      while (!foundStart) {
-        delete [] startRange;
-        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];
+      while (findGuardPattern(row, nextStart, false, START_END_PATTERN,
+          sizeof(START_END_PATTERN) / sizeof(int), rangeStart, rangeEnd)) {
+        int start = *rangeStart;
+        nextStart = *rangeEnd;
         // 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);
+        if (quietStart >= 0 && row->isRange(quietStart, start, false)) {
+          return true;
         }
       }
-      return startRange;
+      return false;
     }
 
-    // TODO(flyashi): Return a pair<int, int> for return value to avoid using the heap.
-    int* UPCEANReader::findGuardPattern(Ref<BitArray> row, int rowOffset, bool whiteFirst,
-        const int pattern[], int patternLen) {
+    bool UPCEANReader::findGuardPattern(Ref<BitArray> row, int rowOffset, bool whiteFirst,
+        const int pattern[], int patternLen, int* start, int* end) {
       int patternLength = patternLen;
       int counters[patternLength];
       int countersCount = sizeof(counters) / sizeof(int);
@@ -205,10 +191,9 @@ namespace zxing {
           if (counterPosition == patternLength - 1) {
             if (patternMatchVariance(counters, countersCount, pattern,
                 MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) {
-              int* resultValue = new int[2];
-              resultValue[0] = patternStart;
-              resultValue[1] = x;
-              return resultValue;
+              *start = patternStart;
+              *end = x;
+              return true;
             }
             patternStart += counters[0] + counters[1];
             for (int y = 2; y < patternLength; y++) {
@@ -224,12 +209,13 @@ namespace zxing {
           isWhite = !isWhite;
         }
       }
-      return NULL;
+      return false;
     }
 
-    int* UPCEANReader::decodeEnd(Ref<BitArray> row, int endStart) {
+    bool UPCEANReader::decodeEnd(Ref<BitArray> row, int endStart, int* endGuardBegin,
+        int* endGuardEnd) {
       return findGuardPattern(row, endStart, false, START_END_PATTERN,
-          sizeof(START_END_PATTERN) / sizeof(int));
+          sizeof(START_END_PATTERN) / sizeof(int), endGuardBegin, endGuardEnd);
     }
 
     int UPCEANReader::decodeDigit(Ref<BitArray> row, int counters[], int countersLen, int rowOffset,
index 9076681..2584b26 100644 (file)
@@ -37,14 +37,14 @@ namespace zxing {
                        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<BitArray> row);
+                       static bool findStartGuardPattern(Ref<BitArray> row, int* rangeStart, int* rangeEnd);
 
-                       virtual int* decodeEnd(Ref<BitArray> row, int endStart);
+                       virtual bool decodeEnd(Ref<BitArray> row, int endStart, int* endGuardBegin, int* endGuardEnd);
 
                        static bool checkStandardUPCEANChecksum(std::string s);
                protected:
-                       static int* findGuardPattern(Ref<BitArray> row, int rowOffset, bool whiteFirst,
-                           const int pattern[], int patternLen);
+                       static bool findGuardPattern(Ref<BitArray> row, int rowOffset, bool whiteFirst,
+                           const int pattern[], int patternLen, int* start, int* end);
 
                        virtual const int getMIDDLE_PATTERN_LEN();
                        virtual const int* getMIDDLE_PATTERN();
@@ -53,13 +53,14 @@ namespace zxing {
                        UPCEANReader();
 
       // Returns < 0 on failure, >= 0 on success.
-                       virtual int decodeMiddle(Ref<BitArray> row, int startRange[], int startRangeLen,
+                       virtual int decodeMiddle(Ref<BitArray> row, int startGuardBegin, int startGuardEnd,
                            std::string& resultString) = 0;
 
                        Ref<Result> decodeRow(int rowNumber, Ref<BitArray> row);
 
                        // TODO(dswitkin): Should this be virtual so that UPCAReader can override it?
-                       Ref<Result> decodeRow(int rowNumber, Ref<BitArray> row, int startGuardRange[]);
+                       Ref<Result> decodeRow(int rowNumber, Ref<BitArray> row, int startGuardBegin,
+          int startGuardEnd);
 
       // Returns < 0 on failure, >= 0 on success.
                        static int decodeDigit(Ref<BitArray> row, int counters[], int countersLen, int rowOffset,
index cd36492..520512e 100644 (file)
@@ -42,13 +42,13 @@ namespace zxing {
     UPCEReader::UPCEReader() {
     }
 
-    int UPCEReader::decodeMiddle(Ref<BitArray> row, int startRange[], int startRangeLen,
+    int UPCEReader::decodeMiddle(Ref<BitArray> row, int startGuardBegin, int startGuardEnd,
         std::string& resultString) {
       const int countersLen = 4;
       int counters[countersLen] = { 0, 0, 0, 0 };
 
       int end = row->getSize();
-      int rowOffset = startRange[1];
+      int rowOffset = startGuardEnd;
       int lgPatternFound = 0;
 
       for (int x = 0; x < 6 && rowOffset < end; x++) {
@@ -72,9 +72,10 @@ namespace zxing {
       return rowOffset;
     }
 
-    int* UPCEReader::decodeEnd(Ref<BitArray> row, int endStart) {
+    bool UPCEReader::decodeEnd(Ref<BitArray> row, int endStart, int* endGuardBegin,
+        int* endGuardEnd) {
       return findGuardPattern(row, endStart, true, MIDDLE_END_PATTERN,
-          sizeof(MIDDLE_END_PATTERN) / sizeof(int));
+          sizeof(MIDDLE_END_PATTERN) / sizeof(int), endGuardBegin, endGuardEnd);
     }
 
     bool UPCEReader::checkChecksum(std::string s){
index 42a4fd0..0f4c61f 100644 (file)
@@ -30,12 +30,12 @@ namespace zxing {
     private:
       static bool determineNumSysAndCheckDigit(std::string& resultString, int lgPatternFound);
     protected:
-      int* decodeEnd(Ref<BitArray> row, int endStart);
+      bool decodeEnd(Ref<BitArray> row, int endStart, int* endGuardBegin, int* endGuardEnd);
       bool checkChecksum(std::string s);
     public:
       UPCEReader();
 
-      int decodeMiddle(Ref<BitArray> row, int startRange[], int startRangeLen,
+      int decodeMiddle(Ref<BitArray> row, int startGuardBegin, int startGuardEnd,
           std::string& resultString);
       static std::string convertUPCEtoUPCA(std::string upce);