FilePicker를 사용 하 여 Direct2D 효과에 이미지를 로드 하는 방법How to load an image into Direct2D effects using the FilePicker

Windows:: Storage::P ickers:: FileOpenPicker 를 사용 하 여 Direct2D 효과에 이미지를 로드 하는 방법을 보여 줍니다.Shows how to use the Windows::Storage::Pickers::FileOpenPicker to load an image into Direct2D effects. 사용자가 Windows 스토어 앱의 저장소에서 이미지 파일을 선택할 수 있게 하려면 Fileopenpicker를 사용 하는 것이 좋습니다.If you want to let the user select an image file from storage in a Windows Store app, we recommend that you use the FileOpenPicker.

기억해야 하는 사항What you need to know

기술Technologies

필수 구성 요소Prerequisites

지침Instructions

1 단계: 파일 선택기 열기Step 1: Open the file picker

Fileopenpicker 개체를 만들고 이미지를 선택 하기 위한 ViewMode, SuggestedStartLocationfila 필터 를 설정 합니다.Create a FileOpenPicker object and set the ViewMode, SuggestedStartLocation, and the FileTypeFilter for selecting images. PickSingleFileAsync 메서드를 호출 합니다.Call the PickSingleFileAsync method.

    FileOpenPicker^ openPicker = ref new FileOpenPicker();
    openPicker->ViewMode = PickerViewMode::Thumbnail;
    openPicker->SuggestedStartLocation = PickerLocationId::PicturesLibrary;
    openPicker->FileTypeFilter->Append(".jpg");
    auto pickOperation = openPicker->PickSingleFileAsync();

PickSingleFileAsync 완료 되 면 반환 되는 iasyncoperation 인터페이스에서 파일 스트림을 가져옵니다.After the PickSingleFileAsync completes, you get a file stream from the IAsyncOperation interface it returns.

2 단계: 파일 스트림 가져오기Step 2: Get a file stream

파일 선택 비동기 작업이 반환 된 후에 실행 되도록 완료 처리기를 선언 합니다.Declare a completion handler to run after the file picker async operation returns. GetResults 메서드를 사용 하 여 파일을 검색 하 고 파일 스트림 개체를 가져옵니다.Use the GetResults method to retrieve the file and to get the file stream object.

    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 으로 변환 합니다.In the next step you convert the IRandomAccessStream object to an IStream that you can pass to WIC.

3 단계: 파일 스트림 변환Step 3: Convert the file stream

CreateStreamOverRandomAccessStream 함수를 사용 하 여 파일 스트림을 변환 합니다.Use the CreateStreamOverRandomAccessStream function to convert the file stream. Windows 런타임 Api는 IRandomAccessStream를 사용 하는 스트림을 나타내며, WICIStream을 사용 합니다.Windows Runtime APIs represent streams with IRandomAccessStream, while WIC consumes IStream.

    ComPtr<IStream> istream;
    DX::ThrowIfFailed(
        CreateStreamOverRandomAccessStream(
        reinterpret_cast<IUnknown*>(fileStream),
        IID_PPV_ARGS(&istream)
        )
    );

참고

CreateStreamOverRandomAccessStream 함수를 사용 하려면 프로젝트에 shcore. h 를 포함 해야 합니다.To use the CreateStreamOverRandomAccessStream function, you should include shcore.h in your project.

 

4 단계: WIC 디코더 만들기 및 프레임 가져오기Step 4: Create a WIC decoder and get the frame

IWICImagingFactory:: CreateDecoderFromStream 메서드를 사용 하 여 IWICBitmapDecoder 개체를 만듭니다.Create an IWICBitmapDecoder object using the IWICImagingFactory::CreateDecoderFromStream method.

    ComPtr<IWICBitmapDecoder> decoder;
    DX::ThrowIfFailed(
          m_wicFactory->CreateDecoderFromStream(
                    istream.Get(),
                    nullptr,
                    WICDecodeMetadataCacheOnDemand,
                    &decoder
                    )
          );

