読者です 読者をやめる 読者になる 読者になる

がりらぼ

WindowsRuntimeの応援ブログ

DirectXによるWindowsストアアプリゲーム開発入門vol.5 画像を描画する

プロジェクトファイルをダウンロードして
TestDirectX_5_DrawBitmapディレクトリ内のソリューションを開いて実行してください。
garicchi/DirectXSample · GitHub

DirectXのロゴが表示されます。
f:id:garicchi:20131219113617p:plain

RendererBase.hを見てみましょう。

// Bitmapが入るリソース
Microsoft::WRL::ComPtr<ID2D1Bitmap>    m_bitmap;

グローバル変数として存在するのはBitmapデータが格納されるID2D1Bitmapインターフェースのインスタンスのみです。

RendererBase.cppを見ます。
CreateDeviceDependentResourcesメソッドがとてつもなく長いです。
Bitmapを確保するのが、いかに大変かがわかります。
少しずつ見ていきましょう。

まず、Bitmapを確保するまでに必要な変数は、
Bitmapデータを格納するID2D1Bitmapインターフェースのインスタンス
IWICBitmapDecorderインターフェースのデコーダ、
IWICBitmapFrameDecodeインターフェースのインスタンスの3つが最低でも必要となります。
まずは、PackageクラスのCurrentプロパティ内のInstalledLocationから、アプリがインストールしているディレクトリを取得します。ディレクトリ区切り文字「\\」を加えて、
画像ファイルの相対パスを指定します。これらはStringクラスのConcatメソッドで結合します。
この場合、プロジェクトファイル→Assetsディレクトリ→sample.pngを参照しています。

//アプリがインストールされた場所を指す
auto location = Package::Current->InstalledLocation;
//ディレクトリ区切り文字「\\」を足す
String^ path = String::Concat(location->Path, "\\");
//ファイル名を相対パスで足す
path = String::Concat(path, "Assets/sample.png");

これでファイルパスを取得することができました。

ファイルパスが取得できたらIWICImagingFactory2インターフェースのCreateDecorderFromFilenameメソッドでBitmapDecorderのインスタンスを初期化します。

//BitmapDecorder
ComPtr<IWICBitmapDecoder> wicBitmapDecoder;
	
//BitmapDecorderを作る(ファイルパスを指定)
m_deviceResources->GetWicImagingFactory()->CreateDecoderFromFilename(
	path->Data(),
	nullptr,
	GENERIC_READ,
	WICDecodeMetadataCacheOnDemand,
	&wicBitmapDecoder
	);

次に、生成したBitmapDecorderのGetFrameメソッドによってIWICBitmapFrameDecodeのインスタンスであるBitmapFrameを生成しています。

//BitmapFrame
	ComPtr<IWICBitmapFrameDecode> wicBitmapFrame;
	
	//BitmapDecorderからBitmapFrameを作る
	wicBitmapDecoder->GetFrame(0, &wicBitmapFrame);

続いて、ID2D1DeviceresourcesのGetWicImagingFactoryメソッドでWicImagingFactoryを取得し、CreateFormatConverterメソッドによってWicFormatConverterを生成します。
その後、WicFormatConverterのInitializeメソッドを呼び出してFormatConverterをイニシャライズします。

最後に、dpiを定義し、FormatConverterのGetResolutionメソッドでdpiを取得しています。

//FormatConverter
	ComPtr<IWICFormatConverter> wicFormatConverter;
	
	//WicImaginfFactoryからFormatConverterを作る
	m_deviceResources->GetWicImagingFactory()->CreateFormatConverter(&wicFormatConverter);

	//FormatConverterをイニシャライズ(BitmapFrameを使う)
	wicFormatConverter->Initialize(
		wicBitmapFrame.Get(),
		GUID_WICPixelFormat32bppPBGRA,
		WICBitmapDitherTypeNone,
		nullptr,
		0.0,
		WICBitmapPaletteTypeCustom  // The BGRA format has no palette so this value is ignored.
		);
		

	double dpiX = 96.0f;
	double dpiY = 96.0f;
	
	//FormatConverterからdpiを取得
	wicFormatConverter->GetResolution(&dpiX, &dpiY);

最後にID2D1DeviceContextのCreateBitmapFromWicBitmapによって、ID2D1Bitmapのインスタンスを生成します。

//ID2D1Bitmapリソースを生成(FormatConverterから)
	m_deviceResources->GetD2DDeviceContext()->CreateBitmapFromWicBitmap(
		wicFormatConverter.Get(),
		BitmapProperties(
		PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
		static_cast<float>(dpiX),
		static_cast<float>(dpiY)
		),
		&m_bitmap
		);

ここまでやって、やっと画像をロードできました。

画像のロードが完了したらあとは簡単です。
ID2D1DeviceContextインターフェースのDrawBitmapメソッドにBitmapを渡せば描画が可能となっています。

//Bitmapを描画
context->DrawBitmap(m_bitmap.Get(),&RectF(100,100,200,200),1.0,D2D1_INTERPOLATION_MODE_LINEAR,0);