mirror of
https://github.com/zxing/zxing.git
synced 2025-03-05 20:48:51 -08:00
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:
parent
886b70e167
commit
0f431db54d
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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){
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue