Carga de una imagen en efectos de Direct2D mediante FilePicker

Muestra cómo usar el Windows::Storage::P ickers::FileOpenPicker para cargar una imagen en efectos de Direct2D. Si desea permitir que el usuario seleccione un archivo de imagen del almacenamiento en una aplicación de Windows Store, se recomienda usar FileOpenPicker.

Lo que necesita saber

Tecnologías

Requisitos previos

Instructions

Paso 1: Abrir el selector de archivos

Cree un objeto FileOpenPicker y establezca ViewMode, SuggestedStartLocation y FileTypeFilter para seleccionar imágenes. Llame al método PickSingleFileAsync.

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

Una vez completado PickSingleFileAsync, se obtiene una secuencia de archivos de la interfaz IAsyncOperation que devuelve.

Paso 2: Obtener una secuencia de archivos

Declare un controlador de finalización para que se ejecute después de que se devuelva la operación asincrónica del selector de archivos. Use el método GetResults para recuperar el archivo y obtener el objeto de secuencia de archivos.

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

En el paso siguiente se convierte el objeto IRandomAccessStream en un IStream que se puede pasar a WIC.

Paso 3: Conversión de la secuencia de archivos

Use la función CreateStreamOverRandomAccessStream para convertir la secuencia de archivos. Windows Las API en tiempo de ejecución representan secuencias con IRandomAccessStream,mientras que WIC consume IStream.

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

Nota

Para usar la función CreateStreamOverRandomAccessStream, debe incluir shcore.h en el proyecto.

Paso 4: Crear un descodificador wic y obtener el marco

Cree un objeto IWICBitmapDecoder mediante el método IWICImagingFactory::CreateDecoderFromStream.

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

Obtenga el primer fotograma de la imagen del descodificador mediante el método IWICBitmapDecoder::GetFrame.

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

Paso 5: Crear un convertidor de WIC e inicializar

Convierta la imagen al formato de color BGRA mediante WIC. IWICBitmapFrameDecode devolverá el formato de píxel nativo de la imagen, como los JPEG se almacenan en GUID _ WICPixelFormat24bppBGR. Sin embargo, como optimización del rendimiento con Direct2D, se recomienda convertir a WICPixelFormat32bppPBGRA.

  1. Cree un objeto IWICFormatConverter mediante el método IWICImagingFactory::CreateFormatConverter.

        ComPtr<IWICFormatConverter> converter;
        DX::ThrowIfFailed(
            m_wicFactory->CreateFormatConverter(&converter)
            ); 
    
    
  2. Inicialice el convertidor de formato para usar WICPixelFormat32bppPBGRA y pase el marco de mapa de bits.

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

La interfaz IWICFormatConverter se deriva de la interfaz IWICBitmapSource, por lo que puede pasar el convertidor al efecto de origen del mapa de bits.

Paso 6: Crear efecto y pasar un IWICBitmapSource

Use el método CreateEffect para crear un objeto ID2D1Effect de origen de mapa de bits mediante el contexto del dispositivo Direct2D .

Use el método ID2D1Effect::SetValue para establecer la propiedad _ BITMAPSOURCE _ PROP _ WIC BITMAP _ _ SOURCE de D2D1 en el convertidor de formato WIC .

Nota

El efecto de origen del mapa de bits no toma una entrada del método SetInput como muchos efectos de Direct2D. En su lugar, el objeto IWICBitmapSource se especifica como una propiedad.

    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.

Ahora que tiene el efecto de origen de mapa de bits, puede usarlo como entrada para cualquier id2D1Effect y crear un gráfico de efectos.

Ejemplo completo

Este es el código completo de este ejemplo.

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