FilePicker를 사용하여 Direct2D 효과에 이미지를 로드하는 방법
Windows::Storage::P ickers::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 개체를 WIC에 전달할 수 있는 IStream으로 변환합니다.
3단계: 파일 스트림 변환
CreateStreamOverRandomAccessStream 함수를 사용하여 파일 스트림을 변환합니다. Windows 런타임 API는 스트림을 나타냅니다.IRandomAccessStream, WIC는 IStream을 사용합니다.
ComPtr<IStream> istream;
DX::ThrowIfFailed(
CreateStreamOverRandomAccessStream(
reinterpret_cast<IUnknown*>(fileStream),
IID_PPV_ARGS(&istream)
)
);
참고 항목
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 인터페이스에서 파생되므로 변환기를 비트맵 소스 효과에 전달할 수 있습니다.
6단계: 효과 만들기 및 IWICBitmapSource 전달
CreateEffect 메서드를 사용하여 Direct2D 디바이스 컨텍스트를 사용하여 비트맵 원본 ID2D1Effect 개체를 만듭니다.
ID2D1Effect::SetValue 메서드를 사용하여 D2D1_BITMAPSOURCE_PROP_WIC_BITMAP_SOURCE 속성을 WIC 형식 변환기로 설정합니다.
참고 항목
비트맵 소스 효과는 많은 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.
}