Laden eines Bilds in Direct2D-Effekte mit dem FilePicker

Zeigt, wie Sie windows ::Storage::P ickers::FileOpenPicker verwenden, um ein Bild in Direct2D-Effekte zu laden. Wenn Sie dem Benutzer erlauben möchten, eine Bilddatei aus dem Speicher in einer Windows Store-App auszuwählen, wird empfohlen, fileOpenPicker zu verwenden.

Wichtige Informationen

Technologien

Voraussetzungen

Anweisungen

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 Dateidatenstrom von der IAsyncOperation-Schnittstelle , die zurückgegeben wird.

Schritt 2: Abrufen eines Dateidatenstroms

Deklarieren Sie einen Vervollständigungshandler, der ausgeführt werden soll, nachdem der asynchrone Vorgang der Dateiauswahl zurückgegeben wurde. Verwenden Sie die GetResults-Methode , um die Datei 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 Dateidatenstroms

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

    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 mithilfe der IWICImagingFactory::CreateDecoderFromStream-Methode ein IWICBitmapDecoder-Objekt.

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

Rufen Sie den ersten Frame des Bilds mithilfe der IWICBitmapDecoder::GetFrame-Methode vom Decoder 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, wie JPEGs in GUID_WICPixelFormat24bppBGR gespeichert werden. Als Leistungsoptimierung mit Direct2D wird jedoch empfohlen, dass Sie in WICPixelFormat32bppPBGRA 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 den 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 von der IWICBitmapSource-Schnittstelle abgeleitet, sodass Sie den Konverter an den Bitmapquelleffekt übergeben können.

Schritt 6: Erstellen eines Effekts und Übergeben einer IWICBitmapSource

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

Verwenden Sie die ID2D1Effect::SetValue-Methode, um die eigenschaft D2D1_BITMAPSOURCE_PROP_WIC_BITMAP_SOURCE auf den WIC-Formatkonverter festzulegen.

Hinweis

Der Bitmap-Quelleffekt nimmt keine Eingabe aus 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 jeden 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.
}