Removed as many exceptions as possible from the C++ product readers
[zxing.git] / cpp / core / src / zxing / oned / OneDReader.cpp
index d8c6a31..4ba73ab 100644 (file)
@@ -2,7 +2,6 @@
  *  OneDReader.cpp
  *  ZXing
  *
- *  Created by Lukasz Warchol on 10-01-15.
  *  Copyright 2010 ZXing authors All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
 
 #include "OneDReader.h"
 #include <zxing/ReaderException.h>
+#include <zxing/oned/OneDResultPoint.h>
 #include <math.h>
+#include <limits.h>
 
 namespace zxing {
        namespace oned {
                using namespace std;
-               
+
                OneDReader::OneDReader() {
                }
-               
-               Ref<Result> OneDReader::decode(Ref<BinaryBitmap> image) {
-                       try {
-                               return doDecode(image);
-                       }catch (ReaderException re) {
-                               if (false /*tryHarder && image.isRotateSupported()*/) {
-                                       /*
-                                       BinaryBitmap rotatedImage = image.rotateCounterClockwise();
-                                       Result result = doDecode(rotatedImage, hints);
+
+               Ref<Result> OneDReader::decode(Ref<BinaryBitmap> image, DecodeHints hints) {
+                 Ref<Result> result = doDecode(image, hints);
+                 if (result.empty() && hints.getTryHarder() && image->isRotateSupported()) {
+                   Ref<BinaryBitmap> 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;
@@ -46,38 +46,36 @@ namespace zxing {
                                                                           ((Integer) metadata.get(ResultMetadataType.ORIENTATION)).intValue()) % 360;
                                        }
                                        result.putMetadata(ResultMetadataType.ORIENTATION, new Integer(orientation));
-                                       // Update result points
-                                       ResultPoint[] points = result.getResultPoints();
-                                       int height = rotatedImage.getHeight();
-                                       for (int i = 0; i < points.length; i++) {
-                                               points[i] = new ResultPoint(height - points[i].getY() - 1, points[i].getX());
-                                       }
-                                       return result;
                                        */
-                               } else {
-                                       throw re;
+          // Update result points
+                                       std::vector<Ref<ResultPoint> > points (result->getResultPoints());
+                                       int height = rotatedImage->getHeight();
+                                       for (size_t i = 0; i < points.size(); i++) {
+                                               points[i].reset(new OneDResultPoint(height - points[i]->getY() - 1, points[i]->getX()));
+                                       }
                                }
-                       }
+                 }
+                 if (result.empty()) {
+                   throw ReaderException("");
+                 }
+                 return result;
                }
-               
-               Ref<Result> OneDReader::doDecode(Ref<BinaryBitmap> image){
+
+               Ref<Result> OneDReader::doDecode(Ref<BinaryBitmap> image, DecodeHints hints) {
                        int width = image->getWidth();
                        int height = image->getHeight();
                        Ref<BitArray> row(new BitArray(width));
-//                     BitArray row = new BitArray(width);
-                       
                        int middle = height >> 1;
-                       bool tryHarder = true;//hints != null && hints.containsKey(DecodeHintType.TRY_HARDER);
-                       int rowStep = (int)fmax(1, height >> (tryHarder ? 7 : 4));
+                       bool tryHarder = hints.getTryHarder();
+                       int rowStep = (int)fmax(1, height >> (tryHarder ? 8 : 5));
                        int maxLines;
                        if (tryHarder) {
                                maxLines = height; // Look at the whole image, not just the center
                        } else {
-                               maxLines = 9; // Nine rows spaced 1/16 apart is roughly the middle half of the image
+        maxLines = 15; // 15 rows spaced 1/32 apart is roughly the middle half of the image
                        }
-                       
+
                        for (int x = 0; x < maxLines; x++) {
-                               
                                // Scanning from the middle out. Determine which row we're looking at next:
                                int rowStepsAboveOrBelow = (x + 1) >> 1;
                                bool isAbove = (x & 0x01) == 0; // i.e. is x even?
@@ -86,45 +84,57 @@ namespace zxing {
                                        // Oops, if we run off the top or bottom, stop
                                        break;
                                }
-                                       
+
                                // Estimate black point for this row and load it:
                                try {
                                        row = image->getBlackRow(rowNumber, row);
-                               }catch (ReaderException re) {
+                               } catch (ReaderException re) {
                                        continue;
+                               } catch (IllegalArgumentException re) {
+          continue;
                                }
-                               
+
                                // While we have the image data in a BitArray, it's fairly cheap to reverse it in place to
                                // handle decoding upside down barcodes.
                                for (int attempt = 0; attempt < 2; attempt++) {
                                        if (attempt == 1) { // trying again?
                                                row->reverse(); // reverse the row and continue
                                        }
-                                       try {
-                                               // Look for a barcode
-                                               Ref<Result> result = decodeRow(rowNumber, row);
-                                               // We found our barcode
-                                               if (attempt == 1) {
-                                                       //                                              // But it was upside down, so note that
-                                                       //                                              result.putMetadata(ResultMetadataType.ORIENTATION, new Integer(180));
-                                                       //                                              // And remember to flip the result points horizontally.
-                                                       //                                              ResultPoint[] points = result.getResultPoints();
-                                                       //                                              points[0] = new ResultPoint(width - points[0].getX() - 1, points[0].getY());
-                                                       //                                              points[1] = new ResultPoint(width - points[1].getX() - 1, points[1].getY());
-                                               }
-                                               return result;
-                                       } catch (ReaderException re) {
-                                               // continue -- just couldn't decode this row
-                                       }
+
+          // Look for a barcode
+          Ref<Result> result = decodeRow(rowNumber, row);
+          // We found our barcode
+          if (!result.empty()) {
+            //                                         // But it was upside down, so note that
+            //                                         result.putMetadata(ResultMetadataType.ORIENTATION, new Integer(180));
+            //                                         // And remember to flip the result points horizontally.
+            std::vector<Ref<ResultPoint> > points(result->getResultPoints());
+            // if there's exactly two points (which there should be), flip the x coordinate
+            // if there's not exactly 2, I don't know what do do with it
+            if (points.size() == 2) {
+              Ref<ResultPoint> pointZero(new OneDResultPoint(width - points[0]->getX() - 1,
+                  points[0]->getY()));
+              points[0] = pointZero;
+
+              Ref<ResultPoint> pointOne(new OneDResultPoint(width - points[1]->getX() - 1,
+                  points[1]->getY()));
+              points[1] = pointOne;
+
+              result.reset(new Result(result->getText(), result->getRawBytes(), points,
+                  result->getBarcodeFormat()));
+            }
+            return result;
+          }
                                }
                        }
-                       throw ReaderException("");
+                       return Ref<Result>();
                }
-               
-               int OneDReader::patternMatchVariance(int counters[], int countersSize, const int pattern[], int maxIndividualVariance) {
+
+               unsigned int OneDReader::patternMatchVariance(int counters[], int countersSize,
+                   const int pattern[], int maxIndividualVariance) {
                        int numCounters = countersSize;
-                       int total = 0;
-                       int patternLength = 0;
+                       unsigned int total = 0;
+                       unsigned int patternLength = 0;
                        for (int i = 0; i < numCounters; i++) {
                                total += counters[i];
                                patternLength += pattern[i];
@@ -137,10 +147,10 @@ namespace zxing {
                        // We're going to fake floating-point math in integers. We just need to use more bits.
                        // Scale up patternLength so that intermediate values below like scaledCounter will have
                        // more "significant digits"
-                       int unitBarWidth = (total << INTEGER_MATH_SHIFT) / patternLength;
+                       unsigned int unitBarWidth = (total << INTEGER_MATH_SHIFT) / patternLength;
                        maxIndividualVariance = (maxIndividualVariance * unitBarWidth) >> INTEGER_MATH_SHIFT;
-                       
-                       int totalVariance = 0;
+
+                       unsigned int totalVariance = 0;
                        for (int x = 0; x < numCounters; x++) {
                                int counter = counters[x] << INTEGER_MATH_SHIFT;
                                int scaledPattern = pattern[x] * unitBarWidth;
@@ -152,15 +162,15 @@ namespace zxing {
                        }
                        return totalVariance / total;
                }
-               
-               void OneDReader::recordPattern(Ref<BitArray> row, int start, int counters[], int countersCount){
+
+               bool OneDReader::recordPattern(Ref<BitArray> row, int start, int counters[], int countersCount) {
                        int numCounters = countersCount;//sizeof(counters) / sizeof(int);
                        for (int i = 0; i < numCounters; i++) {
                                counters[i] = 0;
                        }
                        int end = row->getSize();
                        if (start >= end) {
-                               throw ReaderException("recordPattern: start >= end");
+                               return false;
                        }
                        bool isWhite = !row->get(start);
                        int counterPosition = 0;
@@ -183,11 +193,12 @@ namespace zxing {
                        // If we read fully the last section of pixels and filled up our counters -- or filled
                        // the last counter but ran off the side of the image, OK. Otherwise, a problem.
                        if (!(counterPosition == numCounters || (counterPosition == numCounters - 1 && i == end))) {
-                               throw ReaderException("recordPattern");
+                               return false;
                        }
+                       return true;
                }
-               
+
                OneDReader::~OneDReader() {
                }
        }
-}
\ No newline at end of file
+}