Compartir a través de


Cómo cargar una imagen en efectos de Direct2D mediante FilePicker

Muestra cómo usar Windows::Storage::Pickers::FileOpenPicker para cargar una imagen en efectos Direct2D. Si desea permitir al usuario seleccionar un archivo de imagen del almacenamiento en una aplicación de la Tienda Windows, le recomendamos que use FileOpenPicker.

Lo que necesita saber

Tecnologías

Requisitos previos

Instrucciones

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 que se complete PickSingleFileAsync, obtendrá una secuencia de archivos de la interfaz IAsyncOperation.

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 siguiente paso, convertirá el objeto IRandomAccessStream en un IStream que puede pasar a WIC.

Paso 3: Convertir la secuencia de archivos

Use la función CreateStreamOverRandomAccessStream para convertir la secuencia de archivos. Las API de Windows Runtime 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: Creación de un convertidor WIC e inicialización

Convierta la imagen en el 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 de 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 CreateEffect para crear un objeto de origen de mapa de bits ID2D1Effect mediante el contexto del dispositivo Direct2D .

Use el método ID2D1Effect::SetValue para establecer la propiedad D2D1_BITMAPSOURCE_PROP_WIC_BITMAP_SOURCE 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 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 del 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.
}