画像の誤差拡散法による2階調化2

解説

 画像をグレースケール変換して指定されたしきい値を境に2つの色に変える。そのとき 新しい画像と元画像との誤差を右、左下、下、右下の各ピクセルに反映させる誤差拡散法 を採用した。



実行例

 以下のコードで処理を施した。
		RGBTRIPLE	rgbHigh;
		RGBTRIPLE	rgbLow;

		rgbHigh.rgbtBlue	= 100;
		rgbHigh.rgbtGreen	= 255;
		rgbHigh.rgbtRed		= 255;
		rgbLow.rgbtBlue		= 0;
		rgbLow.rgbtGreen	= 0;
		rgbLow.rgbtRed		= 0;
		_cImage2.BicolorErrorVariance2(120,rgbHigh,rgbLow);



 前回作成した処理関数BicolorErrorVarianceよりも誤差適用範囲が広いため、生成で きる画像はきめ細かくなるはずだが...BicolorErrorVarianceよりも劣っている。


ソースコード

 GDI+を利用した画像処理テストのスケルトン2を 元に拡張する。


 前に作成した「DnpImage.h」に2階調化関数を追加する。


class	CDnpImage : public CDnpImageBase
	,public CDnpImageConvolution
	,public CDnpColorSpaceHLS
	,public CDnpColorSpaceHSV
{
public:

	//
	//	画像の誤差拡散法による2階調化
	//
	//グレースケール変換したときの色値がcbThresholdを超えていればrgbHighに、
	//下回ればrgbLowに変えて2階調化する。新しい値の誤差を右、左下、下、右下
	//など右、左下、下、右下方向2列までの各ピクセルに割り振る誤差拡散法による。
	//
	bool	BicolorErrorVariance2(BYTE cbThreshold,RGBTRIPLE rgbHigh,RGBTRIPLE rgbLow)
	{
		if(IsValidImage() == false)
			return	false;

		int			nStrideBytes;
		bool		ret;
		UINT		x;
		UINT		y;
		UINT		nWidth;
		UINT		nHeight;
		BYTE*		pData;
		RGBTRIPLE*	pRGB;
		BYTE		cbHigh;
		BYTE		cbLow;
		int			nError;

		cbHigh	= (BYTE)((77 * rgbHigh.rgbtRed + 150 * rgbHigh.rgbtGreen + 29 * rgbHigh.rgbtBlue) >> 8);
		cbLow	= (BYTE)((77 * rgbLow .rgbtRed + 150 * rgbLow .rgbtGreen + 29 * rgbLow .rgbtBlue) >> 8);

		nWidth	= GetWidth();
		nHeight	= GetHeight();

		//グレースケール変換
		ret = GrayScale();
		if(ret == false)
			return	false;

		ret = LockBits(&pData,&nStrideBytes);
		if(ret == false)
			return	false;

		for(y = 0; y < nHeight; y++)
		{
			pRGB = (RGBTRIPLE*)pData;
			for(x = 0; x < nWidth; x++)
			{
				RGBTRIPLE*	pRGBDown1;
				RGBTRIPLE*	pRGBDown2;

				pRGBDown1 = (RGBTRIPLE*)((BYTE*)pRGB + nStrideBytes);
				pRGBDown2 = (RGBTRIPLE*)((BYTE*)pRGB + nStrideBytes * 2);
				//pRGB[x]			//現
				//pRGB[x+1]			//右
				//pRGB[x+2]			//右2つ目
				//pRGBDown1[x-1]	//左下
				//pRGBDown1[x]		//真下
				//pRGBDown1[x+1]	//右下
				//pRGBDown2[x-1]	//左下2つ目
				//pRGBDown2[x]		//真下2つ目
				//pRGBDown2[x+1]	//右下2つ目
				//....

				if(pRGB[x].rgbtRed > cbThreshold)
				{
					pRGB[x] = rgbHigh;
					nError = (int)cbHigh - (int)pRGB[x].rgbtRed;
				}
				else
				{
					pRGB[x] = rgbLow;
					nError = (int)cbLow - (int)pRGB[x].rgbtRed;
				}

				#define		ERROR_VARIANCE(rgb,nWeight)			\
					{											\
						rgb.rgbtRed += nError * nWeight / 48;	\
						if(rgb.rgbtRed > 255)					\
							rgb.rgbtRed = 255;					\
						if(rgb.rgbtRed < 0)						\
							rgb.rgbtRed = 0;					\
					}

				//右1
				if(x < nWidth - 1)
					ERROR_VARIANCE(pRGB[x + 1],7);
				//右2
				if(x < nWidth - 2)
					ERROR_VARIANCE(pRGB[x + 2],5);

				if(y < nHeight - 1)
				{
					//下1左2
					if(x >= 2)
						ERROR_VARIANCE(pRGBDown1[x - 2],3);
					//下1左1
					if(x >= 1)
						ERROR_VARIANCE(pRGBDown1[x - 1],5);
					//下1
					ERROR_VARIANCE(pRGBDown1[x],7);
					//下1右1
					if(x < nWidth - 1)
						ERROR_VARIANCE(pRGBDown1[x + 1],5);
					//下1右2
					if(x < nWidth - 2)
						ERROR_VARIANCE(pRGBDown1[x + 2],3);
				}

				if(y < nHeight - 2)
				{
					//下2左2
					if(x >= 2)
						ERROR_VARIANCE(pRGBDown2[x - 2],1);
					//下2左1
					if(x >= 1)
						ERROR_VARIANCE(pRGBDown2[x - 1],3);
					//下2
					ERROR_VARIANCE(pRGBDown2[x],5);
					//下2右1
					if(x < nWidth - 1)
						ERROR_VARIANCE(pRGBDown2[x + 1],3);
					//下2右2
					if(x < nWidth - 2)
						ERROR_VARIANCE(pRGBDown2[x + 2],1);
				}
			}
			pData += nStrideBytes;
		}
		UnlockBits();

		return	true;
	}


	。。。。省略。。。。

};

カテゴリー「VC++ TIPS」 のエントリー