CFX_Int32Array* CBC_Detector::findGuardPattern(CBC_CommonBitMatrix* matrix, int32_t column, int32_t row, int32_t width, FX_BOOL whiteFirst, int32_t* pattern, int32_t patternLength, CFX_Int32Array& counters) { for (int32_t i = 0; i < counters.GetSize(); i++) { counters.SetAt(i, 0); } FX_BOOL isWhite = whiteFirst; int32_t patternStart = column; int32_t pixelDrift = 0; CFX_Int32Array* intarray = new CFX_Int32Array; while (matrix->Get(patternStart, row) && patternStart > 0 && pixelDrift++ < MAX_PIXEL_DRIFT) { patternStart--; } int32_t x = patternStart; int32_t counterPosition = 0; for (; x < width; x++) { FX_BOOL pixel = matrix->Get(x, row); if (pixel ^ isWhite) { counters[counterPosition]++; } else { if (counterPosition == patternLength - 1) { if (patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) { intarray->Add(patternStart); intarray->Add(x); return intarray; } patternStart += counters[0] + counters[1]; for (int32_t l = 2, k = 0; l < patternLength; l++, k++) { counters.SetAt(k, counters.GetAt(l)); } counters.SetAt(patternLength - 2, 0); counters.SetAt(patternLength - 1, 0); counterPosition--; } else { counterPosition++; } counters[counterPosition] = 1; isWhite = !isWhite; } } if (counterPosition == patternLength - 1) { if (patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) { intarray->Add(patternStart); intarray->Add(x - 1); return intarray; } } delete intarray; return NULL; }
int Code128Reader::decodeCode(Ref<BitArray> row, int counters[], int countersCount, int rowOffset) { if (!recordPattern(row, rowOffset, counters, countersCount)) { throw ReaderException(""); } unsigned int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept int bestMatch = -1; for (int d = 0; d < CODE_PATTERNS_LENGTH; d++) { int pattern[countersLength]; for(int ind = 0; ind< countersLength; ind++){ pattern[ind] = CODE_PATTERNS[d][ind]; } // memcpy(pattern, CODE_PATTERNS[d], countersLength); unsigned int variance = patternMatchVariance(counters, countersCount, pattern, MAX_INDIVIDUAL_VARIANCE); if (variance < bestVariance) { bestVariance = variance; bestMatch = d; } } // TODO We're overlooking the fact that the STOP pattern has 7 values, not 6. if (bestMatch >= 0) { return bestMatch; } else { throw ReaderException(""); } }
int* Code128Reader::findStartPattern(Ref<BitArray> row){ int width = row->getSize(); int rowOffset = 0; while (rowOffset < width) { if (row->get(rowOffset)) { break; } rowOffset++; } int counterPosition = 0; int counters[countersLength] = {0,0,0,0,0,0}; int patternStart = rowOffset; bool isWhite = false; int patternLength = sizeof(counters) / sizeof(int); for (int i = rowOffset; i < width; i++) { bool pixel = row->get(i); if (pixel ^ isWhite) { counters[counterPosition]++; } else { if (counterPosition == patternLength - 1) { 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); if (variance < bestVariance) { bestVariance = variance; bestMatch = startCode; } } 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)) { int* resultValue = new int[3]; resultValue[0] = patternStart; resultValue[1] = i; resultValue[2] = bestMatch; return resultValue; } } patternStart += counters[0] + counters[1]; for (int y = 2; y < patternLength; y++) { counters[y - 2] = counters[y]; } counters[patternLength - 2] = 0; counters[patternLength - 1] = 0; counterPosition--; } else { counterPosition++; } counters[counterPosition] = 1; isWhite = !isWhite; } } throw ReaderException(""); }
// 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){ recordPattern(row, rowOffset, counters, countersLen); unsigned int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept int bestMatch = -1; int max = 0; switch (patternType) { case UPC_EAN_PATTERNS_L_PATTERNS: max = L_PATTERNS_LEN; for (int i = 0; i < max; i++) { int pattern[countersLen]; for(int j = 0; j< countersLen; j++){ pattern[j] = L_PATTERNS[i][j]; } unsigned int variance = patternMatchVariance(counters, countersLen, pattern, MAX_INDIVIDUAL_VARIANCE); if (variance < bestVariance) { bestVariance = variance; bestMatch = i; } } break; case UPC_EAN_PATTERNS_L_AND_G_PATTERNS: max = L_AND_G_PATTERNS_LEN; for (int i = 0; i < max; i++) { int pattern[countersLen]; for(int j = 0; j< countersLen; j++){ pattern[j] = L_AND_G_PATTERNS[i][j]; } unsigned int variance = patternMatchVariance(counters, countersLen, pattern, MAX_INDIVIDUAL_VARIANCE); if (variance < bestVariance) { bestVariance = variance; bestMatch = i; } } break; default: break; } if (bestMatch >= 0) { return bestMatch; } else { throw ReaderException("UPCEANReader::decodeDigit: No best mach"); } }
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); for (int i=0; i<countersCount ; i++) { counters[i]=0; } int width = row->getSize(); bool isWhite = false; while (rowOffset < width) { isWhite = !row->get(rowOffset); if (whiteFirst == isWhite) { break; } rowOffset++; } int counterPosition = 0; int patternStart = rowOffset; for (int x = rowOffset; x < width; x++) { bool pixel = row->get(x); if (pixel ^ isWhite) { counters[counterPosition]++; } else { 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; } patternStart += counters[0] + counters[1]; for (int y = 2; y < patternLength; y++) { counters[y - 2] = counters[y]; } counters[patternLength - 2] = 0; counters[patternLength - 1] = 0; counterPosition--; } else { counterPosition++; } counters[counterPosition] = 1; isWhite = !isWhite; } } throw ReaderException("findGuardPattern"); }
/** * @param row row of black/white values to search * @param rowOffset position to start search * @param pattern pattern of counts of number of black and white pixels that are * being searched for as a pattern * @return start/end horizontal offset of guard pattern, as an array of two * ints * @throws ReaderException if pattern is not found */ 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; int counters[patternLength]; for (int i=0; i<patternLength; i++) { counters[i] = 0; } int width = (int)row->getSize(); bool isWhite = false; int counterPosition = 0; int patternStart = rowOffset; for (int x = rowOffset; x < width; x++) { bool pixel = row->get(x); if (pixel ^ isWhite) { counters[counterPosition]++; } else { if (counterPosition == patternLength - 1) { if (patternMatchVariance(counters, patternLength, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) { int* resultValue = new int[2]; resultValue[0] = patternStart; resultValue[1] = x; return resultValue; } patternStart += counters[0] + counters[1]; for (int y = 2; y < patternLength; y++) { counters[y - 2] = counters[y]; } counters[patternLength - 2] = 0; counters[patternLength - 1] = 0; counterPosition--; } else { counterPosition++; } counters[counterPosition] = 1; isWhite = !isWhite; } } throw ReaderException(""); }
/** * Attempts to decode a sequence of ITF black/white lines into single * digit. * * @param counters the counts of runs of observed black/white/black/... values * @return The decoded digit * @throws ReaderException if digit cannot be decoded */ int ITFReader::decodeDigit(int counters[], int countersLen){ unsigned int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept int bestMatch = -1; int max = PATTERNS_LEN; for (int i = 0; i < max; i++) { int pattern[countersLen]; for(int ind = 0; ind<countersLen; ind++){ pattern[ind] = PATTERNS[i][ind]; } unsigned int variance = patternMatchVariance(counters, countersLen, pattern, MAX_INDIVIDUAL_VARIANCE); if (variance < bestVariance) { bestVariance = variance; bestMatch = i; } } if (bestMatch >= 0) { return bestMatch; } else { throw ReaderException("digit didint found"); } }