Removed dynamic allocation of new int[2] when searching for

guard patterns to improve performance.


git-svn-id: https://zxing.googlecode.com/svn/trunk@1563 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
dswitkin@google.com 2010-08-25 20:51:14 +00:00
parent 886b70e167
commit 0f431db54d
10 changed files with 72 additions and 85 deletions

View 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;

View 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();

View 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;

View 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();

View 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) {

View 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();

View 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,

View 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,

View 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){

View 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);