Bagikan melalui


Cara memuat gambar ke efek Direct2D menggunakan FilePicker

Memperlihatkan cara menggunakan Windows::Storage::P ickers::FileOpenPicker untuk memuat gambar ke efek Direct2D. Jika Anda ingin membiarkan pengguna memilih file gambar dari penyimpanan di aplikasi Bursa Windows, kami sarankan Anda menggunakan FileOpenPicker.

Apa yang perlu Anda ketahui

Teknologi

Prasyarat

Petunjuk

Langkah 1: Buka pemilih file

Buat objek FileOpenPicker dan atur ViewMode, SuggestedStartLocation, dan FileTypeFilter untuk memilih gambar. Panggil metode PickSingleFileAsync .

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

Setelah PickSingleFileAsync selesai, Anda mendapatkan aliran file dari antarmuka IAsyncOperation yang dikembalikannya.

Langkah 2: Dapatkan aliran file

Nyatakan handler penyelesaian untuk dijalankan setelah operasi asinkron pemilih file kembali. Gunakan metode GetResults untuk mengambil file dan untuk mendapatkan objek aliran file.

    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);
                             });
        }
    });

Pada langkah berikutnya Anda mengonversi objek IRandomAccessStream ke IStream yang dapat Anda teruskan ke WIC.

Langkah 3: Mengonversi aliran file

Gunakan fungsi CreateStreamOverRandomAccessStream untuk mengonversi aliran file. API Runtime Windows mewakili aliran dengan IRandomAccessStream, sementara WIC mengonsumsi IStream.

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

Catatan

Untuk menggunakan fungsi CreateStreamOverRandomAccessStream , Anda harus menyertakan shcore.h dalam proyek Anda.

 

Langkah 4: Buat dekoder WIC dan dapatkan bingkai

Buat objek IWICBitmapDecoder menggunakan metode IWICImagingFactory::CreateDecoderFromStream .

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

Dapatkan bingkai pertama gambar dari dekoder menggunakan metode IWICBitmapDecoder::GetFrame .

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

Langkah 5: Buat konverter WIC dan inisialisasi

Konversikan gambar ke format warna BGRA menggunakan WIC. IWICBitmapFrameDecode akan mengembalikan format piksel asli gambar, seperti JPEG disimpan dalam GUID_WICPixelFormat24bppBGR. Namun, sebagai pengoptimalan performa dengan Direct2D kami sarankan Anda mengonversi ke WICPixelFormat32bppPBGRA.

  1. Buat objek IWICFormatConverter menggunakan metode IWICImagingFactory::CreateFormatConverter .

        ComPtr<IWICFormatConverter> converter;
        DX::ThrowIfFailed(
            m_wicFactory->CreateFormatConverter(&converter)
            ); 
    
    
  2. Inisialisasi pengonversi format untuk menggunakan WICPixelFormat32bppPBGRA dan teruskan dalam bingkai bitmap.

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

Antarmuka IWICFormatConverter berasal dari antarmuka IWICBitmapSource , sehingga Anda dapat meneruskan pengonversi ke efek sumber bitmap .

Langkah 6: Membuat efek dan meneruskan IWICBitmapSource

Gunakan metode CreateEffect untuk membuat objek ID2D1Effectsumber bitmap menggunakan konteks perangkatDirect2D.

Gunakan metode ID2D1Effect::SetValue untuk mengatur properti D2D1_BITMAPSOURCE_PROP_WIC_BITMAP_SOURCE ke pengonversi formatWIC.

Catatan

Efek sumber bitmap tidak mengambil input dari metode SetInput seperti banyak efek Direct2D. Sebagai gantinya, objek IWICBitmapSource ditentukan sebagai properti .

 

    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.

Sekarang setelah Anda memiliki efek sumber bitmap , Anda dapat menggunakannya sebagai input ke ID2D1Effect dan membuat grafik efek.

Contoh lengkap

Berikut adalah kode lengkap untuk contoh ini.

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