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

📄 bars2symupcx2.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"

using namespace Algorithm;
using namespace Barcode;
using namespace Core;

class CodeValue
{
public:
	CodeValue(TInt conv)
	{
		this->iConv = conv;
		this->iCount = 1;
	}
	void Add(TInt conv)
	{
		this->iCount ++;
		this->iConv = Max(this->iConv, conv);
	}
	TInt Conv() const
	{
		return iConv;
	}
	TInt Count() const 
	{
		return iCount;
	}
private:
	TInt iConv;
	TInt iCount;
};

    CBars2SymUpc::~CBars2SymUpc(void)
	{
		ClearHash();

		delete iCodes;
		iCodes = NULL;
		ipfCoeff->Reset();
		delete ipfCoeff;
		ipfCoeff = NULL;
	}


	EXPORT_C CBars2SymUpc* CBars2SymUpc::NewL()
	{
		CBars2SymUpc *pMe = new (ELeave) CBars2SymUpc();
		CleanupStack::PushL(pMe);
		pMe->ConstructL();
		CleanupStack::Pop(pMe);
		return pMe;
	}

	CBars2SymUpc::CBars2SymUpc() :
		CBars2Sym(),
		ifSigma(0.2)
	{
	}

	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
		TReal conv[10][DigitWidth];
		
		for (i=0; i<10; i++) {
			char digitCode = digitCodes[i];
			int j;
			for (j=DigitWidth-1;j>=0;j--) {
				if (digitCode & 1) {
					conv[i][j] = -1.0;
				} else {
					conv[i][j] = 1.0;
				}
				digitCode = digitCode >> 1;
			}
		}
		ComputeCoefficientsL();
		// form left digit convolution masks
		for (i=0; i<10; i++) {
			int j;
			for (j=0; j<10; j++) {
				TReal fConvLeft[LeftWidth+DigitWidth*2];
				fConvLeft[0] = -1.0;
				fConvLeft[1] = 1.0;
				fConvLeft[2] = -1.0;
				Mem::Copy(
						(TAny*) &fConvLeft[LeftWidth], 
						(TAny*) conv[i], 
						DigitWidth*sizeof(TReal));
				Mem::Copy(
						(TAny*) &fConvLeft[LeftWidth+DigitWidth], 
						(TAny*) conv[j], 
						DigitWidth*sizeof(TReal));
				BlurPatternL(fConvLeft, LeftWidth+DigitWidth*2);
				NormalizePattern(fConvLeft, LeftWidth+DigitWidth*2, iLeftConv[i][j], true, true);
			}
		}
		// form middle digit convolution masks
		for (i=0; i<10; i++) {
			int j;
			for (j=0; j<10; j++) {
				TReal fConvMid[MidWidth+DigitWidth*2];
				// 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*) conv[i], 
						DigitWidth*sizeof(TReal));
				Mem::Copy(
						(TAny*) &fConvMid[MidWidth+DigitWidth], 
						(TAny*) conv[j], 
						DigitWidth*sizeof(TReal));
				BlurPatternL(fConvMid, MidWidth+DigitWidth*2);
				NormalizePattern(fConvMid, MidWidth+DigitWidth*2, 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*) conv[i], 
						DigitWidth*sizeof(TReal));
				Mem::Copy(
						(TAny*) &fConvPairs[DigitWidth], 
						(TAny*) conv[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*2>*>(16);
	}

	void CBars2SymUpc::BlurPatternL(TReal* vector, TInt nLength) const
	{
		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];
			}
		    (*pResult)[i] = sum / sumWeights;
		}
		Mem::Copy((TAny*) vector, (TAny*) &(*pResult)[0], nLength*sizeof(TReal));
		CleanupStack::PopAndDestroy(pResult);
	}

	void CBars2SymUpc::ClearHash()
	{
		if (iHash) {
			if (iHash->First()) {
				do {
					// delete the stored values
					delete (CodeValue *)iHash->Value();
				} while (iHash->Next());
			}
			delete iHash;
			iHash = NULL;
		}
		if (iCodes) {
			int i;
			for (i=0; i<iCodes->Count(); i++) {
				delete iCodes->At(i);
			}
			iCodes->Reset();
		}
	}

	void CBars2SymUpc::ComputeCoefficientsL()
	{
		ipfCoeff = new (ELeave) CArrayFixFlat<TReal>(128);
		const TReal threshold = 0.05;
		// = Sqrt(2*Pi)
		const TReal Sqrt2Pi = 2.506628274631000;
		TReal denom1 = 1.0 / (Sqrt2Pi * ifSigma);
		TReal denom2 = 1.0 / (2.0 * ifSigma * ifSigma);
		TInt x = 0;
		TReal coeff;
		do {
			TReal exp;
			Math::Exp(exp, -x * x * denom2);
			coeff = denom1 * exp;
			ipfCoeff->AppendL(coeff);
			x += 1;
		} while (coeff > threshold); // track through end of tail
		// now normalize so the sum is 1, taking into account 
		// the symmetric pattern of the weights, of which we've
		// computed one side
		TReal sum = ipfCoeff->At(0);
		TInt i;
		for (i=1; i<ipfCoeff->Count(); i++) {
			sum += ipfCoeff->At(i) * 2;
		}
		for (i=0; i<ipfCoeff->Count(); i++) {
			ipfCoeff->At(i) /= sum;
		}
	}


    IMPORT_C bool CBars2SymUpc::DecodeL(
				CImage image, 
				TRect rectangle,
				CBars2Sym::CodeType*& pCode)
	{
		pCode = NULL; // no return
		int CountDigits[Digits*2][10];

		Mem::FillZ((TAny*) CountDigits, sizeof(CountDigits));

		IImageSize size(image);

		int i;
		iHash = CHashTable::NewL(7);
		int pixelsPerBar = size.Width() / TotalWidth;
		TInt row;
		int totalConv = 0;
		for (row = 0; row<size.Height(); row++) {
			TInt nOffset = EstimateLeftEdge(image, row);
			TBuf8<Digits*2> code;
			code.SetMax();
			image.LockLC();
			IGrayIndex index(image);
			int pos = nOffset; // position of start of barcode pattern
			int bestDigit = -1, bestDigit1 = -1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -