boxsmoothrgb.cpp

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

CPP
195
字号
//
// BoxSmoothRgb
//   Smooths a color image with an nxm box filter.
//   Implemented efficiently so each filter operation takes 4 adds + 1 multiply per color.
//
// 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 "BoxSmoothRgb.h"

#include "Debug.h"
#include "Image.h"
#include "Replicate.h"
#include "RgbImageIter.h"
#include "RgbIndex.h"

#include <e32std.h>

using namespace Core;

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

	CBoxSmoothRgb::~CBoxSmoothRgb(void)
	{
	}

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

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

	// Do the filtering
	void CBoxSmoothRgb::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.
		typedef int (*RgbColArray)[][3];
		RgbColArray nSums = (RgbColArray) new (ELeave) int [rSize.Width()][3];
		// initialize sums to zero
		Mem::FillZ(nSums, sizeof(int) * 3 * 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 = (int*) new (ELeave) int [rSize.Width()];
		// initialize counts to zero
		Mem::FillZ(nCounts, sizeof(int) * rSize.Width());
		CleanupStack::PushL(nCounts);

		int i=0;
		int color;
		int nHalfHeight = inFilterHeight/2;
		int nHalfWidth = inFilterWidth/2;

		image.LockLC();
		// Create input iterator
		IRgbImageIter rIn(image);
		// Create indexer for input
		IRgbIndex rIndex(image);
		// Create an iterator for the output
		IRgbImageIter rOut(iImage);
		// Sum first nHalfHeight rows
		rIn.Reset();
		for (i=0; i<nHalfHeight; i++) {
			int j=0;
			for (; j<rSize.Width(); j++) {
				for (color=0; color<3; color++) {
					(*nSums)[j][color] += rIn[color];
				}
				nCounts[j]++;
				rIn++;
			}
			rIn.NextRow();
		}
		// now start summing and outputing filtered values
		// start output iterator
		rOut.Reset();
		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++) {
					for (color=0; color<3; color++) {
						(*nSums)[j][color] += rIndex[nNextRow][j][color];
					}
					nCounts[j]++;
				}
			}
			// column sums have been updated to include the new row.
			// form first sum
			int nSum[3] = {0};
			int nCount = 0;
			int j=0;
			for (; j<nHalfWidth; j++) {
				for (color=0; color<3; color++) {
					nSum[color] += (*nSums)[j][color];
				}
				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()) {
					for (color=0; color<3; color++) {
						nSum[color] += (*nSums)[nNextCol][color];
					}
					nCount += nCounts[nNextCol];
				}
				// output sum
				for (color=0; color<3; color++) {
					rOut[color] = (unsigned char) (nSum[color] / nCount);
				}
				rOut++;
				// update for next pixel
				int nPrevCol = j-nHalfWidth;
				if (nPrevCol >= 0) {
					for (color=0; color<3; color++) {
						nSum[color] -= (*nSums)[nPrevCol][color];
					}
					nCount -= nCounts[nPrevCol];
				}
			}
			// subtract previous row
			int nPrevRow = i-nHalfHeight;
			if (nPrevRow >= 0) {
				int j=0;
				for (; j<rSize.Width(); j++) {
					for (color=0; color<3; color++) {
						(*nSums)[j][color] -= rIndex[nPrevRow][j][color];
					}
					nCounts[j]--;
				}
			}
			rOut.NextRow();
		}
		CleanupStack::PopAndDestroy(); // unlock bitmaps

		ibEmpty = false;
		CDebug::ShowImage(iImage);
		CleanupStack::Check(nCounts);
		CleanupStack::PopAndDestroy();
  		CleanupStack::Check(nSums);
  		CleanupStack::PopAndDestroy();
	}

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

⌨️ 快捷键说明

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