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

📄 widths2bars.cpp

📁 barcode readers [ from Image]
💻 CPP
字号:
//
// CWidths2Bars
// Given an array of edge positions compute a string
// representing the bar code widths corresponding to those edge
// positions.
//
// Copyright (C) 2006 by Jon A. Webb (Contact via GMail; username is jonawebb)
//
// 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 "Widths2Bars.h"

namespace Algorithm
{

    EXPORT_C CWidths2Bars* CWidths2Bars::NewL(TReal rMinWidth, TReal rMaxWidth, TReal rEps, int nMinBars)
    {
        return new (ELeave) CWidths2Bars(rMinWidth, rMaxWidth, rEps, nMinBars);
    }

    CWidths2Bars::CWidths2Bars(TReal rMinWidth, TReal rMaxWidth, TReal rEps, int nMinBars) :
	    inMinBars(nMinBars),
		irEps(rEps),
		irMaxWidth(rMaxWidth),
		irMinWidth(rMinWidth)
    {
		if (inMinBars < 2) {
			inMinBars = 2;
		}
    }

    CWidths2Bars::~CWidths2Bars(void)
    {
    }

    bool CWidths2Bars::FindBarsL(CArrayFix<TReal>* pPositions, CArrayFix<char>*& pBars, int& nBarStart, int& nBarEnd)
	{
		if (pPositions->Count() < inMinBars) {
			return false;
		}
		CArrayFixFlat<TReal>& widths(*new CArrayFixFlat<TReal>(16));
		CleanupStack::PushL(&widths);
		// transform the edge positions into an array of bar widths
		// skip over bars that are too narrow
		int i;
		TReal rPosPrev = (*pPositions)[0];
		for (i=1; i<pPositions->Count(); i++) {
			// the invariant here is that widths 0..i-1 holds all
			// bar widths from pPositions where the bar width is
			// greater than the minimum 
			TReal rPosThis = (*pPositions)[i];
			TReal rWidth = rPosThis - rPosPrev;
			if (rWidth >= irMinWidth) {
				widths.AppendL(rWidth);
			} else {
				// skip this bar -- it represents noise.
				// do not update rPosPrev -- which will cause
				// the previous bar to be continued
			}
			rPosPrev = rPosThis;
		}
		if (widths.Count() < inMinBars) {
			CleanupStack::PopAndDestroy(&widths);
			return false;
		}
		// now find the shortest bar width in the array
		TReal rShortest = widths[0];
		for (i=0; i<widths.Count()-1; i++) {
			if (widths[i] < rShortest) {
				rShortest = widths[i];
			}
		}
		// there may be several bars around this width; we average them to get
		// the true shortest bar width, so long as they're within irEps
		int nBars = 0;
		TReal rSum = 0.0;
		for (i=0; i<widths.Count()-1; i++) {
			if (widths[i] < rShortest * (1.0+irEps)) {
				rSum += widths[i];
				nBars += 1;
			}
		}	
		// get the average shortest width
		rShortest = rSum / nBars;
		// divide all bars by the shortest so we can talk in terms of bar
		// width relative to the shortest from now on
		for (i=0; i<widths.Count(); i++) {
			widths[i] /= rShortest;
		}	
		// bars greater than the maximum width are dead space on one side or another
		// of a bar code. Since we are looking for a single bar code we determine which
		// series of bars separated by a too-wide bar is the longest and use that
		int nBestStart = 0, nBestLength = 0;
		int nCurStart = 0, nCurLength = 0;
		for (i=0; i<widths.Count(); i++) {
			// the invariant here is that nBestStart ... nBestEnd is the
			// best sequence of bars, with no internal bar greater than
			// irMaxWidth in width, for all widths from 0..i-1
			// Also nCurStart...nCurEnd is the sequence of bars from the
			// last best sequence to i-1
			if (widths[i] > irMaxWidth) { // a new bar sequence end
				// is it longer than the best sequence so far
				if (nCurLength > nBestLength) {
					nBestStart = nCurStart;
					nBestLength = nCurLength;
				}
				nCurStart = i + 1;
				nCurLength = 0;
			} else {
				nCurLength += 1;
			}
		}
		// check if the final bar sequence was longer than the best
		if (nCurLength > nBestLength) {
			nBestStart = nCurStart;
			nBestLength = nCurLength;
		}
		if (nBestLength < inMinBars) {
			CleanupStack::PopAndDestroy(&widths);
			return false;
		}
		// delete the other elements from the array
		// remove the first nBestStart elements from the array
		// which will bring the element at nBestStart to the front
		if (nBestStart > 0) {
			widths.Delete(0, nBestStart);
		}
		// and all the elements after the ones we want
		if (nBestLength < widths.Count()) {
			widths.Delete(
				nBestLength, 
				widths.Count() - nBestLength);
		}

		// now transform the array into an array of output bar relative widths
		pBars = new (ELeave) CArrayFixFlat<char>(128);
		for (i=0; i<widths.Count(); i++) {
			// the invariant here is that widths 0..i-1 have been turned into
			// digits
			TInt32 nRelative;
			Math::Int(nRelative, widths[i] + 0.49); // round
			pBars->AppendL((unsigned char) Min(nRelative, 255));
		}
		CleanupStack::PopAndDestroy(&widths);
		return true;
	}

}; // namespace Algorithm

⌨️ 快捷键说明

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