boxsmooth.cpp

来自「barcode readers [ from Image]」· C++ 代码 · 共 173 行

CPP
173
字号
//
// BoxSmooth
//   Smooths a gray image with an nxm box filter.
//   Implemented efficiently so each filter operation takes 4 adds + 1 multiply.
//
// Copyright (C) 2003, 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 "BoxSmooth.h"

#include "Debug.h"
#include "GrayImageIter.h"
#include "GrayIndex.h"
#include "Image.h"
#include "Replicate.h"

#include <e32std.h>

using namespace Core;

namespace Algorithm
{
	EXPORT_C CBoxSmooth* CBoxSmooth::NewL(int nFilterWidth, int nFilterHeight)
	{
		CBoxSmooth *me = new (ELeave) CBoxSmooth(nFilterWidth, nFilterHeight);
		return me;
	}

	CBoxSmooth::~CBoxSmooth(void)
	{
	}

	CBoxSmooth::CBoxSmooth(int nFilterWidth, int nFilterHeight) :
		ibEmpty(true),
		inFilterHeight(nFilterHeight),
		inFilterWidth(nFilterWidth)
	{
	}

	CImage CBoxSmooth::FrontL() 
	{
		if (ibEmpty) {
			User::Leave(KErrGeneral);
		}
		ibEmpty = true;
		return iImage;
	}

	// Do the filtering
	void CBoxSmooth::PushL(CImage image)
	{
		// Need to create an output image of the same size as the input.
		IReplicate rRepl(image);
		rRepl.CastL(iImage);
		// Get the image size
		IImageSize rSize(image);

		// The computation is done by maintaining a sum for each column of the input. The column sum is
		// maintained, after initialization, simply by subtracting off the top row and adding on the
		// bottom one.
		// Allocate space for the sums.
		int *nSums = new (ELeave) int [rSize.Width()];
		CleanupStack::PushL(nSums);
		// We handle the filtering at the edge of the image slightly cleverly by keeping track of the
		// number of pixels that have been added in the column sums. When the box filter extends
		// outside the image we sum just the pixels that lie within the image and divide by their
		// count. This means we have to maintain a count of the number of pixels in each column sum.
		int *nCounts = new (ELeave) int [rSize.Width()];
		CleanupStack::PushL(nCounts);

		int i=0;
		int nHalfHeight = inFilterHeight/2;
		int nHalfWidth = inFilterWidth/2;
		// initialize counts to zero
		for (; i<rSize.Width(); i++) {
			nSums[i] = 0;
			nCounts[i] = 0;
		}

		image.LockLC();
		// Create input iterator
		IGrayImageIter rIn(image);
		// Create indexer for input
		IGrayIndex rIndex(image);
		// Create an iterator for the output
		IGrayImageIter rOut(iImage);
		// Sum first nHalfHeight rows
		for (i=0; i<nHalfHeight; i++) {
			int j=0;
			for (; j<rSize.Width(); j++) {
				nSums[j] += rIn++();
				nCounts[j] ++;
			}
			rIn.NextRow();
		}
		// now start summing and outputing filtered values
		// start output iterator
		for (i=0; i<rSize.Height(); i++) {
			// add next row
			int nNextRow = i+nHalfHeight;
			if (nNextRow < rSize.Height()) {
				int j=0;
				for (; j<rSize.Width(); j++) {
					nSums[j] += rIndex[nNextRow][j];
					nCounts[j]++;
				}
			}
			// column sums have been updated to include the new row.
			// form first sum
			int nSum = 0;
			int nCount = 0;
			int j=0;
			for (; j<nHalfWidth; j++) {
				nSum += nSums[j];
				nCount += nCounts[j];
			}
			// first sum has been calculated. Now work across the image
			// and calculate all the other sums and assign them to the
			// output image
			for (j=0; j<rSize.Width(); j++) {
				int nNextCol = j+nHalfWidth;
				if (nNextCol < rSize.Width()) {
					nSum += nSums[nNextCol];
					nCount += nCounts[nNextCol];
				}
				// output sum
				rOut++() = (unsigned char) (nSum / nCount);
				// update for next pixel
				int nPrevCol = j-nHalfWidth;
				if (nPrevCol >= 0) {
					nSum -= nSums[nPrevCol];
					nCount -= nCounts[nPrevCol];
				}
			}
			// subtract previous row
			int nPrevRow = i-nHalfHeight;
			if (nPrevRow >= 0) {
				int j=0;
				for (; j<rSize.Width(); j++) {
					nSums[j] -= rIndex[nPrevRow][j];
					nCounts[j]--;
				}
			}
			rOut.NextRow();
		}
		CleanupStack::PopAndDestroy(); // unlock bitmaps
		ibEmpty = false;
		CleanupStack::PopAndDestroy(nCounts);
  		CleanupStack::PopAndDestroy(nSums);
		CDebug::ShowImage(iImage);
	}

	bool CBoxSmooth::Empty() const
	{
		return ibEmpty;
	}
};

⌨️ 快捷键说明

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