画像のグレースケール変換

解説


   RGBのカラー画像CBitmap m_cBitmapをグレースケール(白黒画像)に変換する。

   原理的には変換にはYCrCb変換のY値、つまり輝度を求めるのに使われる下記の式を使用。

     出力画素 = (0.299 * R + 0.587 * G + 0.114 * B)

   ただし浮動小数点演算だとクロック数を多く消費するので以下の整数演算式を使用。

     出力画素 = (0.299 * R + 0.587 * G + 0.114 * B) * 256 / 256
           = (77 * R + 150 * G + 29 * B) >> 8


   厳密に変換しているわけではないので変換後の画像は元の画像と同じく1ピクセル当たり3Bytesを消費している




//
//		グレースケールへの変更
//
//			※ 1pixel 3Byte使用は変わらず!
//
//	YCrCbのY値つまり輝度を用いることによる変換
//	出力画素 = (0.299 * R + 0.587 * G + 0.114 * B)
//
bool	CDIBitmap::ConvertToGrayScale(void)
{
	TRY
	{
		int		i;
		int		j;
		int		n;
		int		nGray;
		BITMAP	sBitmap;
		DWORD	dwLineBytes;
		DWORD	dwSizeImage;
		BYTE*	lpBuffer;

		m_lpcBitmap->GetBitmap(&sBitmap);

		dwSizeImage	 = (DWORD)(sBitmap.bmWidthBytes * sBitmap.bmHeight);
		dwLineBytes = sBitmap.bmWidthBytes;

		lpBuffer = new BYTE[dwSizeImage + 1];

		m_lpcBitmap->GetBitmapBits(dwSizeImage,lpBuffer);

		n = 0;
		for(j = 0; j < sBitmap.bmHeight; j++)
		{
			//lpBuffer[n+0]から[n+2]はそれぞれR、G、B値となる
			for(i = 0;i < sBitmap.bmWidth; i++)
			{
				// (0.299 * R + 0.587 * G + 0.114 * B)を整数演算式に変換して使用
				nGray = (int)(77 * lpBuffer[n + 0] + 150 * lpBuffer[n + 1] + 29 * lpBuffer[n + 2]) >> 8;
				lpBuffer[n + 0] = (BYTE)nGray;
				lpBuffer[n + 1] = (BYTE)nGray;
				lpBuffer[n + 2] = (BYTE)nGray;
				n += 3;
			}
			n = j * dwLineBytes;
		}
		m_lpcBitmap->SetBitmapBits(dwSizeImage,lpBuffer);		//CBitmapへの保存
		delete	lpBuffer;

		return	true;
	}
	CATCH_ALL(e)
		return	false;
	END_CATCH_ALL
}

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