📄 bars2symupcx2.cpp
字号:
TInt32 bestConv = -9999999, nextBestConv = -9999999;
int d;
// estimate first two digits
for (d=0; d<10; d++) {
int d1;
for (d1=0; d1<10; d1++) {
int j;
TInt32 conv = 0;
for (j=0; j<LeftWidth+DigitWidth*2; j++) {
int k;
for (k=0; k<pixelsPerBar; k++) {
conv += index[row][pos + j*pixelsPerBar + k] * iLeftConv[d][d1][j];
}
}
if (conv > bestConv) {
nextBestConv = bestConv;
bestConv = conv;
bestDigit = d;
bestDigit1 = d1;
} else {
nextBestConv = Max(nextBestConv,conv);
}
}
}
code[0] = (TUint8) bestDigit;
CountDigits[0][bestDigit]++;
code[1] = (TUint8) bestDigit1;
CountDigits[1][bestDigit]++;
totalConv += bestConv;
TInt lastDigit = bestDigit1;
for (i=2; i<Digits; i++) {
pos = nOffset + (LeftWidth + (i-1) * DigitWidth) * pixelsPerBar; // position of start of next digit
int bestDigit = -1;
TInt32 bestConv = -9999999, nextBestConv = -9999999;
int d;
for (d=0; d<10; d++) {
TInt32 conv = 0;
int j;
for (j=0; j<DigitWidth*2; j++) {
int k;
for (k=0; k<pixelsPerBar; k++) {
conv += index[row][pos + j*pixelsPerBar + k] * iPairConv[lastDigit][d][j];
}
}
if (conv > bestConv) {
nextBestConv = bestConv;
bestConv = conv;
bestDigit = d;
} else {
nextBestConv = Max(nextBestConv,conv);
}
}
code[i] = (TUint8) bestDigit;
CountDigits[i][bestDigit]++;
totalConv += bestConv;
lastDigit = bestDigit;
}
// estimate first two digits of right side of pattern
pos = nOffset + MidOffset * pixelsPerBar; // position of start of right side
bestConv = -9999999;
nextBestConv = -9999999;
for (d=0; d<10; d++) {
int d1;
for (d1=0; d1<10; d1++) {
TInt32 conv = 0;
int j;
for (j=0; j<MidWidth+DigitWidth*2; j++) {
int k;
// note sign change in convolution sum below -- right side of pattern
// reverses black and white compared to left side
for (k=0; k<pixelsPerBar; k++) {
conv -= index[row][pos + j*pixelsPerBar + k] * iMidConv[d][d1][j];
}
}
if (conv > bestConv) {
nextBestConv = bestConv;
bestConv = conv;
bestDigit = d;
bestDigit1 = d1;
} else {
nextBestConv = Max(nextBestConv,conv);
}
}
}
code[Digits] = (TUint8) bestDigit;
CountDigits[Digits][bestDigit]++;
code[Digits+1] = (TUint8) bestDigit1;
CountDigits[Digits+1][bestDigit1]++;
totalConv += bestConv;
lastDigit = bestDigit1;
for (i=2; i<Digits; i++) {
pos = nOffset + (MidOffset + MidWidth + (i-1) * DigitWidth) * pixelsPerBar; // position of start of next digit
int bestDigit = -1;
TInt32 bestConv = -9999999, nextBestConv = -9999999;
int d;
for (d=0; d<10; d++) {
TInt32 conv = 0;
int j;
for (j=0; j<DigitWidth*2; j++) {
int k;
for (k=0; k<pixelsPerBar; k++) {
conv -= index[row][pos + j*pixelsPerBar + k] * iPairConv[lastDigit][d][j];
}
}
if (conv > bestConv) {
nextBestConv = bestConv;
bestConv = conv;
bestDigit = d;
} else {
nextBestConv = Max(nextBestConv,conv);
}
}
code[Digits+i] = (TUint8) bestDigit;
CountDigits[Digits+i][bestDigit]++;
totalConv += bestConv;
lastDigit = bestDigit;
}
CleanupStack::PopAndDestroy(); // unlock images
/* if (VerifyCheckDigit(code)) */ {
if (iHash->Find(&code[0], Digits*2)) {
((CodeValue*)(iHash->Value()))->Add(totalConv);
} else {
TBuf8<Digits*2>* pCode = new TBuf8<Digits*2>(code);
iCodes->AppendL(pCode); // so it gets deleted later
iHash->AddL(&(*pCode)[0], Digits*2, new CodeValue(totalConv));
}
}
}
// now run through the hash table and find the most common
// and second-most common reading of this barcode
int countMostCommon = -1, countNextMost = -1;
TBuf8<Digits*2> codeMostCommon;
int convMostCommon = -1;
if (iHash->First()) {
do {
int count = ((CodeValue*)iHash->Value())->Count();
if (count > countMostCommon) {
countNextMost = countMostCommon;
codeMostCommon.Copy(iHash->Key(), Digits*2);
countMostCommon = count;
convMostCommon = ((CodeValue*)iHash->Value())->Conv();
} else if (count > countNextMost) {
countNextMost = count;
}
} while (iHash->Next());
ClearHash();
int certainty = 0;
for (i=0; i<Digits*2; i++) {
int j;
int most = -1, nextMost = -1;
for (j=0; j<10; j++) {
if (CountDigits[i][j] > most) {
nextMost = most;
most = CountDigits[i][j];
} else {
nextMost = Max(nextMost, CountDigits[i][j]);
}
}
if (most > nextMost*10) {
certainty++;
}
}
if (/* countMostCommon > countNextMost*3/2 &&
countMostCommon > size.Height()/4 && */
/* certainty > 9 && */
VerifyCheckDigit(codeMostCommon)) {
pCode = TurnDigitsToText(codeMostCommon);
return true;
}
} else {
ClearHash();
}
return false;
}
// find the position of the left edge of the bar code at row
// nRow
int CBars2SymUpc::EstimateLeftEdge(CImage image, TInt nRow)
{
TInt nCol;
IImageSize size(image);
TInt nExp = size.Width() / TotalWidth; // number of pixels per bar
// shift the barcode across the image
TInt bestConv = -9999999;
TInt bestPos = -1;
image.LockLC();
IGrayIndex in(image);
for (nCol = 1; nCol < size.Width() - (TotalWidth + 1) * nExp; nCol++) {
TInt j;
TInt conv = 0;
for (j=0; j<nExp; j++) {
TInt nOffset = j + nCol;
// left pattern is 1, 0, 1, surrounded by 0 0
conv += in[nRow][nOffset - nExp] // 0
-in[nRow][nOffset] // 1
+in[nRow][nOffset + nExp] // 0
-in[nRow][nOffset + 2*nExp] // 1
+in[nRow][nOffset + 3*nExp] // 0
// mid pattern in 0 1 0 1 0 surrounded by 1 1
-in[nRow][nOffset + (MidOffset - 1) * nExp] // 1
+in[nRow][nOffset + (MidOffset) * nExp] // 0
-in[nRow][nOffset + (MidOffset + 1) * nExp] // 1
+in[nRow][nOffset + (MidOffset + 2) * nExp] // 0
-in[nRow][nOffset + (MidOffset + 3) * nExp] // 1
+in[nRow][nOffset + (MidOffset + 4) * nExp] // 0
-in[nRow][nOffset + (MidOffset + 5) * nExp] // 1
// right pattern is 1, 0, 1, surrounded by 0 0
+in[nRow][nOffset + (RightOffset - 1) * nExp] // 0
-in[nRow][nOffset + (RightOffset) * nExp] // 1
+in[nRow][nOffset + (RightOffset + 1) * nExp] // 0
-in[nRow][nOffset + (RightOffset + 2) * nExp] // 1
+in[nRow][nOffset + (RightOffset + 3) * nExp]; // 0
}
if (conv > bestConv) {
bestConv = conv;
bestPos = nCol;
}
}
CleanupStack::PopAndDestroy(); // unlock image
return bestPos;
}
void CBars2SymUpc::NormalizePattern(
TReal* pfCoeff,
TInt nLength,
TInt16 *pnCoeff,
bool bNormZero,
bool bConvInt)
{
// first normalize so sum = 0 if required
TInt i;
TReal sum;
if (bNormZero) {
sum = 0.0;
for (i=0; i<nLength; i++) {
sum += pfCoeff[i];
}
sum /= nLength;
for (i=0; i<nLength; i++) {
pfCoeff[i] -= sum;
}
}
// now normalize so sum of absolute values is 1
sum = 0.0;
for (i=0; i<nLength; i++) {
sum += Abs(pfCoeff[i]);
}
for (i=0; i<nLength; i++) {
pfCoeff[i] /= sum;
}
// finally scale and convert to int if required
if (bConvInt) {
for (i=0; i<nLength; i++) {
Math::Int(pnCoeff[i], pfCoeff[i] * 256.0);
}
}
}
int CBars2SymUpc::BarcodeWidth() const
{
return TotalWidth;
}
const TDesC& CBars2SymUpc::Name() const
{
_LIT(KUpcName, "UPC");
return KUpcName;
}
CBars2Sym::CodeType* CBars2SymUpc::TurnDigitsToText(TBuf8<Digits*2>& code)
{
#ifdef UNICODE
const TUint16 digits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
#else
const TUint8 digits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
#endif
CBars2Sym::CodeType* pResult = new CBars2Sym::CodeType;
int i;
for (i=0; i<Digits*2; i++) {
pResult->Append(digits[code[i]]);
}
pResult->ZeroTerminate();
return pResult;
}
bool CBars2SymUpc::VerifyCheckDigit(TBuf8<Digits*2>& digits)
{
// compute check digit
// add even numbered digits
int evenSum = 0;
int i;
for (i=0;i<Digits*2;i+=2) {
evenSum += digits[i];
}
// add odd numbered digits
int oddSum = 0;
for (i=1;i<Digits*2-1;i+=2) {
oddSum += digits[i];
}
// compute even digit sum * 3 + odd digit sum;
int total = evenSum*3+oddSum;
// check digit is this sum subtracted from the next higher multiple of 10
int checkDigit = (total/10 + 1) * 10 - total;
return digits[Digits*2-1] == checkDigit;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -