EAN13Reader::EAN13Reader() { }
int EAN13Reader::decodeMiddle(Ref<BitArray> row, int startRange[], int startRangeLen,
- std::string& resultString){
+ std::string& resultString) {
const int countersLen = 4;
int counters[countersLen] = { 0, 0, 0, 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];
}
}
- 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(){
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<BitArray> row, int startRange[], int startRangeLen, std::string& resultString); //throws ReaderException
-
+
+ int decodeMiddle(Ref<BitArray> row, int startRange[], int startRangeLen,
+ std::string& resultString);
+
BarcodeFormat getBarcodeFormat();
};
}
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];
delete [] middleRange;
return rowOffset;
- } catch (ReaderException const& re) {
- delete [] middleRange;
- throw re;
}
+ return -1;
}
BarcodeFormat EAN8Reader::getBarcodeFormat(){
namespace zxing {
namespace oned {
class EAN8Reader : public UPCEANReader {
-
+
public:
EAN8Reader();
-
- int decodeMiddle(Ref<BitArray> row, int startRange[], int startRangeLen, std::string& resultString); //throws ReaderException
-
+
+ int decodeMiddle(Ref<BitArray> row, int startRange[], int startRangeLen,
+ std::string& resultString);
+
BarcodeFormat getBarcodeFormat();
};
}
}
Ref<Result> OneDReader::decode(Ref<BinaryBitmap> image, DecodeHints hints) {
- try {
- return doDecode(image, hints);
- } catch (ReaderException re) {
- if (hints.getTryHarder() && image->isRotateSupported()) {
- Ref<BinaryBitmap> rotatedImage(image->rotateCounterClockwise());
- Ref<Result> result(doDecode(rotatedImage, 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;
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<Result> OneDReader::doDecode(Ref<BinaryBitmap> image, DecodeHints hints) {
}
}
}
- throw ReaderException("doDecode() failed");
+ return Ref<Result>();
}
unsigned int OneDReader::patternMatchVariance(int counters[], int countersSize,
namespace zxing {
namespace oned {
class UPCAReader : public UPCEANReader {
-
+
private:
EAN13Reader ean13Reader;
- static Ref<Result> maybeReturnResult(Ref<Result> result); //throws ReaderException
-
+ static Ref<Result> maybeReturnResult(Ref<Result> result);
+
public:
UPCAReader();
-
- int decodeMiddle(Ref<BitArray> row, int startRange[], int startRangeLen, std::string& resultString); //throws ReaderException
-
- Ref<Result> decodeRow(int rowNumber, Ref<BitArray> row); //throws ReaderException
- Ref<Result> decodeRow(int rowNumber, Ref<BitArray> row, int startGuardRange[]); //throws ReaderException
+
+ int decodeMiddle(Ref<BitArray> row, int startRange[], int startRangeLen,
+ std::string& resultString);
+
+ Ref<Result> decodeRow(int rowNumber, Ref<BitArray> row);
+ Ref<Result> decodeRow(int rowNumber, Ref<BitArray> row, int startGuardRange[]);
Ref<Result> decode(Ref<BinaryBitmap> image, DecodeHints hints);
-
+
BarcodeFormat getBarcodeFormat();
};
}
Ref<Result> UPCEANReader::decodeRow(int rowNumber, Ref<BitArray> row) {
- int* start = NULL;
- try {
- start = findStartGuardPattern(row);
- Ref<Result> result = decodeRow(rowNumber, row, start);
- delete [] start;
- return result;
- } catch (ReaderException const& re) {
- delete [] start;
- return Ref<Result>();
+ int* start = findStartGuardPattern(row);
+ if (start != NULL) {
+ try {
+ Ref<Result> result = decodeRow(rowNumber, row, start);
+ delete [] start;
+ return result;
+ } catch (ReaderException const& re) {
+ delete [] start;
+ }
}
+ return Ref<Result>();
}
Ref<Result> UPCEANReader::decodeRow(int rowNumber, Ref<BitArray> 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<Result>();
+ }
+ int* endRange = decodeEnd(row, endStart);
+ if (endRange == NULL) {
+ return Ref<Result>();
+ }
- 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<Result>();
+ }
- Ref<String> resultString(new String(tmpResultString));
+ if (!checkChecksum(tmpResultString)) {
+ delete [] endRange;
+ return Ref<Result>();
+ }
- float left = (float) (startGuardRange[1] + startGuardRange[0]) / 2.0f;
- float right = (float) (endRange[1] + endRange[0]) / 2.0f;
+ Ref<String> resultString(new String(tmpResultString));
- std::vector< Ref<ResultPoint> > resultPoints(2);
- Ref<OneDResultPoint> resultPoint1(new OneDResultPoint(left, (float) rowNumber));
- Ref<OneDResultPoint> 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<unsigned char> resultBytes(1);
+ std::vector< Ref<ResultPoint> > resultPoints(2);
+ Ref<OneDResultPoint> resultPoint1(new OneDResultPoint(left, (float) rowNumber));
+ Ref<OneDResultPoint> resultPoint2(new OneDResultPoint(right, (float) rowNumber));
+ resultPoints[0] = resultPoint1;
+ resultPoints[1] = resultPoint2;
- Ref<Result> res(new Result(resultString, resultBytes, resultPoints, getBarcodeFormat()));
- delete [] endRange;
- return res;
- } catch (ReaderException const& re) {
- delete [] endRange;
- throw re;
- }
+ ArrayRef<unsigned char> resultBytes(1);
+ Ref<Result> res(new Result(resultString, resultBytes, resultPoints, getBarcodeFormat()));
+ delete [] endRange;
+ return res;
}
int* UPCEANReader::findStartGuardPattern(Ref<BitArray> 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<int, int> for return value to avoid using the heap.
isWhite = !isWhite;
}
}
- throw ReaderException("findGuardPattern");
+ return NULL;
}
int* UPCEANReader::decodeEnd(Ref<BitArray> row, int endStart) {
int UPCEANReader::decodeDigit(Ref<BitArray> 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;
default:
break;
}
- if (bestMatch >= 0) {
- return bestMatch;
- } else {
- throw ReaderException("UPCEANReader::decodeDigit: No best mach");
- }
+ return bestMatch;
}
-
/**
* @return {@link #checkStandardUPCEANChecksum(String)}
*/
*
* @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();
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;
}
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;
}
* limitations under the License.
*/
-#pragma once
-
#include <zxing/oned/OneDReader.h>
#include <zxing/common/BitArray.h>
#include <zxing/Result.h>
+
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<BitArray> row); //throws ReaderException
-
- virtual int* decodeEnd(Ref<BitArray> row, int endStart); //throws ReaderException
-
- static bool checkStandardUPCEANChecksum(std::string s); //throws ReaderException
+
+ static int* findStartGuardPattern(Ref<BitArray> row);
+
+ virtual int* decodeEnd(Ref<BitArray> row, int endStart);
+
+ static bool checkStandardUPCEANChecksum(std::string s);
protected:
- static int* findGuardPattern(Ref<BitArray> row, int rowOffset, bool whiteFirst, const int pattern[], int patternLen); //throws ReaderException
-
+ static int* findGuardPattern(Ref<BitArray> 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<BitArray> row, int startRange[], int startRangeLen, std::string& resultString) = 0; //throws ReaderException
-
+
+ // Returns < 0 on failure, >= 0 on success.
+ virtual int decodeMiddle(Ref<BitArray> row, int startRange[], int startRangeLen,
+ 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[]);
-
- static int decodeDigit(Ref<BitArray> 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<BitArray> row, int counters[], int countersLen, int rowOffset,
+ UPC_EAN_PATTERNS patternType);
+
+ virtual bool checkChecksum(std::string s);
+
virtual BarcodeFormat getBarcodeFormat() = 0;
virtual ~UPCEANReader();
};
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];
}
}
- determineNumSysAndCheckDigit(resultString, lgPatternFound);
-
+ if (!determineNumSysAndCheckDigit(resultString, lgPatternFound)) {
+ return -1;
+ }
return rowOffset;
}
}
- 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;
}
/**
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<BitArray> row, int endStart); //throws ReaderException
- bool checkChecksum(std::string s); //throws ReaderException
+ int* decodeEnd(Ref<BitArray> row, int endStart);
+ bool checkChecksum(std::string s);
public:
UPCEReader();
-
- int decodeMiddle(Ref<BitArray> row, int startRange[], int startRangeLen, std::string& resultString); //throws ReaderException
+
+ int decodeMiddle(Ref<BitArray> row, int startRange[], int startRangeLen,
+ std::string& resultString);
static std::string convertUPCEtoUPCA(std::string upce);
-
+
BarcodeFormat getBarcodeFormat();
};
}