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: https://zxing.googlecode.com/svn/trunk@1535 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
dswitkin@google.com 2010-08-16 15:17:39 +00:00
parent c194eb915c
commit e68b2951f4
10 changed files with 175 additions and 161 deletions

View file

@ -30,7 +30,7 @@ namespace zxing {
EAN13Reader::EAN13Reader() { } EAN13Reader::EAN13Reader() { }
int EAN13Reader::decodeMiddle(Ref<BitArray> row, int startRange[], int startRangeLen, int EAN13Reader::decodeMiddle(Ref<BitArray> row, int startRange[], int startRangeLen,
std::string& resultString){ std::string& resultString) {
const int countersLen = 4; const int countersLen = 4;
int counters[countersLen] = { 0, 0, 0, 0 }; int counters[countersLen] = { 0, 0, 0, 0 };
@ -41,6 +41,9 @@ namespace zxing {
for (int x = 0; x < 6 && rowOffset < end; x++) { for (int x = 0; x < 6 && rowOffset < end; x++) {
int bestMatch = decodeDigit(row, counters, countersLen, rowOffset, int bestMatch = decodeDigit(row, counters, countersLen, rowOffset,
UPC_EAN_PATTERNS_L_AND_G_PATTERNS); UPC_EAN_PATTERNS_L_AND_G_PATTERNS);
if (bestMatch < 0) {
return -1;
}
resultString.append(1, (char) ('0' + bestMatch % 10)); resultString.append(1, (char) ('0' + bestMatch % 10));
for (int i = 0; i < countersLen; i++) { for (int i = 0; i < countersLen; i++) {
rowOffset += counters[i]; rowOffset += counters[i];
@ -50,39 +53,41 @@ namespace zxing {
} }
} }
determineFirstDigit(resultString, lgPatternFound); if (!determineFirstDigit(resultString, lgPatternFound)) {
return -1;
}
int* middleRange = 0; int* middleRange = findGuardPattern(row, rowOffset, true, (int*)getMIDDLE_PATTERN(),
try {
middleRange = findGuardPattern(row, rowOffset, true, (int*)getMIDDLE_PATTERN(),
getMIDDLE_PATTERN_LEN()); getMIDDLE_PATTERN_LEN());
if (middleRange != NULL) {
rowOffset = middleRange[1]; rowOffset = middleRange[1];
for (int x = 0; x < 6 && rowOffset < end; x++) { for (int x = 0; x < 6 && rowOffset < end; x++) {
int bestMatch = decodeDigit(row, counters, countersLen, rowOffset, int bestMatch = decodeDigit(row, counters, countersLen, rowOffset,
UPC_EAN_PATTERNS_L_PATTERNS); UPC_EAN_PATTERNS_L_PATTERNS);
if (bestMatch < 0) {
delete [] middleRange;
return -1;
}
resultString.append(1, (char) ('0' + bestMatch)); resultString.append(1, (char) ('0' + bestMatch));
for (int i = 0; i < countersLen; i++) { for (int i = 0; i < countersLen; i++) {
rowOffset += counters[i]; rowOffset += counters[i];
} }
} }
delete [] middleRange; delete [] middleRange;
return rowOffset; 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++) { for (int d = 0; d < 10; d++) {
if (lgPatternFound == FIRST_DIGIT_ENCODINGS[d]) { if (lgPatternFound == FIRST_DIGIT_ENCODINGS[d]) {
resultString.insert(0, 1, (char) ('0' + d)); resultString.insert(0, 1, (char) ('0' + d));
return; return true;
} }
} }
throw ReaderException("determineFirstDigit"); return false;
} }
BarcodeFormat EAN13Reader::getBarcodeFormat(){ BarcodeFormat EAN13Reader::getBarcodeFormat(){

View file

@ -26,15 +26,16 @@
namespace zxing { namespace zxing {
namespace oned { namespace oned {
class EAN13Reader : public UPCEANReader { class EAN13Reader : public UPCEANReader {
private: private:
static void determineFirstDigit(std::string& resultString, int lgPatternFound); //throws ReaderException static bool determineFirstDigit(std::string& resultString, int lgPatternFound);
public: public:
EAN13Reader(); 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(); BarcodeFormat getBarcodeFormat();
}; };
} }

View file

@ -36,21 +36,26 @@ namespace zxing {
for (int x = 0; x < 4 && rowOffset < end; x++) { for (int x = 0; x < 4 && rowOffset < end; x++) {
int bestMatch = decodeDigit(row, counters, countersLen, rowOffset, int bestMatch = decodeDigit(row, counters, countersLen, rowOffset,
UPC_EAN_PATTERNS_L_PATTERNS); UPC_EAN_PATTERNS_L_PATTERNS);
if (bestMatch < 0) {
return -1;
}
resultString.append(1, (char) ('0' + bestMatch)); resultString.append(1, (char) ('0' + bestMatch));
for (int i = 0; i < countersLen; i++) { for (int i = 0; i < countersLen; i++) {
rowOffset += counters[i]; rowOffset += counters[i];
} }
} }
int* middleRange = 0; int* middleRange = findGuardPattern(row, rowOffset, true, (int*)getMIDDLE_PATTERN(),
try {
middleRange = findGuardPattern(row, rowOffset, true, (int*)getMIDDLE_PATTERN(),
getMIDDLE_PATTERN_LEN()); getMIDDLE_PATTERN_LEN());
if (middleRange != NULL) {
rowOffset = middleRange[1]; rowOffset = middleRange[1];
for (int x = 0; x < 4 && rowOffset < end; x++) { for (int x = 0; x < 4 && rowOffset < end; x++) {
int bestMatch = decodeDigit(row, counters, countersLen, rowOffset, int bestMatch = decodeDigit(row, counters, countersLen, rowOffset,
UPC_EAN_PATTERNS_L_PATTERNS); UPC_EAN_PATTERNS_L_PATTERNS);
if (bestMatch < 0) {
delete [] middleRange;
return -1;
}
resultString.append(1, (char) ('0' + bestMatch)); resultString.append(1, (char) ('0' + bestMatch));
for (int i = 0; i < countersLen; i++) { for (int i = 0; i < countersLen; i++) {
rowOffset += counters[i]; rowOffset += counters[i];
@ -59,10 +64,8 @@ namespace zxing {
delete [] middleRange; delete [] middleRange;
return rowOffset; return rowOffset;
} catch (ReaderException const& re) {
delete [] middleRange;
throw re;
} }
return -1;
} }
BarcodeFormat EAN8Reader::getBarcodeFormat(){ BarcodeFormat EAN8Reader::getBarcodeFormat(){

View file

@ -26,12 +26,13 @@
namespace zxing { namespace zxing {
namespace oned { namespace oned {
class EAN8Reader : public UPCEANReader { class EAN8Reader : public UPCEANReader {
public: public:
EAN8Reader(); 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(); BarcodeFormat getBarcodeFormat();
}; };
} }

View file

@ -31,13 +31,12 @@ namespace zxing {
} }
Ref<Result> OneDReader::decode(Ref<BinaryBitmap> image, DecodeHints hints) { Ref<Result> OneDReader::decode(Ref<BinaryBitmap> image, DecodeHints hints) {
try { Ref<Result> result = doDecode(image, hints);
return doDecode(image, hints); if (result.empty() && hints.getTryHarder() && image->isRotateSupported()) {
} catch (ReaderException re) { Ref<BinaryBitmap> rotatedImage(image->rotateCounterClockwise());
if (hints.getTryHarder() && image->isRotateSupported()) { result = doDecode(rotatedImage, hints);
Ref<BinaryBitmap> rotatedImage(image->rotateCounterClockwise()); if (!result.empty()) {
Ref<Result> result(doDecode(rotatedImage, hints)); /*
/*
// Record that we found it rotated 90 degrees CCW / 270 degrees CW // Record that we found it rotated 90 degrees CCW / 270 degrees CW
Hashtable metadata = result.getResultMetadata(); Hashtable metadata = result.getResultMetadata();
int orientation = 270; int orientation = 270;
@ -54,11 +53,12 @@ namespace zxing {
for (size_t i = 0; i < points.size(); i++) { for (size_t i = 0; i < points.size(); i++) {
points[i].reset(new OneDResultPoint(height - points[i]->getY() - 1, points[i]->getX())); 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) { Ref<Result> OneDReader::doDecode(Ref<BinaryBitmap> image, DecodeHints hints) {
@ -127,7 +127,7 @@ namespace zxing {
} }
} }
} }
throw ReaderException("doDecode() failed"); return Ref<Result>();
} }
unsigned int OneDReader::patternMatchVariance(int counters[], int countersSize, unsigned int OneDReader::patternMatchVariance(int counters[], int countersSize,

View file

@ -25,20 +25,21 @@
namespace zxing { namespace zxing {
namespace oned { namespace oned {
class UPCAReader : public UPCEANReader { class UPCAReader : public UPCEANReader {
private: private:
EAN13Reader ean13Reader; EAN13Reader ean13Reader;
static Ref<Result> maybeReturnResult(Ref<Result> result); //throws ReaderException static Ref<Result> maybeReturnResult(Ref<Result> result);
public: public:
UPCAReader(); UPCAReader();
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);
Ref<Result> decodeRow(int rowNumber, Ref<BitArray> row); //throws ReaderException
Ref<Result> decodeRow(int rowNumber, Ref<BitArray> row, int startGuardRange[]); //throws ReaderException 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); Ref<Result> decode(Ref<BinaryBitmap> image, DecodeHints hints);
BarcodeFormat getBarcodeFormat(); BarcodeFormat getBarcodeFormat();
}; };
} }

View file

@ -95,86 +95,85 @@ namespace zxing {
Ref<Result> UPCEANReader::decodeRow(int rowNumber, Ref<BitArray> row) { Ref<Result> UPCEANReader::decodeRow(int rowNumber, Ref<BitArray> row) {
int* start = NULL; int* start = findStartGuardPattern(row);
try { if (start != NULL) {
start = findStartGuardPattern(row); try {
Ref<Result> result = decodeRow(rowNumber, row, start); Ref<Result> result = decodeRow(rowNumber, row, start);
delete [] start; delete [] start;
return result; return result;
} catch (ReaderException const& re) { } catch (ReaderException const& re) {
delete [] start; delete [] start;
return Ref<Result>(); }
} }
return Ref<Result>();
} }
Ref<Result> UPCEANReader::decodeRow(int rowNumber, Ref<BitArray> row, int startGuardRange[]) { Ref<Result> UPCEANReader::decodeRow(int rowNumber, Ref<BitArray> row, int startGuardRange[]) {
int* endRange = NULL; std::string tmpResultString;
try { std::string& tmpResultStringRef = tmpResultString;
std::string tmpResultString; int endStart = decodeMiddle(row, startGuardRange, 2 /*reference findGuardPattern*/ ,
std::string& tmpResultStringRef = tmpResultString; tmpResultStringRef);
int endStart = decodeMiddle(row, startGuardRange, 2 /*reference findGuardPattern*/ , if (endStart < 0) {
tmpResultStringRef); return Ref<Result>();
endRange = decodeEnd(row, endStart); }
int* endRange = decodeEnd(row, endStart);
if (endRange == NULL) {
return Ref<Result>();
}
// Make sure there is a quiet zone at least as big as the end pattern after the barcode. // 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. // The spec might want more whitespace, but in practice this is the maximum we can count on.
size_t end = endRange[1]; size_t end = endRange[1];
size_t quietEnd = end + (end - endRange[0]); size_t quietEnd = end + (end - endRange[0]);
if (quietEnd >= row->getSize() || !row->isRange(end, quietEnd, false)) { if (quietEnd >= row->getSize() || !row->isRange(end, quietEnd, false)) {
throw ReaderException("Quiet zone asserrt fail.");
}
if (!checkChecksum(tmpResultString)) {
throw ReaderException("Checksum fail.");
}
Ref<String> resultString(new String(tmpResultString));
float left = (float) (startGuardRange[1] + startGuardRange[0]) / 2.0f;
float right = (float) (endRange[1] + endRange[0]) / 2.0f;
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;
ArrayRef<unsigned char> resultBytes(1);
Ref<Result> res(new Result(resultString, resultBytes, resultPoints, getBarcodeFormat()));
delete [] endRange; delete [] endRange;
return res; return Ref<Result>();
} catch (ReaderException const& re) { }
if (!checkChecksum(tmpResultString)) {
delete [] endRange; delete [] endRange;
throw re; 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;
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;
ArrayRef<unsigned char> resultBytes(1);
Ref<Result> res(new Result(resultString, resultBytes, resultPoints, getBarcodeFormat()));
delete [] endRange;
return res;
} }
int* UPCEANReader::findStartGuardPattern(Ref<BitArray> row) { int* UPCEANReader::findStartGuardPattern(Ref<BitArray> row) {
bool foundStart = false; bool foundStart = false;
int* startRange = NULL; int* startRange = NULL;
int nextStart = 0; int nextStart = 0;
try { while (!foundStart) {
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) {
delete [] startRange; 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. // TODO(flyashi): Return a pair<int, int> for return value to avoid using the heap.
@ -225,7 +224,7 @@ namespace zxing {
isWhite = !isWhite; isWhite = !isWhite;
} }
} }
throw ReaderException("findGuardPattern"); return NULL;
} }
int* UPCEANReader::decodeEnd(Ref<BitArray> row, int endStart) { int* UPCEANReader::decodeEnd(Ref<BitArray> row, int endStart) {
@ -236,7 +235,7 @@ namespace zxing {
int UPCEANReader::decodeDigit(Ref<BitArray> row, int counters[], int countersLen, int rowOffset, int UPCEANReader::decodeDigit(Ref<BitArray> row, int counters[], int countersLen, int rowOffset,
UPC_EAN_PATTERNS patternType) { UPC_EAN_PATTERNS patternType) {
if (!recordPattern(row, rowOffset, counters, countersLen)) { if (!recordPattern(row, rowOffset, counters, countersLen)) {
throw ReaderException(""); return -1;
} }
unsigned int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept unsigned int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept
int bestMatch = -1; int bestMatch = -1;
@ -278,14 +277,9 @@ namespace zxing {
default: default:
break; break;
} }
if (bestMatch >= 0) { return bestMatch;
return bestMatch;
} else {
throw ReaderException("UPCEANReader::decodeDigit: No best mach");
}
} }
/** /**
* @return {@link #checkStandardUPCEANChecksum(String)} * @return {@link #checkStandardUPCEANChecksum(String)}
*/ */
@ -299,7 +293,6 @@ namespace zxing {
* *
* @param s string of digits to check * @param s string of digits to check
* @return true iff string of digits passes the UPC/EAN checksum algorithm * @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) { bool UPCEANReader::checkStandardUPCEANChecksum(std::string s) {
int length = s.length(); int length = s.length();
@ -311,7 +304,7 @@ namespace zxing {
for (int i = length - 2; i >= 0; i -= 2) { for (int i = length - 2; i >= 0; i -= 2) {
int digit = (int) s[i] - (int) '0'; int digit = (int) s[i] - (int) '0';
if (digit < 0 || digit > 9) { if (digit < 0 || digit > 9) {
throw ReaderException("checkStandardUPCEANChecksum"); return false;
} }
sum += digit; sum += digit;
} }
@ -319,7 +312,7 @@ namespace zxing {
for (int i = length - 1; i >= 0; i -= 2) { for (int i = length - 1; i >= 0; i -= 2) {
int digit = (int) s[i] - (int) '0'; int digit = (int) s[i] - (int) '0';
if (digit < 0 || digit > 9) { if (digit < 0 || digit > 9) {
throw ReaderException("checkStandardUPCEANChecksum"); return false;
} }
sum += digit; sum += digit;
} }

View file

@ -20,46 +20,53 @@
* limitations under the License. * limitations under the License.
*/ */
#pragma once
#include <zxing/oned/OneDReader.h> #include <zxing/oned/OneDReader.h>
#include <zxing/common/BitArray.h> #include <zxing/common/BitArray.h>
#include <zxing/Result.h> #include <zxing/Result.h>
typedef enum UPC_EAN_PATTERNS { typedef enum UPC_EAN_PATTERNS {
UPC_EAN_PATTERNS_L_PATTERNS = 0, UPC_EAN_PATTERNS_L_PATTERNS = 0,
UPC_EAN_PATTERNS_L_AND_G_PATTERNS UPC_EAN_PATTERNS_L_AND_G_PATTERNS
} UPC_EAN_PATTERNS; } UPC_EAN_PATTERNS;
namespace zxing { namespace zxing {
namespace oned { namespace oned {
class UPCEANReader : public OneDReader { class UPCEANReader : public OneDReader {
private: private:
static const unsigned int MAX_AVG_VARIANCE = (unsigned int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.42f); 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 const int MAX_INDIVIDUAL_VARIANCE = (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.7f);
static int* findStartGuardPattern(Ref<BitArray> row); //throws ReaderException static int* findStartGuardPattern(Ref<BitArray> row);
virtual int* decodeEnd(Ref<BitArray> row, int endStart); //throws ReaderException virtual int* decodeEnd(Ref<BitArray> row, int endStart);
static bool checkStandardUPCEANChecksum(std::string s); //throws ReaderException static bool checkStandardUPCEANChecksum(std::string s);
protected: 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_LEN();
virtual const int* getMIDDLE_PATTERN(); virtual const int* getMIDDLE_PATTERN();
public: public:
UPCEANReader(); 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); 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 startGuardRange[]);
static int decodeDigit(Ref<BitArray> row, int counters[], int countersLen, int rowOffset, UPC_EAN_PATTERNS patternType); //throws ReaderException // Returns < 0 on failure, >= 0 on success.
static int decodeDigit(Ref<BitArray> row, int counters[], int countersLen, int rowOffset,
virtual bool checkChecksum(std::string s); //throws ReaderException UPC_EAN_PATTERNS patternType);
virtual bool checkChecksum(std::string s);
virtual BarcodeFormat getBarcodeFormat() = 0; virtual BarcodeFormat getBarcodeFormat() = 0;
virtual ~UPCEANReader(); virtual ~UPCEANReader();
}; };

View file

@ -49,12 +49,14 @@ namespace zxing {
int end = row->getSize(); int end = row->getSize();
int rowOffset = startRange[1]; int rowOffset = startRange[1];
int lgPatternFound = 0; int lgPatternFound = 0;
for (int x = 0; x < 6 && rowOffset < end; x++) { for (int x = 0; x < 6 && rowOffset < end; x++) {
int bestMatch = decodeDigit(row, counters, countersLen, rowOffset, int bestMatch = decodeDigit(row, counters, countersLen, rowOffset,
UPC_EAN_PATTERNS_L_AND_G_PATTERNS); UPC_EAN_PATTERNS_L_AND_G_PATTERNS);
if (bestMatch < 0) {
return -1;
}
resultString.append(1, (char) ('0' + bestMatch % 10)); resultString.append(1, (char) ('0' + bestMatch % 10));
for (int i = 0; i < countersLen; i++) { for (int i = 0; i < countersLen; i++) {
rowOffset += counters[i]; rowOffset += counters[i];
@ -64,8 +66,9 @@ namespace zxing {
} }
} }
determineNumSysAndCheckDigit(resultString, lgPatternFound); if (!determineNumSysAndCheckDigit(resultString, lgPatternFound)) {
return -1;
}
return rowOffset; 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 numSys = 0; numSys <= 1; numSys++) {
for (int d = 0; d < 10; d++) { for (int d = 0; d < 10; d++) {
if (lgPatternFound == NUMSYS_AND_CHECK_DIGIT_PATTERNS[numSys][d]) { if (lgPatternFound == NUMSYS_AND_CHECK_DIGIT_PATTERNS[numSys][d]) {
resultString.insert(0, 1, (char) ('0' + numSys)); resultString.insert(0, 1, (char) ('0' + numSys));
resultString.append(1, (char) ('0' + d)); resultString.append(1, (char) ('0' + d));
return; return true;
} }
} }
} }
throw ReaderException("determineNumSysAndCheckDigit exception"); return false;
} }
/** /**

View file

@ -26,19 +26,19 @@
namespace zxing { namespace zxing {
namespace oned { namespace oned {
class UPCEReader : public UPCEANReader { class UPCEReader : public UPCEANReader {
private: private:
static void determineFirstDigit(std::string& resultString, int lgPatternFound); //throws ReaderException static bool determineNumSysAndCheckDigit(std::string& resultString, int lgPatternFound);
static void determineNumSysAndCheckDigit(std::string& resultString, int lgPatternFound); //throws ReaderException
protected: protected:
int* decodeEnd(Ref<BitArray> row, int endStart); //throws ReaderException int* decodeEnd(Ref<BitArray> row, int endStart);
bool checkChecksum(std::string s); //throws ReaderException bool checkChecksum(std::string s);
public: public:
UPCEReader(); 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); static std::string convertUPCEtoUPCA(std::string upce);
BarcodeFormat getBarcodeFormat(); BarcodeFormat getBarcodeFormat();
}; };
} }