FilePicker を使用して Direct2D 効果に画像を読み込む方法
Windows::Storage::Pickers::FileOpenPicker を使用して、イメージを Direct2D 効果に読み込む方法を示します。 ユーザーが Windows ストア アプリのストレージからイメージ ファイルを選択できるようにする場合は、FileOpenPicker を使用することをお勧めします。
知っておくべきこと
テクノロジ
前提条件
- 効果を作成するには、ID2D1DeviceContext オブジェクトが必要です。
- WIC オブジェクトを作成するには、IWICImagingFactory オブジェクトが必要です。
手順
手順 1: ファイル ピッカーを開く
FileOpenPicker オブジェクトを作成し、イメージを選択するための ViewMode、SuggestedStartLocation、および FileTypeFilter を設定します。 PickSingleFileAsync メソッドを呼び出します。
FileOpenPicker^ openPicker = ref new FileOpenPicker();
openPicker->ViewMode = PickerViewMode::Thumbnail;
openPicker->SuggestedStartLocation = PickerLocationId::PicturesLibrary;
openPicker->FileTypeFilter->Append(".jpg");
auto pickOperation = openPicker->PickSingleFileAsync();
PickSingleFileAsync が完了すると、返される IAsyncOperation インターフェイスからファイル ストリームが取得されます。
手順 2: ファイル ストリームを取得する
ファイル ピッカーの非同期操作が返された後に実行する完了ハンドラーを宣言します。 GetResults メソッドを使用して、ファイルを取得し、ファイル ストリーム オブジェクトを取得します。
pickOperation->Completed = ref new AsyncOperationCompletedHandler<StorageFile^>(
[=](IAsyncOperation<StorageFile^> ^operation, AsyncStatus status)
{
auto file = operation->GetResults();
if (file) // If file == nullptr, the user did not select a file.
{
auto openOperation = file->OpenAsync(FileAccessMode::Read);
openOperation->Completed = ref new
AsyncOperationCompletedHandler<IRandomAccessStream^>(
[=](IAsyncOperation<IRandomAccessStream^> ^operation, AsyncStatus status)
{
auto fileStream = operation->GetResults();
// Pass IRandomAccessStream^ into DirectXApp for decoding/processing.
OpenFile(fileStream);
});
}
});
次の手順では、IRandomAccessStream オブジェクトを IStream に変換し、WIC に渡すことができます。
手順 3: ファイル ストリームを変換する
CreateStreamOverRandomAccessStream 関数を使用して、ファイル ストリームを変換します。 Windows ランタイム API は、IRandomAccessStream を含むストリームを表します。また、WIC は IStream を使用します。
ComPtr<IStream> istream;
DX::ThrowIfFailed(
CreateStreamOverRandomAccessStream(
reinterpret_cast<IUnknown*>(fileStream),
IID_PPV_ARGS(&istream)
)
);
Note
CreateStreamOverRandomAccessStream 関数を使用するには、プロジェクトに shcore.h を含める必要があります。
手順 4: WIC デコーダーを作成してフレームを取得する
IWICImagingFactory::CreateDecoderFromStream メソッドを使用して、IWICBitmapDecoder オブジェクトを作成します。
ComPtr<IWICBitmapDecoder> decoder;
DX::ThrowIfFailed(
m_wicFactory->CreateDecoderFromStream(
istream.Get(),
nullptr,
WICDecodeMetadataCacheOnDemand,
&decoder
)
);
IWICBitmapDecoder::GetFrame メソッドを使用して、デコーダーからイメージの最初のフレームを取得します。
ComPtr<IWICBitmapFrameDecode> frame;
DX::ThrowIfFailed(
decoder->GetFrame(0, &frame)
);
手順 5: WIC コンバーターを作成して初期化する
WIC を使用して、イメージを BGRA カラー形式に変換します。 IWICBitmapFrameDecode は、JPEG が GUID_WICPixelFormat24bppBGR に保存されるのと同様に、イメージのネイティブ ピクセル形式を返します。 ただし、Direct2D を使用したパフォーマンスの最適化として、WICPixelFormat32bppPBGRA に変換することをお勧めします。
IWICImagingFactory::CreateFormatConverter メソッドを使用して、IWICFormatConverter オブジェクトを作成します。
ComPtr<IWICFormatConverter> converter; DX::ThrowIfFailed( m_wicFactory->CreateFormatConverter(&converter) );
WICPixelFormat32bppPBGRA を使用してビットマップ フレームを渡すように、フォーマット コンバーターを初期化します。
DX::ThrowIfFailed( converter->Initialize( frame.Get(), GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, nullptr, 0.0f, WICBitmapPaletteTypeCustom // premultiplied BGRA has no paletting, so this is ignored ) );
IWICFormatConverter インターフェイスは、IWICBitmapSource インターフェイスから派生するため、コンバーターを bitmap ソース効果に渡すことができます。
手順 6: 効果を作成して IWICBitmapSource に渡す
CreateEffect メソッドを使用し、Direct2D デバイス コンテキスト を使用して bitmap source ID2D1Effect オブジェクトを作成します。
ID2D1Effect::SetValue メソッドを使用して、D2D1_BITMAPSOURCE_PROP_WIC_BITMAP_SOURCE プロパティを WIC フォーマット コンバーターに設定します。
Note
ビットマップ ソース効果は、多くの Direct2D 効果のような SetInput メソッドからの入力は受け取りません。 代わりに、IWICBitmapSource オブジェクトがプロパティとして指定されます。
ComPtr<ID2D1Effect> bitmapSourceEffect;
DX::ThrowIfFailed(
m_d2dContext->CreateEffect(CLSID_D2D1BitmapSource, &bitmapSourceEffect)
);
DX::ThrowIfFailed(
bitmapSourceEffect->SetValue(D2D1_BITMAPSOURCE_PROP_WIC_BITMAP_SOURCE, converter.Get())
);
// Insert code using the bitmap source in an effect graph.
これで、ビットマップソース効果が得られ、それを任意の ID2D1Effect への入力として使用して効果グラフを作成できます。
コード例全体
この例の完全なコードは次のとおりです。
ComPtr<ID2D1Effect> bitmapSourceEffect;
void OpenFilePicker()
{
FileOpenPicker^ openPicker = ref new FileOpenPicker();
openPicker->ViewMode = PickerViewMode::Thumbnail;
openPicker->SuggestedStartLocation = PickerLocationId::PicturesLibrary;
openPicker->FileTypeFilter->Append(".jpg");
auto pickOperation = openPicker->PickSingleFileAsync();
pickOperation->Completed = ref new AsyncOperationCompletedHandler<StorageFile^>(
[=](IAsyncOperation<StorageFile^> ^operation, AsyncStatus status)
{
auto file = operation->GetResults();
if (file)
{
auto openOperation = file->OpenAsync(FileAccessMode::Read);
openOperation->Completed = ref new
AsyncOperationCompletedHandler<IRandomAccessStream^>(
[=](IAsyncOperation<IRandomAccessStream^> ^operation, AsyncStatus status)
{
auto fileStream = operation->GetResults();
// Pass IRandomAccessStream^ into DirectXApp for decoding/processing.
OpenFile(fileStream);
});
}
});
}
void OpenFile(Windows::Storage::Streams::IRandomAccessStream^ fileStream)
{
ComPtr<IStream> istream;
DX::ThrowIfFailed(
CreateStreamOverRandomAccessStream(
reinterpret_cast<IUnknown*>(fileStream),
IID_PPV_ARGS(&istream)
)
);
ComPtr<IWICBitmapDecoder> decoder;
DX::ThrowIfFailed(
m_wicFactory->CreateDecoderFromStream(
istream.Get(),
nullptr,
WICDecodeMetadataCacheOnDemand,
&decoder
)
);
ComPtr<IWICBitmapFrameDecode> frame;
DX::ThrowIfFailed(
decoder->GetFrame(0, &frame)
);
ComPtr<IWICFormatConverter> converter;
DX::ThrowIfFailed(
m_wicFactory->CreateFormatConverter(&converter)
);
DX::ThrowIfFailed(
converter->Initialize(
frame.Get(),
GUID_WICPixelFormat32bppPBGRA,
WICBitmapDitherTypeNone,
nullptr,
0.0f,
WICBitmapPaletteTypeCustom // premultiplied BGRA has no paletting, so this is ignored
)
);
ComPtr<ID2D1Effect> bitmapSourceEffect;
DX::ThrowIfFailed(
m_d2dContext->CreateEffect(CLSID_D2D1BitmapSource, &bitmapSourceEffect)
);
DX::ThrowIfFailed(
bitmapSourceEffect->SetValue(D2D1_BITMAPSOURCE_PROP_WIC_BITMAP_SOURCE, converter.Get())
);
// Insert code using the bitmap source in an effect graph.
}