Como carregar uma imagem em efeitos do Direct2D usando o FilePicker
Mostra como usar o Windows::Storage::Pickers::FileOpenPicker para carregar uma imagem em efeitos do Direct2D. 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
- Você precisa de um objeto ID2D1DeviceContext para criar efeitos.
- Você precisa de um objeto IWICImagingFactory para criar objetos WIC.
Instruções
Etapa 1: abrir o seletor de arquivos
Crie um objeto FileOpenPicker e defina ViewMode, SuggestedStartLocation e FileTypeFilter para a seleção de 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ê obterá um fluxo de arquivos da interface IAsyncOperation retornada por ele.
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 WIC.
Etapa 3: converter o fluxo de arquivos
Use a função CreateStreamOverRandomAccessStream para converter o fluxo de arquivos. As APIs do Windows Runtime 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ê deverá 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 para o formato de cor BGRA usando WIC. IWICBitmapFrameDecode retornará o formato de pixel nativo da imagem, como os JPEGs são armazenados em GUID_WICPixelFormat24bppBGR. No entanto, como uma otimização de desempenho com Direct2D, recomendamos que você converta em WICPixelFormat32bppPBGRA.
Crie um objeto IWICFormatConverter usando o método IWICImagingFactory::CreateFormatConverter.
ComPtr<IWICFormatConverter> converter; DX::ThrowIfFailed( m_wicFactory->CreateFormatConverter(&converter) );
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 ao efeito de origem do bitmap.
Etapa 6: criar efeito e passar um IWICBitmapSource
Use o método CreateEffect para criar um objeto origem de bitmap ID2D1Effect usando o contexto de dispositivo Direct2D.
Use o método ID2D1Effect::SetValue para definir a propriedade D2D1_BITMAPSOURCE_PROP_WIC_BITMAP_SOURCE para o conversor de formato WIC.
Observação
O efeito origem de bitmap não obtém uma entrada do método SetInput como em muitos efeitos do 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 de bitmap, pode usá-lo como entrada para qualquer ID2D1Effect e criar um gráfico de efeitos.
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.
}