FilePicker를 사용하여 Direct2D 효과에 이미지를 로드하는 방법

Windows::Storage::P ickers::FileOpenPicker를 사용하여 Direct2D 효과에 이미지를 로드하는 방법을 보여 줍니다. 사용자가 Windows 스토어 앱의 스토리지에서 이미지 파일을 선택하도록 하려면 FileOpenPicker를 사용하는 것이 좋습니다.

알아야 하는 작업

기술

사전 요구 사항

지침

1단계: 파일 선택기 열기

FileOpenPicker 개체를 만들고 이미지를 선택하기 위해 ViewMode, SuggestedStartLocationFileTypeFilter를 설정합니다. 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을 사용하는 스트림을 나타내고 WICIStream을 사용합니다.

    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로 변환하는 것이 좋습니다.

  1. IWICImagingFactory::CreateFormatConverter 메서드를 사용하여 IWICFormatConverter 개체를 만듭니다.

        ComPtr<IWICFormatConverter> converter;
        DX::ThrowIfFailed(
            m_wicFactory->CreateFormatConverter(&converter)
            ); 
    
    
  2. 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.
}