So laden Sie ein Bild mit dem FilePicker in Direct2D-Effekte

Zeigt, wie Sie Windows::Storage::Pickers::FileOpenPicker verwenden, um ein Bild in Direct2D-Effekte zu laden. Wenn Sie den Benutzer*innen in einer Windows Store-App die Möglichkeit geben möchten, eine gespeicherte Bilddatei auszuwählen, empfehlen wir Ihnen, den FileOpenPicker zu verwenden.

Wichtige Informationen

Technologie

Voraussetzungen

Anweisungen

Schritt 1: Öffnen Sie den File-Picker

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

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

Nachdem PickSingleFileAsync abgeschlossen ist, erhalten Sie einen File-Stream von der IAsyncOperation-Schnittstelle.

Schritt 2: Abrufen eines File-Streams

Deklarieren Sie einen Handler, der nach der Rückkehr des asynchronen Vorgangs des File-Pickers ausgeführt wird. Verwenden Sie die Methode GetResults, um die Datei abzurufen und das File-Stream-Objekt zu erhalten.

    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 Sie den File-Stream

Verwenden Sie die Funktion CreateStreamOverRandomAccessStream, um den File-Stream zu konvertieren. Windows Runtime-APIs repräsentieren Streams über IRandomAccessStream, während WIC IStream verwendet.

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

Hinweis

Um die Funktion CreateStreamOverRandomAccessStream zu verwenden, sollten Sie shcore.h in Ihr Projekt aufnehmen.

 

Schritt 4: Erstellen Sie einen WIC-Decoder, und holen Sie sich den Frame

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

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

Rufen Sie mit der Methode IWICBitmapDecoder::GetFrame den ersten Frame des Bildes vom Decoder ab.

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

Schritt 5: Erstellen Sie einen WIC-Konverter, und initialisieren Sie ihn

Konvertieren Sie das Bild in das BGRA-Farbformat mit WIC. IWICBitmapFrameDecode wird das native Pixelformat des Bildes zurückgeben (so wie JPEGs in GUID_WICPixelFormat24bppBGR gespeichert werden). Um die Leistung von Direct2D zu optimieren, empfehlen wir Ihnen jedoch eine Konvertierung in WICPixelFormat32bppPBGRA.

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

        ComPtr<IWICFormatConverter> converter;
        DX::ThrowIfFailed(
            m_wicFactory->CreateFormatConverter(&converter)
            ); 
    
    
  2. Initialisieren Sie den Formatkonverter zur Verwendung von WICPixelFormat32bppPBGRA, und übergeben Sie das Bitmap-Frame.

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

Die Schnittstelle IWICFormatConverter ist von der Schnittstelle IWICBitmapSource abgeleitet, sodass Sie den Konverter an den Effekt Bitmap-Quelle übergeben können.

Schritt 6: Erstellen Sie einen Effekt, und übergeben Sie eine IWICBitmapSource

Verwenden Sie die Methode CreateEffect, um ein Bitmap Source ID2D1Effect-Objekt unter Verwendung des Direct2D-Gerätekontextes zu erstellen.

Verwenden Sie die Methode ID2D1Effect::SetValue, um die Eigenschaft D2D1_BITMAPSOURCE_PROP_WIC_BITMAP_SOURCE für den WIC-Formatkonverter festzulegen.

Hinweis

Der Bitmap Source Effekt nimmt keinen Input von der SetInput-Methode wie viele Direct2D-Effekte. 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.

Jetzt, da Sie den Bitmap Source-Effekt haben, können Sie ihn als Eingabe für jeden ID2D1Effect verwenden und einen Effekt-Graphen 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.
}