Laden eines Bilds in Direct2D-Effekte mithilfe des FilePicker

Zeigt, wie Sie die Windows::Storage::P ickers::FileOpenPicker verwenden, um ein Bild in Direct2D-Effekte zu laden. Wenn Sie dem Benutzer eine Bilddatei aus dem Speicher in einer Windows Store-App auswählen möchten, empfehlen wir, die DateiOpenPicker zu verwenden.

Wichtige Informationen

Technologien

Voraussetzungen

Instructions

Schritt 1: Öffnen der Dateiauswahl

Erstellen Sie ein FileOpenPicker-Objekt , und legen Sie den ViewMode, SuggestedStartLocation und den FileTypeFilter für die Auswahl von Bildern fest. Rufen Sie die PickSingleFileAsync-Methode auf.

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

Nachdem die PickSingleFileAsync abgeschlossen wurde, erhalten Sie einen Dateistrom aus der IAsyncOperation-Schnittstelle , die zurückgegeben wird.

Schritt 2: Abrufen eines Dateidatenstroms

Deklarieren Sie einen Abschlusshandler, der ausgeführt werden soll, nachdem der Dateiauswahl-async-Vorgang zurückgegeben wird. Verwenden Sie die GetResults-Methode , um die Datei abzurufen und das Dateidatenstromobjekt abzurufen.

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

Im nächsten Schritt konvertieren Sie das IRandomAccessStream-Objekt in einen IStream , den Sie an WIC übergeben können.

Schritt 3: Konvertieren des Dateidatenstroms

Verwenden Sie die CreateStreamOverRandomAccessStream-Funktion , um den Dateidatenstrom zu konvertieren. Windows-Runtime APIs stellen Datenströme mit IRandomAccessStream dar, während WICIStream verwendet.

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

Hinweis

Um die CreateStreamOverRandomAccessStream-Funktion zu verwenden, sollten Sie shcore.h in Ihr Projekt einschließen.

 

Schritt 4: Erstellen eines WIC-Decoders und Abrufen des Frames

Erstellen Sie ein IWICBitmapDecoder-Objekt mithilfe der IWICImagingFactory::CreateDecoderFromStream-Methode .

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

Rufen Sie den ersten Frame des Bilds aus dem Decoder mithilfe der IWICBitmapDecoder::GetFrame-Methode ab.

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

Schritt 5: Erstellen eines WIC-Konverters und Initialisieren

Konvertieren Sie das Bild mithilfe von WIC in das BGRA-Farbformat. IWICBitmapFrameDecode gibt das native Pixelformat des Bilds zurück, z. B. JPEGs werden in GUID_WICPixelFormat24bppBGR gespeichert. Als Leistungsoptimierung mit Direct2D empfehlen wir jedoch, dass Sie in WICPixelFormat32bppPBGRA konvertieren.

  1. Erstellen Sie ein IWICFormatConverter-Objekt mithilfe der IWICImagingFactory::CreateFormatConverter-Methode .

        ComPtr<IWICFormatConverter> converter;
        DX::ThrowIfFailed(
            m_wicFactory->CreateFormatConverter(&converter)
            ); 
    
    
  2. Initialisieren Sie den Formatkonverter, um den WICPixelFormat32bppPBGRA zu verwenden und im Bitmapframe zu übergeben.

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

Die IWICFormatConverter-Schnittstelle wird aus der IWICBitmapSource-Schnittstelle abgeleitet, sodass Sie den Konverter an den Bitmapquelleeffekt übergeben können.

Schritt 6: Erstellen von Effekten und Übergeben in einer IWICBitmapSource

Verwenden Sie die CreateEffect-Methode, um ein BitmapsourceID2D1Effect-Objekt mithilfe des Direct2Ddevice-Kontexts zu erstellen.

Verwenden Sie die ID2D1Effect::SetValue-Methode, um die D2D1_BITMAPSOURCE_PROP_WIC_BITMAP_SOURCE-Eigenschaft auf den WICformat-Konverter festzulegen.

Hinweis

Der Bitmapquelleeffekt nimmt keine Eingabe aus der SetInput-Methode wie viele Direct2D-Effekte ab. Stattdessen wird das IWICBitmapSource-Objekt als Eigenschaft angegeben.

 

    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.

Nachdem Sie nun über den Bitmapquelleeffekt verfügen, können Sie sie als Eingabe für alle ID2D1Effect verwenden und ein Effektdiagramm erstellen.

Vollständiges Beispiel

Hier ist der vollständige Code für dieses Beispiel.

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