わびさびサンプルソース

WindowsやHTML5などのプログラムのサンプルコードやフリーソフトを提供します。

Direct2Dで画像をトリミングする

Direct2Dは、画像をトリミングして描画を行うには、ID2D1HwndRenderTarget::DrawBitmap()メソッドを使います。 DrawBitmap()メソッドでは、描画する画像に対してどの部分を描画するかを矩形で指定することができます。描画したい部分だけを指定すればクリッピングができます。

#include <stdio.h>
#include <tchar.h>
#include <locale.h>
#include <iostream>
#include <windows.h>
#include <d2d1.h>
#include <wincodec.h>
#include <wincodecsdk.h>



// lib
#pragma comment( lib, "d2d1.lib" )
#pragma comment( lib, "WindowsCodecs.lib" )



/*
	メインウインドウイベント処理
*/
LRESULT CALLBACK eMainWindowProc(
	  HWND	 hwnd	// handle to window
	, UINT	 uMsg	// message identifier
	, WPARAM wParam // first message parameter
	, LPARAM lParam // second message parameter
);



// グローバル変数
IWICImagingFactory* pWICImagingFactory = NULL;
ID2D1Factory* pD2d1Factory = NULL;
ID2D1HwndRenderTarget* pRenderTarget = NULL;



/*
	Direct2Dで画像をトリミングする
*/
int _tmain
(
	  int argc
	, _TCHAR* argv[]
)
{
	// std::wcoutのロケールを設定
	std::wcout.imbue( std::locale( "", std::locale::ctype ) );

	// COM初期化
	::CoInitialize( NULL );

	WNDCLASSEX tWndClass;
	HINSTANCE  hInstance;
	TCHAR*	   cpClassName;
	TCHAR*	   cpWindowName;
	TCHAR*	   cpMenu;
	HWND	   hWnd;
	MSG		   tMsg;


	// アプリケーションインスタンス
	hInstance	 = ::GetModuleHandle( NULL );

	// クラス名称
	cpClassName	 = _T("MainWindowClass");

	// メニュー
	cpMenu		 = MAKEINTRESOURCE( NULL );

	// ウインドウ名称
	cpWindowName = _T("Direct2Dで画像をトリミングする");

	// ウインドウクラスパラメータセット
	tWndClass.cbSize		= sizeof( WNDCLASSEX );
	tWndClass.style			= CS_HREDRAW | CS_VREDRAW;
	tWndClass.lpfnWndProc	= eMainWindowProc;
	tWndClass.cbClsExtra	= 0;	// ::GetClassLong で取得可能なメモリ
	tWndClass.cbWndExtra	= 0;	// ::GetWindowLong で取得可能なメモリ
	tWndClass.hInstance		= hInstance; 
	tWndClass.hIcon			= ::LoadIcon( NULL, IDI_APPLICATION );
	tWndClass.hCursor		= ::LoadCursor( NULL, IDC_ARROW );
	tWndClass.hbrBackground = (HBRUSH)( COLOR_WINDOW + 1 );
	tWndClass.lpszMenuName	= cpMenu;
	tWndClass.lpszClassName = cpClassName;
	tWndClass.hIconSm		= NULL;

	// ウインドウクラス生成
	if ( 0 == ::RegisterClassEx( &tWndClass ) ) {

		/* 失敗 */
		return( -1 );
	}

	// ウインドウを生成する
	hWnd = ::CreateWindowEx (
		  0						  // extended window style
		, tWndClass.lpszClassName // pointer to registered class name
		, cpWindowName			  // pointer to window name
		, WS_OVERLAPPEDWINDOW	  // window style
		, CW_USEDEFAULT			  // horizontal position of window
		, CW_USEDEFAULT			  // vertical position of window
		, 640					  // window width
		, 480					  // window height
		, NULL					  // handle to parent or owner window
		, NULL					  // handle to menu, or child-window identifier
		, hInstance				  // handle to application instance
		, (VOID*)0x12345678		  // pointer to window-creation data
	);


	/*
		メッセージループ
	*/
	while( 0 != ::GetMessage( &tMsg, NULL, 0, 0 ) ) {
		::TranslateMessage ( &tMsg );
		::DispatchMessage ( &tMsg );
	}

	// COM初期化
	::CoUninitialize();

	// WM_QUITの終了コードを返却する
	return( tMsg.wParam );
}



