Condividi tramite


Come caricare un'immagine in effetti Direct2D usando FilePicker

Illustra come usare Windows::Storage::P ickers::FileOpenPicker per caricare un'immagine in effetti Direct2D. Se vuoi consentire all'utente di selezionare un file di immagine dalla risorsa di archiviazione in un'app di Windows Store, ti consigliamo di usare FileOpenPicker.

Informazioni importanti

Tecnologie

Prerequisiti

Istruzioni

Passaggio 1: Aprire la selezione file

Creare un oggetto FileOpenPicker e impostare ViewMode, SuggestedStartLocation e FileTypeFilter per la selezione delle immagini. Chiamare il metodo PickSingleFileAsync.

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

Al termine dell'operazione PickSingleFileAsync, si ottiene un flusso di file dall'interfaccia IAsyncOperation restituita.

Passaggio 2: Ottenere un flusso di file

Dichiarare un gestore di completamento da eseguire dopo la restituzione dell'operazione asincrona di selezione file. Utilizzare il metodo GetResults per recuperare il file e ottenere l'oggetto flusso di 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);
                             });
        }
    });

Nel passaggio successivo si converte l'oggetto IRandomAccessStream in un IStream che è possibile passare a WIC.

Passaggio 3: Convertire il flusso di file

Usare la funzione CreateStreamOverRandomAccessStream per convertire il flusso di file. Le API di Windows Runtime rappresentano i flussi con IRandomAccessStream, mentre WIC usa IStream.

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

Nota

Per usare la funzione CreateStreamOverRandomAccessStream , è necessario includere shcore.h nel progetto.

 

Passaggio 4: Creare un decodificatore WIC e ottenere il fotogramma

Creare un oggetto IWICBitmapDecoder usando il metodo IWICImagingFactory::CreateDecoderFromStream.

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

Ottenere il primo fotogramma dell'immagine dal decodificatore usando il metodo IWICBitmapDecoder::GetFrame .

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

Passaggio 5: Creare un convertitore WIC e inizializzare

Convertire l'immagine nel formato di colore BGRA usando WIC. IWICBitmapFrameDecode restituirà il formato pixel nativo dell'immagine, come i JPEG vengono archiviati in GUID_WICPixelFormat24bppBGR. Tuttavia, come ottimizzazione delle prestazioni con Direct2D, ti consigliamo di convertire in WICPixelFormat32bppPGRA.

  1. Creare un oggetto IWICFormatConverter usando il metodo IWICImagingFactory::CreateFormatConverter.

        ComPtr<IWICFormatConverter> converter;
        DX::ThrowIfFailed(
            m_wicFactory->CreateFormatConverter(&converter)
            ); 
    
    
  2. Inizializzare il convertitore di formato per usare WICPixelFormat32bppPBGRA e passare il frame bitmap.

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

L'interfaccia IWICFormatConverter è derivata dall'interfaccia IWICBitmapSource, quindi è possibile passare il convertitore all'effetto origine bitmap.

Passaggio 6: Creare un effetto e passare un oggetto IWICBitmapSource

Utilizzare il metodo CreateEffect per creare un oggetto id2D1Effect dell'origine bitmap usando il contesto di dispositivo Direct2D.

Utilizzare il metodo ID2D1Effect::SetValue per impostare la proprietà D2D1_BITMAPSOURCE_PROP_WIC_BITMAP_SOURCE sul convertitore di formati WIC.

Nota

L'effetto origine bitmap non accetta un input dal metodo SetInput come molti effetti Direct2D. L'oggetto IWICBitmapSource viene invece specificato come proprietà.

 

    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.

Ora che si ha l'effetto di origine bitmap, è possibile usarlo come input per qualsiasi ID2D1Effect e creare un grafico degli effetti.

Esempio completo

Di seguito è riportato il codice completo per questo esempio.

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