共用方式為


如何使用 FilePicker 將影像載入 Direct2D 效果

示範如何使用 Windows::Storage::P ickers::FileOpenPicker 將影像載入 Direct2D 效果 如果您想要讓使用者從 Windows 市集應用程式中的記憶體選取映射檔,建議您使用 FileOpenPicker

您需要瞭解的資訊

技術

必要條件

  • 您需要 ID2D1DeviceContext 物件來建立效果。
  • 您需要 IWICImagingFactory 物件,才能建立 WIC 物件。

指示

步驟 1:開啟檔案選擇器

建立 FileOpenPicker 物件,並設定 ViewModeSuggestedStartLocationFileTypeFilter 以選取影像。 呼叫 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 方法建立 IWICBitmapDecoderDecoder 物件。

    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格式轉換器。

注意

位圖來源效果不會從 SetInput 方法取得輸入,例如許多 Direct2D 效果。 相反地 ,會將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.
}