GDI+を利用した画像処理テストのスケルトン

解説

 最近DirectShowによる動画プログラミングにはまっている。と言ってもフィルタを作って USBカメラからの映像のエッジ検出を行ったりする程度だが...
 そんな動画処理ではフレーム画像を保存しておいて画像の時間変化を見るようなこともし ていたが、結局のところ 動画=静止画の連続 という構図は変わることがなく、静止画を例 にちょっと画像処理を見てみようかと思った。

 まずは簡単に処理部分のプログラミングができるようにスケルトンを作成することにした。 カスタムプロジェクトを作ってもいいのだが、たかがテストのためにそこまで凝らなくても いいかと思い、簡単にコピー&ペーストできるスケルトンを作成することにした。

 画像処理をテストすることだけを目的にしたスケルトンのため、エラー処理もなければ (絶対にやらなければならない)終了処理も省いている。また、ウインドウを描画するた びに画像ファイルを読み込み直すなどかなり実行効率は悪い。

 画像処理のテストをする際にはソースコード中の"画像処理"の部分を変更すればいい。


実行例



ソースコード

 WTLのSDI Applicationでプロジェクトを作成し、...View.hに太字で示したコードを 追加する。この例ではプロジェクト名を「ImageEffect100」にしている。


// ImageEffect100View.h : interface of the CImageEffect100View class
//
/////////////////////////////////////////////////////////////////////////////

#pragma once

#include	"gdiplus.h"
#pragma	comment(lib,"Gdiplus.lib")


class CImageEffect100View : public CWindowImpl
{
public:
	DECLARE_WND_CLASS(NULL)

	BOOL PreTranslateMessage(MSG* pMsg)
	{
		pMsg;
		return FALSE;
	}

	BEGIN_MSG_MAP(CImageEffect100View)
		MESSAGE_HANDLER(WM_PAINT, OnPaint)
	END_MSG_MAP()

// Handler prototypes (uncomment arguments if needed):
//	LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
//	LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
//	LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)




	LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
	{
		CPaintDC dc(m_hWnd);


		////////////////////////////
		//GDI+初期化
		//本当はアプリケーションの初期化時に行うべきだがソースコードの簡易化のためOnPaintに配置
		ULONG_PTR	_nToken;
		Gdiplus::GdiplusStartupInput _sGdiplusStartupInput;
		Gdiplus::GdiplusStartup(&_nToken,&_sGdiplusStartupInput,NULL);


		////////////////////////////
		//画像読み込み
		//ソースコード簡易化のため描画毎に読み出す
		Gdiplus::Bitmap*	pImage;
		Gdiplus::Graphics	cGraphics(dc.m_hDC);

		pImage = Gdiplus::Bitmap::FromFile(L"c:\\test.jpg",TRUE);


		////////////////////////////
		//画像表示(画像処理前)
		cGraphics.DrawImage(pImage,(Gdiplus::REAL)0,(Gdiplus::REAL)0
			,(Gdiplus::REAL)pImage->GetWidth(),(Gdiplus::REAL)pImage->GetHeight());


		////////////////////////////
		//画像処理
		//
		UINT		x;
		UINT		y;
		UINT		nPos;
		RGBTRIPLE*	pTmp;
		Gdiplus::BitmapData		bitmapData;

		pImage->LockBits(&Gdiplus::Rect(0,0,pImage->GetWidth(),pImage->GetHeight())
			,Gdiplus::ImageLockModeRead | Gdiplus::ImageLockModeWrite,PixelFormat24bppRGB,&bitmapData);

		pTmp = (RGBTRIPLE*)bitmapData.Scan0;
		for(y = 0; y < pImage->GetHeight(); y++)
		{
			for(x = 0; x < pImage->GetWidth(); x++)
			{
				nPos = x + (y * bitmapData.Stride) / sizeof(RGBTRIPLE);

				//画像をグリーンにする
				pTmp[nPos].rgbtBlue	= 0;
				pTmp[nPos].rgbtRed	= 0;
			}
		}
		pImage->UnlockBits(&bitmapData);


		////////////////////////////
		//画像表示(画像処理後)
		cGraphics.DrawImage(pImage,(Gdiplus::REAL)pImage->GetWidth() + 2,(Gdiplus::REAL)0
			,(Gdiplus::REAL)pImage->GetWidth(),(Gdiplus::REAL)pImage->GetHeight());

		////////////////////////////
		//画像開放
		delete	pImage;

		////////////////////////////
		//GDI+開放処理
		//本当はアプリケーションの終了時に行うべきだがソースコードの簡易化のため行わない
		//Gdiplus::GdiplusShutdown(_nToken);

		return 0;
	}
};


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