IWICBitmapDecoder:: GetFrame 메서드를 사용 하 여 디코더에 이미지의 첫 번째 프레임을 가져옵니다.Get the first frame of the image from the decoder using the IWICBitmapDecoder::GetFrame method.

    ComPtr<IWICBitmapFrameDecode> frame;
    DX::ThrowIfFailed(
        decoder->GetFrame(0, &frame)
        );

5 단계: WIC 변환기 만들기 및 초기화Step 5: Create a WIC converter and initialize

WIC를 사용 하 여 이미지를 BGRA 색 형식으로 변환 합니다.Convert the image to the BGRA color format using WIC. IWICBitmapFrameDecode 는 JPEG가 GUID WICPixelFormat24bppBGR에 저장 된 것 처럼 이미지의 기본 픽셀 형식을 반환 합니다 _ .IWICBitmapFrameDecode will return the native pixel format of the image, like JPEGs are stored in GUID_WICPixelFormat24bppBGR. 그러나 Direct2D을 사용 하는 성능 최적화로 WICPixelFormat32bppPBGRA로 변환 하는 것이 좋습니다.However, as a performance optimization with Direct2D we recommend that you convert to WICPixelFormat32bppPBGRA.

  1. IWICImagingFactory:: CreateFormatConverter 메서드를 사용 하 여 IWICFormatConverter 개체를 만듭니다.Create a IWICFormatConverter object using the IWICImagingFactory::CreateFormatConverter method.

        ComPtr<IWICFormatConverter> converter;
        DX::ThrowIfFailed(
            m_wicFactory->CreateFormatConverter(&converter)
            ); 
    
    
  2. WICPixelFormat32bppPBGRA를 사용 하 고 비트맵 프레임을 전달 하려면 서식 변환기를 초기화 합니다.Initialize the format converter to use the WICPixelFormat32bppPBGRA and pass in the bitmap frame.

       DX::ThrowIfFailed(
            converter->Initialize(
                frame.Get(),
                GUID_WICPixelFormat32bppPBGRA,
                WICBitmapDitherTypeNone,
                nullptr,
                0.0f,
                WICBitmapPaletteTypeCustom  // premultiplied BGRA has no paletting, so this is ignored
                )
            );
    

IWICFormatConverter 인터페이스는 IWICBitmapSource 인터페이스에서 파생 되므로 변환기를 비트맵 소스 효과에 전달할 수 있습니다.The IWICFormatConverter interface is derived from the IWICBitmapSource interface, so you can pass the converter to the bitmap source effect.

6 단계: 효과 만들기 및 IWICBitmapSource 전달Step 6: Create effect and pass in an IWICBitmapSource

Createeffect 메서드를 사용 하 여 Direct2D 장치 컨텍스트를 사용 하 여 비트맵 원본 ID2D1Effect 개체를 만듭니다.Use the CreateEffect method to create a bitmap source ID2D1Effect object using the Direct2D device context.

ID2D1Effect:: SetValue 메서드를 사용 하 여 D2D1 _ BITMAPSOURCE _ PROP _ wic _ 비트맵 _ 원본 속성을 wic 형식 변환기로 설정 합니다.Use the ID2D1Effect::SetValue method to set the D2D1_BITMAPSOURCE_PROP_WIC_BITMAP_SOURCE property to the WIC format converter.

참고

비트맵 원본 효과는 많은 Direct2D 효과와 같은 SetInput 메서드의 입력을 사용 하지 않습니다.The bitmap source effect doesn't take an input from the SetInput method like many Direct2D effects. 대신 IWICBitmapSource 개체가 속성으로 지정 됩니다.Instead, the IWICBitmapSource object is specified as a property.

 

    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 에 대 한 입력으로 사용 하 여 효과 그래프를 만들 수 있습니다.Now that you have the bitmap source effect, you can use it as input to any ID2D1Effect and create an effect graph.

전체 예제Complete example

이 예제에 대 한 전체 코드는 다음과 같습니다.Here is the full code for this example.

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.
}