⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bars2symupc.cpp

📁 barcode readers [ from Image]
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// 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 + -