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
- Necesita un objeto ID2D1DeviceContext para crear efectos.
- Necesita un objeto IWICImagingFactory para crear objetos WIC.
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.
Cree un objeto IWICFormatConverter mediante el método IWICImagingFactory::CreateFormatConverter.
ComPtr<IWICFormatConverter> converter; DX::ThrowIfFailed( m_wicFactory->CreateFormatConverter(&converter) );
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.
}