📄 bars2symupc.cpp
字号:
//
// Bars2SymUpc
// Given an array of bar code widths read a UPC bar
// code, if present.
//
// This code was written based on the Wikipedia entry for the
// UPC barcode: http://en.wikipedia.org/wiki/Universal_Product_Code.
//
// Copyright (C) 2006 by Jon A. Webb
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
//
#include "Bars2SymUpc.h"
#include "Array.h"
#include "GrayIndex.h"
#include "HistEq.h"
#include "ImageSize.h"
#include "RectStretch.h"
#include "Sequence.h"
#include "VerticalAverage.h"
#include <e32base.h>
using namespace Algorithm;
using namespace Barcode;
using namespace Core;
class CodeConv
{
public:
CodeConv() :
iConv(0)
{}
CodeConv(TUint8 digitFirst, TInt32 conv)
{
iDigits.Append(digitFirst);
iConv = conv;
}
CodeConv(TBuf8<CBars2SymUpc::Digits> code, TInt32 conv) {
iConv = conv;
iDigits.Copy(code);
}
// Operations
void AddDigit(TUint8 digitNext, TInt32 conv) {
iDigits.Append(digitNext);
iConv += conv;
}
void ResetConv() {
iConv = KMinTInt32;
}
// Accessors
TBuf8<CBars2SymUpc::Digits> Code() const
{
return iDigits;
}
TInt32 Conv() const
{
return iConv;
}
TUint8 LastDigit() const
{
return iDigits[iDigits.Length()-1];
}
private:
TInt32 iConv;
TBuf8<CBars2SymUpc::Digits> iDigits;
};
//
// Cleanup Support functions
//
// Needed for CleanupDeletePushL(CArrayFixFlat<CodeConv>*) to work
//
// Note: if you don't define these functions, the program will still compile
// and run on the emulator, but won't run on the phone -- annoying!
//
void CleanupDelete<CArrayFixFlat<CodeConv> *>::Delete(TAny *ptr)
{
CArrayFixFlat<CodeConv> * pArray = (CArrayFixFlat<CodeConv>*) ptr;
pArray->Reset();
delete pArray;
};
CBars2SymUpc::~CBars2SymUpc(void)
{
ClearHash();
delete iHashLeft;
iHashLeft = NULL;
delete iHashRight;
iHashRight = NULL;
delete iCodes;
iCodes = NULL;
ipfCoeff->Reset();
delete ipfCoeff;
ipfCoeff = NULL;
}
EXPORT_C CBars2SymUpc* CBars2SymUpc::NewL(TInt nWidth)
{
CBars2SymUpc *pMe = new (ELeave) CBars2SymUpc(nWidth);
CleanupStack::PushL(pMe);
pMe->ConstructL();
CleanupStack::Pop(pMe);
return pMe;
}
CBars2SymUpc::CBars2SymUpc(TInt nWidth) :
CBars2Sym(),
ifSigma(0.35)
{
TInt nPixelsPerBar = nWidth / TotalWidth;
switch (nPixelsPerBar) {
case 0:
ifSigma = 0.1;
break;
case 1:
ifSigma = 0.25;
break;
case 2:
ifSigma = 0.5;
break;
default:
ifSigma = 1.0;
break;
}
}
void CBars2SymUpc::ConstructL()
{
/* The (L) codes for the ten digits are:
0 = 3-2-1-1 = 0001101 = 0x0d
1 = 2-2-2-1 = 0011001 = 0x19
2 = 2-1-2-2 = 0010011 = 0x13
3 = 1-4-1-1 = 0111101 = 0x3d
4 = 1-1-3-2 = 0100011 = 0x23
5 = 1-2-3-1 = 0110001 = 0x31
6 = 1-1-1-4 = 0101111 = 0x2f
7 = 1-3-1-2 = 0111011 = 0x3b
8 = 1-2-1-3 = 0110111 = 0x37
9 = 3-1-1-2 = 0001011 = 0x0b
*/
// The R codes for the digits are the 1-complements
// of the L codes. But we encode the R digits by
// encoded a white bar as 1 and a black bar as 0
// so we automatically get the 1-complement without
// while using the same table
char digitCodes[] = {0x0d, 0x19, 0x13, 0x3d, 0x23, 0x31, 0x2f, 0x3b, 0x37, 0x0b};
int i;
// initialize convolution table
// on the left side we append -1 and on the right side
// we apend +1
// because we expect that each barcode will be preceded
// by a black and followed by a white stripe
for (i=0; i<10; i++) {
char digitCode = digitCodes[i];
int j;
for (j=DigitWidth-1;j>=0;j--) {
if (digitCode & 1) {
iDigitCodes[i][j] = -1.0;
} else {
iDigitCodes[i][j] = 1.0;
}
digitCode = digitCode >> 1;
}
}
ComputeCoefficientsL();
// form left digit convolution masks
for (i=0; i<10; i++) {
TInt j;
for (j=0; j<10; j++) {
TReal fConvLeft[DigitWidth*2+LeftWidth];
fConvLeft[0] = -1.0;
fConvLeft[1] = 1.0;
fConvLeft[2] = -1.0;
Mem::Copy(
(TAny*) &fConvLeft[LeftWidth],
(TAny*) iDigitCodes[i],
DigitWidth*sizeof(TReal));
Mem::Copy(
(TAny*) &fConvLeft[LeftWidth+DigitWidth],
(TAny*) iDigitCodes[j],
DigitWidth*sizeof(TReal));
BlurPatternL(fConvLeft, DigitWidth*2+LeftWidth);
NormalizePattern(fConvLeft, DigitWidth*2+LeftWidth, iLeftConv[i][j], true, true);
}
}
// form middle digit convolution masks
for (i=0; i<10; i++) {
TInt j;
for (j=0; j<10; j++) {
TReal fConvMid[DigitWidth*2+MidWidth];
// Note: we reverse the sign of the middle convolution mask
// because the right side of the barcode exchanges white
// and black, and we subtract the convolution sum to compensate.
// In order for the middle pattern (which isn't reversed) to be convolved
// properly it must therefore be convolved with inverted weights.
fConvMid[0] = 1.0;
fConvMid[1] = -1.0;
fConvMid[2] = 1.0;
fConvMid[3] = -1.0;
fConvMid[4] = 1.0;
Mem::Copy(
(TAny*) &fConvMid[MidWidth],
(TAny*) iDigitCodes[i],
DigitWidth*sizeof(TReal));
Mem::Copy(
(TAny*) &fConvMid[MidWidth+DigitWidth],
(TAny*) iDigitCodes[j],
DigitWidth*sizeof(TReal));
BlurPatternL(fConvMid, DigitWidth*2+MidWidth);
NormalizePattern(fConvMid, DigitWidth*2+MidWidth, iMidConv[i][j], true, true);
}
}
// form adjacent digit convolution masks
for (i=0; i<10; i++) {
int j;
for (j=0; j<10; j++) {
TReal fConvPairs[DigitWidth*2];
Mem::Copy(
(TAny*) fConvPairs,
(TAny*) iDigitCodes[i],
DigitWidth*sizeof(TReal));
Mem::Copy(
(TAny*) &fConvPairs[DigitWidth],
(TAny*) iDigitCodes[j],
DigitWidth*sizeof(TReal));
// now blur the convolution patterns, scale and convert to int,
// then release memory
BlurPatternL(fConvPairs, DigitWidth*2);
NormalizePattern(fConvPairs,
DigitWidth*2,
iPairConv[i][j],
true,
true);
}
}
iCodes = new (ELeave) CArrayFixFlat<TBuf8<Digits>*>(16);
iHashLeft = CHashTable<Code, TInt>::NewL(7);
iHashRight = CHashTable<Code, TInt>::NewL(7);
}
TInt CBars2SymUpc::BestCode(CArrayFixFlat<CodeConv>& codes)
{
TInt j;
TInt32 bestConv = KMinTInt32;
TInt bestPos = -1;
for (j=0; j<codes.Count(); j++) {
if (codes[j].Conv() > bestConv) {
bestConv = codes[j].Conv();
bestPos = j;
}
}
return bestPos;
}
void CBars2SymUpc::BlurPatternL(TReal* vector, TInt nLength)
{
CArray<TReal> *pResult = CArray<TReal>::NewL(nLength);
CleanupStack::PushL(pResult);
int i;
for (i=0; i<nLength; i++) {
int j;
TReal sum = 0.0;
TReal sumWeights = 0.0;
for (j=Max(0,i-ipfCoeff->Count()+1);
j<Min(nLength, i+ipfCoeff->Count());
j++) {
TReal weight = ipfCoeff->At(Abs(i-j));
sumWeights += weight;
sum += weight * vector[j];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -