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++) {
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));
rowOffset += counters[i];
}
}
-
- delete [] middleRange;
return rowOffset;
}
return -1;
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();
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,
}
}
- 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));
rowOffset += counters[i];
}
}
-
- delete [] middleRange;
return rowOffset;
}
return -1;
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();
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) {
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();
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));
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);
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++) {
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,
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();
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,
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++) {
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){
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);