Compartilhar via


Como carregar uma imagem em Direct2D efeitos usando o FilePicker

Mostra como usar o Windows::Storage::P ickers::FileOpenPicker para carregar uma imagem em Direct2D efeitos. Se você quiser permitir que o usuário selecione um arquivo de imagem do armazenamento em um aplicativo da Windows Store, recomendamos que você use o FileOpenPicker.

O que você precisa saber

Tecnologias

Pré-requisitos

Instruções

Etapa 1: Abrir o seletor de arquivos

Crie um objeto FileOpenPicker e defina ViewMode, SuggestedStartLocation e FileTypeFilter para selecionar imagens. Chame o método PickSingleFileAsync .

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

Após a conclusão de PickSingleFileAsync , você obtém um fluxo de arquivos da interface IAsyncOperation que ele retorna.

Etapa 2: Obter um fluxo de arquivos

Declare um manipulador de conclusão a ser executado após o retorno da operação assíncrona do seletor de arquivos. Use o método GetResults para recuperar o arquivo e obter o objeto de fluxo de arquivos.

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

Na próxima etapa, você converte o objeto IRandomAccessStream em um IStream que você pode passar para o WIC.

Etapa 3: Converter o fluxo de arquivos

Use a função CreateStreamOverRandomAccessStream para converter o fluxo de arquivos. Windows Runtime APIs representam fluxos com IRandomAccessStream, enquanto o WIC consome IStream.

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

Observação

Para usar a função CreateStreamOverRandomAccessStream , você deve incluir shcore.h em seu projeto.

 

Etapa 4: Criar um decodificador WIC e obter o quadro

Crie um objeto IWICBitmapDecoder usando o método IWICImagingFactory::CreateDecoderFromStream .

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

Obtenha o primeiro quadro da imagem do decodificador usando o método IWICBitmapDecoder::GetFrame .

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

Etapa 5: Criar um conversor WIC e inicializar

Converta a imagem no formato de cor BGRA usando WIC. IWICBitmapFrameDecode retornará o formato de pixel nativo da imagem, como JPEGs são armazenados em GUID_WICPixelFormat24bppBGR. No entanto, como uma otimização de desempenho com Direct2D recomendamos que você converta para WICPixelFormat32bppPBGRA.

  1. Crie um objeto IWICFormatConverter usando o método IWICImagingFactory::CreateFormatConverter .

        ComPtr<IWICFormatConverter> converter;
        DX::ThrowIfFailed(
            m_wicFactory->CreateFormatConverter(&converter)
            ); 
    
    
  2. Inicialize o conversor de formato para usar o WICPixelFormat32bppPBGRA e passe o quadro de bitmap.

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

A interface IWICFormatConverter é derivada da interface IWICBitmapSource , para que você possa passar o conversor para o efeito de origem do bitmap .

Etapa 6: Criar efeito e passar um IWICBitmapSource

Use o método CreateEffect para criar um objeto ID2D1Effect de origem de bitmap usando o contexto Direct2Ddevice.

Use o método ID2D1Effect::SetValue para definir a propriedade D2D1_BITMAPSOURCE_PROP_WIC_BITMAP_SOURCE para o conversor de formatoWIC.

Observação

O efeito de origem do bitmap não usa uma entrada do método SetInput, como muitos efeitos Direct2D. Em vez disso, o objeto IWICBitmapSource é especificado como uma propriedade.

 

    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.

Agora que você tem o efeito de origem do bitmap , pode usá-lo como entrada para qualquer ID2D1Effect e criar um grafo de efeito.

Exemplo completo

Este é o código completo para este exemplo.

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