Laden eines Bilds in Direct2D-Effekte mit filepicker

Zeigt, wie sie Windows::Storage::P ickers::FileOpenPicker verwenden, um ein Bild in Direct2D-Effekte zu laden. Wenn Sie dem Benutzer die Auswahl einer Bilddatei aus dem Speicher in einer Windows Store-App gestatten möchten, wird die Verwendung von FileOpenPicker empfohlen.

Wichtige Informationen

Technologien

Voraussetzungen

Instructions

Schritt 1: Öffnen der Dateiauswahl

Erstellen Sie ein FileOpenPicker-Objekt, und legen Sie ViewMode, SuggestedStartLocation und FileTypeFilter zum Auswählen 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();

Nach Abschluss von PickSingleFileAsync erhalten Sie einen Dateistream von der IAsyncOperation-Schnittstelle, die zurückgegeben wird.

Schritt 2: Herunterladen eines Dateistreams

Deklarieren Sie einen Abschlusshandler, der ausgeführt wird, nachdem der asynchrone Dateiauswahlvorgang zurückgegeben wurde. Verwenden Sie die GetResults-Methode, um die Datei abzurufen und das Dateistreamobjekt 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 Dateistreams

Verwenden Sie die CreateStreamOverRandomAccessStream-Funktion, um den Dateistream zu konvertieren. Windows Laufzeit-APIs stellen Streams mit IRandomAccessStream dar, während WIC IStream 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 einfassen.

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

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

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

Verwenden Sie die IWICBitmapDecoder::GetFrame-Methode, um den ersten Frame des Bilds aus dem Decoder zu erhalten.

    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, wie JPEGs in GUID _ WICPixelFormat24bppBGR gespeichert werden. Als Leistungsoptimierung mit Direct2D wird jedoch empfohlen, in WICPixelFormat32bppPBGRA zu konvertieren.

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

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

       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 von der IWICBitmapSource-Schnittstelle abgeleitet, sodass Sie den Konverter an den Bitmapquelleneffekt übergeben können.

Schritt 6: Erstellen eines Effekts und Übergeben einer IWICBitmapSource

Verwenden Sie die CreateEffect-Methode, um mithilfe des Direct2D-Gerätekontexts ein Bitmapquelle-ID2D1Effect-Objekt zu erstellen.

Verwenden Sie die ID2D1Effect::SetValue-Methode, um die Eigenschaft D2D1 _ BITMAPSOURCE PROP _ _ WIC BITMAP _ _ SOURCE auf den WIC-Formatkonverter zu setzen.

Hinweis

Der Bitmapquelleneffekt nimmt keine Eingabe von der SetInput-Methode wie viele Direct2D-Effekte an. 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 Bitmapquelleneffekt verfügen, können Sie ihn als Eingabe für einen beliebigen 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.
}