Began removing the excessive use of exceptions in the 1D readers by drawing

a line in the sand: no one may throw an exception from decodeRow(). Next up
is to throw fewer exceptions internally.


git-svn-id: https://zxing.googlecode.com/svn/trunk@1527 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
dswitkin@google.com 2010-08-13 16:20:03 +00:00
parent 073a3033fc
commit 56ad5f5554
14 changed files with 585 additions and 579 deletions

View file

@ -193,6 +193,10 @@ public:
return x == 0 ? object_ != 0 : true;
}
bool empty() const {
return object_ == 0;
}
template<class Y>
friend std::ostream& operator<<(std::ostream &out, Ref<Y>& ref);
};

View file

@ -2,7 +2,6 @@
* Code128Reader.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");
@ -170,7 +169,8 @@ namespace zxing {
unsigned int bestVariance = MAX_AVG_VARIANCE;
int bestMatch = -1;
for (int startCode = CODE_START_A; startCode <= CODE_START_C; startCode++) {
unsigned int variance = patternMatchVariance(counters, sizeof(counters)/sizeof(int), CODE_PATTERNS[startCode], MAX_INDIVIDUAL_VARIANCE);
unsigned int variance = patternMatchVariance(counters, sizeof(counters) / sizeof(int),
CODE_PATTERNS[startCode], MAX_INDIVIDUAL_VARIANCE);
if (variance < bestVariance) {
bestVariance = variance;
bestMatch = startCode;
@ -178,7 +178,8 @@ namespace zxing {
}
if (bestMatch >= 0) {
// Look for whitespace before start pattern, >= 50% of width of start pattern
if (row->isRange(fmaxl(0, patternStart - (i - patternStart) / 2), patternStart, false)) {
if (row->isRange(fmaxl(0, patternStart - (i - patternStart) / 2), patternStart,
false)) {
int* resultValue = new int[3];
resultValue[0] = patternStart;
resultValue[1] = i;
@ -203,7 +204,8 @@ namespace zxing {
throw ReaderException("");
}
int Code128Reader::decodeCode(Ref<BitArray> row, int counters[], int countersCount, int rowOffset){
int Code128Reader::decodeCode(Ref<BitArray> row, int counters[], int countersCount,
int rowOffset){
recordPattern(row, rowOffset, counters, countersCount);
unsigned int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept
int bestMatch = -1;
@ -214,7 +216,8 @@ namespace zxing {
pattern[ind] = CODE_PATTERNS[d][ind];
}
// memcpy(pattern, CODE_PATTERNS[d], countersLength);
unsigned int variance = patternMatchVariance(counters, countersCount, pattern, MAX_INDIVIDUAL_VARIANCE);
unsigned int variance = patternMatchVariance(counters, countersCount, pattern,
MAX_INDIVIDUAL_VARIANCE);
if (variance < bestVariance) {
bestVariance = variance;
bestMatch = d;
@ -228,9 +231,10 @@ namespace zxing {
}
}
Ref<Result> Code128Reader::decodeRow(int rowNumber, Ref<BitArray> row){
int* startPatternInfo = findStartPattern(row);
Ref<Result> Code128Reader::decodeRow(int rowNumber, Ref<BitArray> row) {
int* startPatternInfo = NULL;
try {
startPatternInfo = findStartPattern(row);
int startCode = startPatternInfo[2];
int codeSet;
switch (startCode) {
@ -244,7 +248,6 @@ namespace zxing {
codeSet = CODE_CODE_C;
break;
default:
delete [] startPatternInfo;
throw ReaderException("");
}
@ -265,7 +268,6 @@ namespace zxing {
bool lastCharacterWasPrintable = true;
while (!done) {
bool unshift = isNextShifted;
isNextShifted = false;
@ -276,7 +278,6 @@ namespace zxing {
try {
code = decodeCode(row, counters, sizeof(counters)/sizeof(int), nextStart);
} catch (ReaderException re) {
delete [] startPatternInfo;
throw re;
}
@ -303,7 +304,6 @@ namespace zxing {
case CODE_START_A:
case CODE_START_B:
case CODE_START_C:
delete [] startPatternInfo;
throw ReaderException("");
}
@ -315,8 +315,8 @@ namespace zxing {
} else if (code < 96) {
tmpResultString.append(1, (char) (code - 64));
} else {
// Don't let CODE_STOP, which always appears, affect whether whether we think the last
// code was printable or not.
// Don't let CODE_STOP, which always appears, affect whether whether we think the
// last code was printable or not.
if (code != CODE_STOP) {
lastCharacterWasPrintable = false;
}
@ -426,7 +426,6 @@ namespace zxing {
nextStart++;
}
if (!row->isRange(nextStart, fminl(width, nextStart + (nextStart - lastStart) / 2), false)) {
delete [] startPatternInfo;
throw ReaderException("");
}
@ -434,7 +433,6 @@ namespace zxing {
checksumTotal -= multiplier * lastCode;
// lastCode is the checksum then:
if (checksumTotal % 103 != lastCode) {
delete [] startPatternInfo;
throw ReaderException("");
}
@ -454,10 +452,7 @@ namespace zxing {
}
Ref<String> resultString(new String(tmpResultString));
// String resultString(tmpResultString);
if (tmpResultString.length() == 0) {
delete [] startPatternInfo;
// Almost surely a false positive
throw ReaderException("");
}
@ -471,13 +466,14 @@ namespace zxing {
resultPoints[0] = resultPoint1;
resultPoints[1] = resultPoint2;
ArrayRef<unsigned char> resultBytes(1);
delete [] startPatternInfo;
startPatternInfo = NULL;
Ref<Result> res(new Result(resultString, resultBytes, resultPoints, BarcodeFormat_CODE_128));
return res;
ArrayRef<unsigned char> resultBytes(1);
return Ref<Result>(new Result(resultString, resultBytes, resultPoints,
BarcodeFormat_CODE_128));
} catch (ReaderException const& re) {
delete [] startPatternInfo;
return Ref<Result>();
}
}
void Code128Reader::append(char* s, char c){

View file

@ -2,7 +2,6 @@
* Code39Reader.cpp
* ZXing
*
* Created by Lukasz Warchol on 10-01-26.
* Copyright 2010 ZXing authors All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -81,7 +80,7 @@ namespace oned {
extendedMode(extendedMode_) {
}
Ref<Result> Code39Reader::decodeRow(int rowNumber, Ref<BitArray> row){
Ref<Result> Code39Reader::decodeRow(int rowNumber, Ref<BitArray> row) {
int* start = NULL;
try {
start = findAsteriskPattern(row);
@ -175,7 +174,7 @@ namespace oned {
return res;
} catch (ReaderException const& re) {
delete [] start;
throw re;
return Ref<Result>();
}
}

View file

@ -2,7 +2,6 @@
* EAN13Reader.cpp
* ZXing
*
* Created by Lukasz Warchol on 10-01-22.
* Copyright 2010 ZXing authors All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -24,23 +23,24 @@
namespace zxing {
namespace oned {
static const int FIRST_DIGIT_ENCODINGS[10] = {0x00, 0x0B, 0x0D, 0xE, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A};
static const int FIRST_DIGIT_ENCODINGS[10] = {
0x00, 0x0B, 0x0D, 0xE, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A
};
EAN13Reader::EAN13Reader() { }
int EAN13Reader::decodeMiddle(Ref<BitArray> row, int startRange[], int startRangeLen, std::string& resultString){
int EAN13Reader::decodeMiddle(Ref<BitArray> row, int startRange[], int startRangeLen,
std::string& resultString){
const int countersLen = 4;
int counters[countersLen] = { 0, 0, 0, 0 };
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);
int bestMatch = decodeDigit(row, counters, countersLen, rowOffset,
UPC_EAN_PATTERNS_L_AND_G_PATTERNS);
resultString.append(1, (char) ('0' + bestMatch % 10));
for (int i = 0; i < countersLen; i++) {
rowOffset += counters[i];
@ -54,11 +54,13 @@ namespace zxing {
int* middleRange = 0;
try {
middleRange = findGuardPattern(row, rowOffset, true, (int*)getMIDDLE_PATTERN(), getMIDDLE_PATTERN_LEN());
middleRange = findGuardPattern(row, rowOffset, true, (int*)getMIDDLE_PATTERN(),
getMIDDLE_PATTERN_LEN());
rowOffset = middleRange[1];
for (int x = 0; x < 6 && rowOffset < end; x++) {
int bestMatch = decodeDigit(row, counters, countersLen, rowOffset, UPC_EAN_PATTERNS_L_PATTERNS);
int bestMatch = decodeDigit(row, counters, countersLen, rowOffset,
UPC_EAN_PATTERNS_L_PATTERNS);
resultString.append(1, (char) ('0' + bestMatch));
for (int i = 0; i < countersLen; i++) {
rowOffset += counters[i];
@ -73,7 +75,7 @@ namespace zxing {
}
}
void EAN13Reader::determineFirstDigit(std::string& resultString, int lgPatternFound){
void 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));

View file

@ -2,7 +2,6 @@
* EAN8Reader.cpp
* ZXing
*
* Created by Lukasz Warchol on 10-01-25.
* Copyright 2010 ZXing authors All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -26,7 +25,8 @@ namespace zxing {
EAN8Reader::EAN8Reader(){ }
int EAN8Reader::decodeMiddle(Ref<BitArray> row, int startRange[], int startRangeLen, std::string& resultString){
int EAN8Reader::decodeMiddle(Ref<BitArray> row, int startRange[], int startRangeLen,
std::string& resultString){
const int countersLen = 4;
int counters[countersLen] = { 0, 0, 0, 0 };
@ -34,7 +34,8 @@ namespace zxing {
int rowOffset = startRange[1];
for (int x = 0; x < 4 && rowOffset < end; x++) {
int bestMatch = decodeDigit(row, counters, countersLen, rowOffset, UPC_EAN_PATTERNS_L_PATTERNS);
int bestMatch = decodeDigit(row, counters, countersLen, rowOffset,
UPC_EAN_PATTERNS_L_PATTERNS);
resultString.append(1, (char) ('0' + bestMatch));
for (int i = 0; i < countersLen; i++) {
rowOffset += counters[i];
@ -43,11 +44,13 @@ namespace zxing {
int* middleRange = 0;
try {
middleRange = findGuardPattern(row, rowOffset, true, (int*)getMIDDLE_PATTERN(), getMIDDLE_PATTERN_LEN());
middleRange = findGuardPattern(row, rowOffset, true, (int*)getMIDDLE_PATTERN(),
getMIDDLE_PATTERN_LEN());
rowOffset = middleRange[1];
for (int x = 0; x < 4 && rowOffset < end; x++) {
int bestMatch = decodeDigit(row, counters, countersLen, rowOffset, UPC_EAN_PATTERNS_L_PATTERNS);
int bestMatch = decodeDigit(row, counters, countersLen, rowOffset,
UPC_EAN_PATTERNS_L_PATTERNS);
resultString.append(1, (char) ('0' + bestMatch));
for (int i = 0; i < countersLen; i++) {
rowOffset += counters[i];

View file

@ -2,7 +2,6 @@
* ITFReader.cpp
* ZXing
*
* Created by Lukasz Warchol on 10-01-26.
* Copyright 2010 ZXing authors All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -66,7 +65,7 @@ namespace zxing {
}
Ref<Result> ITFReader::decodeRow(int rowNumber, Ref<BitArray> row){
Ref<Result> ITFReader::decodeRow(int rowNumber, Ref<BitArray> row) {
int* startRange = 0;
int* endRange = 0;
try {
@ -96,16 +95,14 @@ namespace zxing {
resultPoints[0] = resultPoint1;
resultPoints[1] = resultPoint2;
ArrayRef<unsigned char> resultBytes(1);
Ref<Result> res(new Result(resultString, resultBytes, resultPoints, BarcodeFormat_ITF));
delete [] startRange;
delete [] endRange;
return res;
ArrayRef<unsigned char> resultBytes(1);
return Ref<Result>(new Result(resultString, resultBytes, resultPoints, BarcodeFormat_ITF));
} catch (ReaderException re) {
delete [] startRange;
delete [] endRange;
throw re;
return Ref<Result>();
}
}
@ -115,7 +112,8 @@ namespace zxing {
* @param resultString {@link StringBuffer} to append decoded chars to
* @throws ReaderException if decoding could not complete successfully
*/
void ITFReader::decodeMiddle(Ref<BitArray> row, int payloadStart, int payloadEnd, std::string& resultString){
void ITFReader::decodeMiddle(Ref<BitArray> row, int payloadStart, int payloadEnd,
std::string& resultString) {
// Digits are interleaved in pairs - 5 black lines for one digit, and the
// 5
// interleaved white lines for the second digit.
@ -163,9 +161,8 @@ namespace zxing {
* 'start block'
* @throws ReaderException
*/
int* ITFReader::decodeStart(Ref<BitArray> row){
int* ITFReader::decodeStart(Ref<BitArray> row) {
int endStart = skipWhiteSpace(row);
/// static int* findGuardPattern(Ref<BitArray> row, int rowOffset, bool whiteFirst, const int pattern[], int patternLen);
int* startPattern = 0;
try {
startPattern = findGuardPattern(row, endStart, START_PATTERN, START_PATTERN_LEN);
@ -174,9 +171,7 @@ namespace zxing {
// getting the width of the start pattern and dividing by 4 because its
// made up of 4 narrow lines.
narrowLineWidth = (startPattern[1] - startPattern[0]) >> 2;
validateQuietZone(row, startPattern[0]);
return startPattern;
} catch (ReaderException re) {
delete [] startPattern;
@ -193,7 +188,7 @@ namespace zxing {
* @throws ReaderException
*/
int* ITFReader::decodeEnd(Ref<BitArray> row){
int* ITFReader::decodeEnd(Ref<BitArray> row) {
// For convenience, reverse the row and then
// search from 'the start' for the end block
row->reverse();
@ -238,7 +233,7 @@ namespace zxing {
* @param startPattern index into row of the start or end pattern.
* @throws ReaderException if the quiet zone cannot be found, a ReaderException is thrown.
*/
void ITFReader::validateQuietZone(Ref<BitArray> row, int startPattern){
void ITFReader::validateQuietZone(Ref<BitArray> row, int startPattern) {
//#pragma mark needs some corrections
// int quietCount = narrowLineWidth * 10; // expect to find this many pixels of quiet zone
//
@ -261,7 +256,7 @@ namespace zxing {
* @return index of the first black line.
* @throws ReaderException Throws exception if no black lines are found in the row
*/
int ITFReader::skipWhiteSpace(Ref<BitArray> row){
int ITFReader::skipWhiteSpace(Ref<BitArray> row) {
int width = row->getSize();
int endStart = 0;
while (endStart < width) {
@ -285,8 +280,8 @@ namespace zxing {
* ints
* @throws ReaderException if pattern is not found
*/
int* ITFReader::findGuardPattern(Ref<BitArray> row, int rowOffset, const int pattern[], int patternLen){
int* ITFReader::findGuardPattern(Ref<BitArray> row, int rowOffset, const int pattern[],
int patternLen) {
// TODO: This is very similar to implementation in UPCEANReader. Consider if they can be
// merged to a single method.
int patternLength = patternLen;
@ -305,7 +300,8 @@ namespace zxing {
counters[counterPosition]++;
} else {
if (counterPosition == patternLength - 1) {
if (patternMatchVariance(counters, patternLength, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) {
if (patternMatchVariance(counters, patternLength, pattern,
MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) {
int* resultValue = new int[2];
resultValue[0] = patternStart;
resultValue[1] = x;
@ -345,7 +341,8 @@ namespace zxing {
for(int ind = 0; ind<countersLen; ind++){
pattern[ind] = PATTERNS[i][ind];
}
unsigned int variance = patternMatchVariance(counters, countersLen, pattern, MAX_INDIVIDUAL_VARIANCE);
unsigned int variance = patternMatchVariance(counters, countersLen, pattern,
MAX_INDIVIDUAL_VARIANCE);
if (variance < bestVariance) {
bestVariance = variance;
bestMatch = i;
@ -358,7 +355,6 @@ namespace zxing {
}
}
ITFReader::~ITFReader(){
}
}

View file

@ -2,7 +2,6 @@
* MultiFormatOneDReader.cpp
* ZXing
*
* Created by Lukasz Warchol on 10-01-25.
* Copyright 2010 ZXing authors All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -52,17 +51,16 @@ namespace zxing {
}
}
Ref<Result> MultiFormatOneDReader::decodeRow(int rowNumber, Ref<BitArray> row){
Ref<Result> MultiFormatOneDReader::decodeRow(int rowNumber, Ref<BitArray> row) {
int size = readers.size();
for (int i = 0; i < size; i++) {
OneDReader* reader = readers[i];
try {
return reader->decodeRow(rowNumber, row);
} catch (ReaderException re) {
// continue
Ref<Result> result = reader->decodeRow(rowNumber, row);
if (!result.empty()) {
return result;
}
}
throw ReaderException("No code detected");
return Ref<Result>();
}
}
}

View file

@ -2,7 +2,6 @@
* MultiFormatUPCEANReader.cpp
* ZXing
*
* Created by Lukasz Warchol on 10-01-25.
* Copyright 2010 ZXing authors All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -51,17 +50,16 @@ namespace zxing {
}
}
Ref<Result> MultiFormatUPCEANReader::decodeRow(int rowNumber, Ref<BitArray> row){
Ref<Result> MultiFormatUPCEANReader::decodeRow(int rowNumber, Ref<BitArray> row) {
// Compute this location once and reuse it on multiple implementations
int size = readers.size();
for (int i = 0; i < size; i++) {
Ref<OneDReader> reader = readers[i];
Ref<Result> result;
try {
result = reader->decodeRow(rowNumber, row);//decodeRow(rowNumber, row, startGuardPattern);
} catch (ReaderException re) {
Ref<Result> result = reader->decodeRow(rowNumber, row);
if (result.empty()) {
continue;
}
// Special case: a 12-digit code encoded in UPC-A is identical to a "0"
// followed by those 12 digits encoded as EAN-13. Each will recognize such a code,
// UPC-A as a 12-digit string and EAN-13 as a 13-digit string starting with "0".
@ -76,13 +74,14 @@ namespace zxing {
const std::string& text = (result->getText())->getText();
if (text[0] == '0') {
Ref<String> resultString(new String(text.substr(1)));
Ref<Result> res(new Result(resultString, result->getRawBytes(), result->getResultPoints(), BarcodeFormat_UPC_A));
Ref<Result> res(new Result(resultString, result->getRawBytes(),
result->getResultPoints(), BarcodeFormat_UPC_A));
return res;
}
}
return result;
}
throw ReaderException("No EAN code detected");
return Ref<Result>();
}
}
}

View 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");
@ -32,12 +31,10 @@ namespace zxing {
}
Ref<Result> OneDReader::decode(Ref<BinaryBitmap> image, DecodeHints hints) {
try {
return doDecode(image, hints);
}catch (ReaderException re) {
} catch (ReaderException re) {
if (hints.getTryHarder() && image->isRotateSupported()) {
Ref<BinaryBitmap> rotatedImage(image->rotateCounterClockwise());
Ref<Result> result(doDecode(rotatedImage, hints));
/*
@ -64,7 +61,7 @@ namespace zxing {
}
}
Ref<Result> OneDReader::doDecode(Ref<BinaryBitmap> image, DecodeHints hints){
Ref<Result> OneDReader::doDecode(Ref<BinaryBitmap> image, DecodeHints hints) {
int width = image->getWidth();
int height = image->getHeight();
Ref<BitArray> row(new BitArray(width));
@ -79,7 +76,6 @@ namespace zxing {
}
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?
@ -92,9 +88,9 @@ namespace zxing {
// 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) {
} catch (IllegalArgumentException re) {
continue;
}
@ -104,11 +100,11 @@ namespace zxing {
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) {
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.
@ -124,10 +120,7 @@ namespace zxing {
result.reset(new Result(result->getText(),result->getRawBytes(),points,result->getBarcodeFormat()));
}
}
return result;
} catch (ReaderException re) {
// continue -- just couldn't decode this row
}
}
}

View file

@ -34,9 +34,13 @@ namespace zxing {
OneDReader();
virtual Ref<Result> decode(Ref<BinaryBitmap> image, DecodeHints hints);
// Implementations must not throw any exceptions. If a barcode is not found on this row,
// a empty ref should be returned e.g. return Ref<Result>();
virtual Ref<Result> decodeRow(int rowNumber, Ref<BitArray> row) = 0;
static unsigned int patternMatchVariance(int counters[], int countersSize, const int pattern[], int maxIndividualVariance);
static unsigned int patternMatchVariance(int counters[], int countersSize,
const int pattern[], int maxIndividualVariance);
static void recordPattern(Ref<BitArray> row, int start, int counters[], int countersCount);
virtual ~OneDReader();
};

View file

@ -2,7 +2,6 @@
* OneDResultPoint.cpp
* ZXing
*
* Created by Lukasz Warchol on 10-01-20.
* Copyright 2010 ZXing authors All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -23,7 +22,7 @@
namespace zxing {
namespace oned {
OneDResultPoint::OneDResultPoint(float posX, float posY) : posX_(posX), posY_(posY){
OneDResultPoint::OneDResultPoint(float posX, float posY) : posX_(posX), posY_(posY) {
}
float OneDResultPoint::getX() const {

View file

@ -2,7 +2,6 @@
* UPCAReader.cpp
* ZXing
*
* Created by Lukasz Warchol on 10-01-25.
* Copyright 2010 ZXing authors All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -26,32 +25,37 @@ namespace zxing {
UPCAReader::UPCAReader() : ean13Reader() {
}
Ref<Result> UPCAReader::decodeRow(int rowNumber, Ref<BitArray> row){
Ref<Result> UPCAReader::decodeRow(int rowNumber, Ref<BitArray> row) {
return maybeReturnResult(ean13Reader.decodeRow(rowNumber, row));
}
Ref<Result> UPCAReader::decodeRow(int rowNumber, Ref<BitArray> row, int startGuardRange[]){
Ref<Result> UPCAReader::decodeRow(int rowNumber, Ref<BitArray> row, int startGuardRange[]) {
return maybeReturnResult(ean13Reader.decodeRow(rowNumber, row, startGuardRange));
}
Ref<Result> UPCAReader::decode(Ref<BinaryBitmap> image, DecodeHints hints){
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, std::string& resultString){
int UPCAReader::decodeMiddle(Ref<BitArray> row, int startRange[], int startRangeLen,
std::string& resultString) {
return ean13Reader.decodeMiddle(row, startRange, startRangeLen, resultString);
}
Ref<Result> UPCAReader::maybeReturnResult(Ref<Result> result){
Ref<Result> UPCAReader::maybeReturnResult(Ref<Result> result) {
if (result.empty()) {
return result;
}
const std::string& text = (result->getText())->getText();
if (text[0] == '0') {
Ref<String> resultString(new String(text.substr(1)));
Ref<Result> res(new Result(resultString, result->getRawBytes(), result->getResultPoints(), BarcodeFormat_UPC_A));
Ref<Result> res(new Result(resultString, result->getRawBytes(), result->getResultPoints(),
BarcodeFormat_UPC_A));
return res;
} else {
throw ReaderException("Not UPC-A barcode.");
}
return Ref<Result>();
}
BarcodeFormat UPCAReader::getBarcodeFormat(){
return BarcodeFormat_UPC_A;
}

View file

@ -2,7 +2,6 @@
* UPCEANReader.cpp
* ZXing
*
* Created by Lukasz Warchol on 10-01-21.
* Copyright 2010 ZXing authors All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -21,6 +20,7 @@
#include "UPCEANReader.h"
#include <zxing/oned/OneDResultPoint.h>
#include <zxing/ReaderException.h>
namespace zxing {
namespace oned {
@ -82,14 +82,15 @@ namespace zxing {
};
const int UPCEANReader::getMIDDLE_PATTERN_LEN(){
const int UPCEANReader::getMIDDLE_PATTERN_LEN() {
return MIDDLE_PATTERN_LEN;
}
const int* UPCEANReader::getMIDDLE_PATTERN(){
const int* UPCEANReader::getMIDDLE_PATTERN() {
return MIDDLE_PATTERN;
}
UPCEANReader::UPCEANReader(){
UPCEANReader::UPCEANReader() {
}
@ -102,22 +103,21 @@ namespace zxing {
return result;
} catch (ReaderException const& re) {
delete [] start;
throw re;
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;
try {
std::string tmpResultString;
std::string& tmpResultStringRef = tmpResultString;
int endStart;
endStart = decodeMiddle(row, startGuardRange, 2 /*reference findGuardPattern*/ , tmpResultStringRef);
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.
// 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)) {
@ -148,19 +148,18 @@ namespace zxing {
delete [] endRange;
throw re;
}
}
int* UPCEANReader::findStartGuardPattern(Ref<BitArray> row){
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));
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.
@ -179,7 +178,8 @@ namespace zxing {
}
// 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){
int* UPCEANReader::findGuardPattern(Ref<BitArray> row, int rowOffset, bool whiteFirst,
const int pattern[], int patternLen) {
int patternLength = patternLen;
int counters[patternLength];
int countersCount = sizeof(counters) / sizeof(int);
@ -204,7 +204,8 @@ namespace zxing {
counters[counterPosition]++;
} else {
if (counterPosition == patternLength - 1) {
if (patternMatchVariance(counters, countersCount, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) {
if (patternMatchVariance(counters, countersCount, pattern,
MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) {
int* resultValue = new int[2];
resultValue[0] = patternStart;
resultValue[1] = x;
@ -227,12 +228,14 @@ namespace zxing {
throw ReaderException("findGuardPattern");
}
int* UPCEANReader::decodeEnd(Ref<BitArray> row, int endStart){
return findGuardPattern(row, endStart, false, START_END_PATTERN, sizeof(START_END_PATTERN)/sizeof(int));
int* UPCEANReader::decodeEnd(Ref<BitArray> row, int endStart) {
return findGuardPattern(row, endStart, false, START_END_PATTERN,
sizeof(START_END_PATTERN) / sizeof(int));
}
// int UPCEANReader::decodeDigit(Ref<BitArray> row, int counters[], int countersLen, int rowOffset, int** patterns/*[][]*/, int paterns1Len, int paterns2Len)
int UPCEANReader::decodeDigit(Ref<BitArray> row, int counters[], int countersLen, int rowOffset, UPC_EAN_PATTERNS patternType){
int UPCEANReader::decodeDigit(Ref<BitArray> row, int counters[], int countersLen, int rowOffset,
UPC_EAN_PATTERNS patternType) {
recordPattern(row, rowOffset, counters, countersLen);
unsigned int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept
int bestMatch = -1;
@ -247,7 +250,8 @@ namespace zxing {
pattern[j] = L_PATTERNS[i][j];
}
unsigned int variance = patternMatchVariance(counters, countersLen, pattern, MAX_INDIVIDUAL_VARIANCE);
unsigned int variance = patternMatchVariance(counters, countersLen, pattern,
MAX_INDIVIDUAL_VARIANCE);
if (variance < bestVariance) {
bestVariance = variance;
bestMatch = i;
@ -262,7 +266,8 @@ namespace zxing {
pattern[j] = L_AND_G_PATTERNS[i][j];
}
unsigned int variance = patternMatchVariance(counters, countersLen, pattern, MAX_INDIVIDUAL_VARIANCE);
unsigned int variance = patternMatchVariance(counters, countersLen, pattern,
MAX_INDIVIDUAL_VARIANCE);
if (variance < bestVariance) {
bestVariance = variance;
bestMatch = i;
@ -283,7 +288,7 @@ namespace zxing {
/**
* @return {@link #checkStandardUPCEANChecksum(String)}
*/
bool UPCEANReader::checkChecksum(std::string s){
bool UPCEANReader::checkChecksum(std::string s) {
return checkStandardUPCEANChecksum(s);
}
@ -295,7 +300,7 @@ namespace zxing {
* @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();
if (length == 0) {
return false;
@ -319,7 +324,8 @@ namespace zxing {
}
return sum % 10 == 0;
}
UPCEANReader::~UPCEANReader(){
UPCEANReader::~UPCEANReader() {
}
}
}

View file

@ -2,7 +2,6 @@
* UPCEReader.cpp
* ZXing
*
* Created by Lukasz Warchol on 10-01-26.
* Copyright 2010 ZXing authors All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -40,9 +39,11 @@ namespace zxing {
{0x07, 0x0B, 0x0D, 0x0E, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A}
};
UPCEReader::UPCEReader(){}
UPCEReader::UPCEReader() {
}
int UPCEReader::decodeMiddle(Ref<BitArray> row, int startRange[], int startRangeLen, std::string& resultString){
int UPCEReader::decodeMiddle(Ref<BitArray> row, int startRange[], int startRangeLen,
std::string& resultString) {
const int countersLen = 4;
int counters[countersLen] = { 0, 0, 0, 0 };
@ -52,7 +53,8 @@ namespace zxing {
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);
int bestMatch = decodeDigit(row, counters, countersLen, rowOffset,
UPC_EAN_PATTERNS_L_AND_G_PATTERNS);
resultString.append(1, (char) ('0' + bestMatch % 10));
for (int i = 0; i < countersLen; i++) {
rowOffset += counters[i];
@ -67,8 +69,9 @@ namespace zxing {
return rowOffset;
}
int* UPCEReader::decodeEnd(Ref<BitArray> row, int endStart){
return findGuardPattern(row, endStart, true, MIDDLE_END_PATTERN, sizeof(MIDDLE_END_PATTERN)/sizeof(int));
int* UPCEReader::decodeEnd(Ref<BitArray> row, int endStart) {
return findGuardPattern(row, endStart, true, MIDDLE_END_PATTERN,
sizeof(MIDDLE_END_PATTERN) / sizeof(int));
}
bool UPCEReader::checkChecksum(std::string s){
@ -76,7 +79,7 @@ namespace zxing {
}
void UPCEReader::determineNumSysAndCheckDigit(std::string& resultString, int lgPatternFound){
void 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]) {
@ -129,7 +132,7 @@ namespace zxing {
}
BarcodeFormat UPCEReader::getBarcodeFormat(){
BarcodeFormat UPCEReader::getBarcodeFormat() {
return BarcodeFormat_UPC_E;
}
}