/*
	メインウインドウイベント処理
*/
LRESULT CALLBACK eMainWindowProc
(
	  HWND	 hWnd	// handle to window
	, UINT	 uMsg	// message identifier
	, WPARAM wParam // first message parameter
	, LPARAM lParam // second message parameter
)
{
	switch( uMsg ) {
	case WM_CREATE:
	//--------------------------------------------
	// WM_CREATE
	//--------------------------------------------
		{
			CREATESTRUCT* tpCreateSt = (CREATESTRUCT*)lParam;

			/* パラメータ表示 */
			wprintf(
				L"CREATESTRUCT¥n"
				L"¥tlpCreateParams = 0x%08x¥n"
				L"¥thInstance	   = 0x%08x¥n"
				L"¥thMenu		   = 0x%08x¥n"
				L"¥thwndParent	   = 0x%08x¥n"
				L"¥tcy			   = %d¥n"
				L"¥tcx			   = %d¥n"
				L"¥ty			   = %d¥n"
				L"¥tx			   = %d¥n"
				L"¥tstyle		   = 0x%08x¥n"
				L"¥tlpszName	   = ¥"%s¥"¥n"
				L"¥tlpszClass	   = ¥"%s¥"¥n"
				L"¥tdwExStyle	   = 0x%08x¥n"
				, tpCreateSt->lpCreateParams
				, tpCreateSt->hInstance
				, tpCreateSt->hMenu
				, tpCreateSt->hwndParent
				, tpCreateSt->cy
				, tpCreateSt->cx
				, tpCreateSt->y
				, tpCreateSt->x
				, tpCreateSt->style
				, tpCreateSt->lpszName
				, tpCreateSt->lpszClass
				, tpCreateSt->dwExStyle
			);

			HRESULT hResult = S_OK;


			/*
				IWICImagingFactoryの生成
			*/
			hResult = ::CoCreateInstance( CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, reinterpret_cast<void **>( &pWICImagingFactory ) );
			if ( FAILED( hResult ) ) {

				// エラー
				std::wcout << L"CoCreateInstance失敗" << std::endl;
				break;
			}
			

			/*
				ID2D1Factoryの生成
			*/
			hResult = ::D2D1CreateFactory( D2D1_FACTORY_TYPE_MULTI_THREADED, &pD2d1Factory );
			if ( FAILED( hResult ) ) {

				// エラー
				std::wcout << L"D2D1CreateFactory失敗" << std::endl;
				break;
			}


			/*
				ID2D1HwndRenderTargetの生成
			*/
			{
				D2D1_SIZE_U oPixelSize = {
					  tpCreateSt->cx
					, tpCreateSt->cy
				};

				D2D1_RENDER_TARGET_PROPERTIES oRenderTargetProperties = D2D1::RenderTargetProperties();

				D2D1_HWND_RENDER_TARGET_PROPERTIES oHwndRenderTargetProperties = D2D1::HwndRenderTargetProperties( hWnd, oPixelSize );


				/*
					ID2D1HwndRenderTargetの生成
				*/
				hResult = pD2d1Factory->CreateHwndRenderTarget(
						  oRenderTargetProperties
						, oHwndRenderTargetProperties
						, &pRenderTarget
					);
				if ( FAILED( hResult ) ) {

					// エラー
					std::wcout << L"CreateHwndRenderTarget失敗" << std::endl;
					break;
				}
			}

			// ウインドウを表示する
			::ShowWindow( hWnd, SW_SHOW );
		}
		break;


	case WM_DESTROY:
	//--------------------------------------------
	// WM_DESTROY
	//--------------------------------------------
		{
			// ID2D1HwndRenderTargetの破棄
			if ( NULL != pRenderTarget )  {
				pRenderTarget->Release();
			}

			// ID2D1Factoryの破棄
			if ( NULL != pD2d1Factory )  {
				pD2d1Factory->Release();
			}

			// |WICImagingFactoryの破棄
			if ( NULL != pWICImagingFactory ) {
				pWICImagingFactory->Release();
			}

			// 終了する( 引数はそのまま終了コードとなります )
			::PostQuitMessage( 0 );
		}
		break;


	case WM_SIZE:
	//--------------------------------------------
	// WM_SIZE
	//--------------------------------------------
		{
			D2D1_SIZE_U oPixelSize = { LOWORD( lParam ), HIWORD( lParam ) };

			// ターゲットリサイズ
			pRenderTarget->Resize( &oPixelSize );
		}
		break;


	case WM_ERASEBKGND:
	//--------------------------------------------
	// WM_ERASEBKGND
	//--------------------------------------------
		{
			;
		}
		return( TRUE );


	case WM_PAINT:
	//--------------------------------------------
	// WM_PAINT
	//--------------------------------------------
		{
			HRESULT hResult = S_OK;

			// ターゲットサイズの取得
			D2D1_SIZE_F oTargetSize = pRenderTarget->GetSize();

			// 描画開始
			PAINTSTRUCT tPaintStruct;
			::BeginPaint( hWnd, &tPaintStruct );

			// 描画開始(Direct2D)
			pRenderTarget->BeginDraw();

			// 背景のクリア
			D2D1_COLOR_F oBKColor = { 0.8f, 0.8f, 1.0f, 1.0f };
			pRenderTarget->Clear( oBKColor );


			/*
				画像のトリミング
			*/
			{
				IWICBitmapDecoder* pWICBitmapDecoder = NULL;
				IWICBitmapFrameDecode* pWICBitmapFrame = NULL;
				IWICFormatConverter* pFormatConverter = NULL;
				ID2D1Bitmap* pBitmap = NULL;


				/*
					デコーダ生成( File to Bitmap )
				*/
				hResult = pWICImagingFactory->CreateDecoderFromFilename(
						  L".¥¥TestData¥¥whale.png"
						, NULL
						, GENERIC_READ
						, WICDecodeMetadataCacheOnLoad
						, &pWICBitmapDecoder
					);
				if ( FAILED( hResult ) ) {

					// エラー
					std::wcout << L"CreateDecoderFromFilename失敗" << std::endl;
					goto err;
				}


				/*
					ビットマップのフレーム取得
				*/
				hResult = pWICBitmapDecoder->GetFrame( 0, &pWICBitmapFrame );
				if ( FAILED( hResult ) ) {

					// エラー
					std::wcout << L"GetFrame失敗" << std::endl;
					goto err;
				}
				

				/*
					フォーマットコンバータ生成
				*/
				hResult = pWICImagingFactory->CreateFormatConverter( &pFormatConverter );
				if ( FAILED( hResult ) ) {

					// エラー
					std::wcout << L"CreateFormatConverter失敗" << std::endl;
					goto err;
				}


				/*
					フォーマットコンバータ初期化
				*/
				hResult = pFormatConverter->Initialize(
							  pWICBitmapFrame					// BitmapSource
							, GUID_WICPixelFormat32bppPBGRA		// ピクセルフォーマット
							, WICBitmapDitherTypeNone			// BitmapDitherType
							, NULL								// バレット
							, 1.0f								// 透過率
							, WICBitmapPaletteTypeMedianCut		// パレットタイプ
						);
				if ( FAILED( hResult ) ) {

					// エラー
					std::wcout << L"Initialize失敗" << std::endl;
					goto err;
				}


				/*
					BitmapSource -> Bitmapへ変換
				*/
				hResult = pRenderTarget->CreateBitmapFromWicBitmap( pFormatConverter, NULL, &pBitmap );
				if ( FAILED( hResult ) ) {

					// エラー
					std::wcout << L"CreateBitmapFromWicBitmap失敗" << std::endl;
					goto err;
				}


				/*
					Bitmapの描画
				*/
				{
					// ビットマップのサイズを取得
					D2D1_SIZE_F tBitmapSize = pBitmap->GetSize(); 

					// 描画サイズ
					D2D1_SIZE_F tDstDrawSize = { 512, 512 };

					// 描画位置
					D2D_POINT_2F tLeftTop = D2D1::Point2F(
							  ( oTargetSize.width  - tDstDrawSize.width  ) / 2
							, ( oTargetSize.height - tDstDrawSize.height ) / 2
						);

					// 描画矩形(画面中央)
					D2D1_RECT_F oDrawRect = D2D1::RectF(
							  tLeftTop.x						// left
							, tLeftTop.y						// top
							, tLeftTop.x + tDstDrawSize.width	// right
							, tLeftTop.y + tDstDrawSize.height	// bottom
						);

					// 描画矩形(コピー元)
					D2D1_RECT_F oSrcDrawRect = D2D1::RectF(
							  50	// left
							, 50	// top
							, 250	// right
							, 250	// bottom
						);

					// Bitmapの描画(トリミング)
					pRenderTarget->DrawBitmap(
							  pBitmap			// ビットマップ
							, &oDrawRect		// 描画矩形
							, 1.0f				// 透過率
							, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR
							, &oSrcDrawRect		// 描画元矩形(これを調整してトリミングします)
						);
				}

err:
				// IBitmapの破棄
				if( NULL != pBitmap ) {
					pBitmap->Release();
				}

				// IFormatConverterの破棄
				if ( NULL != pFormatConverter ) {
					pFormatConverter->Release();
				}

				// IWICBitmapFrameの破棄
				if( NULL != pWICBitmapFrame ) {
					pWICBitmapFrame->Release();
				}

				// IWICBitmapDecoderの破棄
				if( NULL != pWICBitmapDecoder ) {
					pWICBitmapDecoder->Release();
				}
			}

			// 描画終了(Direct2D)
			pRenderTarget->EndDraw();

			// 描画終了
			::EndPaint( hWnd, &tPaintStruct );
		}
		return( FALSE );
	}

	// デフォルト処理呼び出し
	return ::DefWindowProc( hWnd, uMsg, wParam, lParam );
}



実行結果







わびさびサンプルソース

WindowsやHTML5などのプログラムのサンプルコードやフリーソフトを提供します。