Comment charger une image dans des effets Direct2D à l’aide de FilePicker
Montre comment utiliser le Windows::Stockage::P ickers::FileOpenPicker pour charger une image dans des effets Direct2D. Si vous souhaitez permettre à l’utilisateur de sélectionner un fichier image à partir du stockage dans une application Windows Store, nous vous recommandons d’utiliser FileOpenPicker.
Bon à savoir
Technologies
Prérequis
- Vous avez besoin d’un objet ID2D1DeviceContext pour créer des effets.
- Vous avez besoin d’un objet IWICImagingFactory pour créer des objets WIC.
Instructions
Étape 1 : Ouvrir le sélecteur de fichiers
Créez un objet FileOpenPicker et définissez ViewMode, SuggestedStartLocation et FileTypeFilter pour sélectionner des images. Appelez la méthode PickSingleFileAsync .
FileOpenPicker^ openPicker = ref new FileOpenPicker();
openPicker->ViewMode = PickerViewMode::Thumbnail;
openPicker->SuggestedStartLocation = PickerLocationId::PicturesLibrary;
openPicker->FileTypeFilter->Append(".jpg");
auto pickOperation = openPicker->PickSingleFileAsync();
Une fois pickSingleFileAsync terminé, vous obtenez un flux de fichiers à partir de l’interface IAsyncOperation qu’il retourne.
Étape 2 : Obtenir un flux de fichiers
Déclarez un gestionnaire d’achèvement à exécuter une fois l’opération asynchrone du sélecteur de fichiers retournée. Utilisez la méthode GetResults pour récupérer le fichier et obtenir l’objet de flux de fichiers.
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);
});
}
});
À l’étape suivante, vous convertissez l’objet IRandomAccessStream en IStream que vous pouvez passer à WIC.
Étape 3 : Convertir le flux de fichiers
Utilisez la fonction CreateStreamOverRandomAccessStream pour convertir le flux de fichiers. Windows Runtime API représentent des flux avec IRandomAccessStream, tandis que WIC consomme IStream.
ComPtr<IStream> istream;
DX::ThrowIfFailed(
CreateStreamOverRandomAccessStream(
reinterpret_cast<IUnknown*>(fileStream),
IID_PPV_ARGS(&istream)
)
);
Notes
Pour utiliser la fonction CreateStreamOverRandomAccessStream , vous devez inclure shcore.h dans votre projet.
Étape 4 : Créer un décodeur WIC et obtenir le frame
Créez un objet IWICBitmapDecoder à l’aide de la méthode IWICImagingFactory::CreateDecoderFromStream .
ComPtr<IWICBitmapDecoder> decoder;
DX::ThrowIfFailed(
m_wicFactory->CreateDecoderFromStream(
istream.Get(),
nullptr,
WICDecodeMetadataCacheOnDemand,
&decoder
)
);
Obtenez la première image de l’image à partir du décodeur à l’aide de la méthode IWICBitmapDecoder::GetFrame .
ComPtr<IWICBitmapFrameDecode> frame;
DX::ThrowIfFailed(
decoder->GetFrame(0, &frame)
);
Étape 5 : Créer un convertisseur WIC et initialiser
Convertissez l’image au format de couleur BGRA à l’aide de WIC. IWICBitmapFrameDecode retourne le format de pixel natif de l’image, comme les JPEG, stockés dans GUID_WICPixelFormat24bppBGR. Toutefois, en tant qu’optimisation des performances avec Direct2D, nous vous recommandons de convertir en WICPixelFormat32bppPBGRA.
Créez un objet IWICFormatConverter à l’aide de la méthode IWICImagingFactory::CreateFormatConverter .
ComPtr<IWICFormatConverter> converter; DX::ThrowIfFailed( m_wicFactory->CreateFormatConverter(&converter) );
Initialisez le convertisseur de format pour utiliser WICPixelFormat32bppPBGRA et passer le frame bitmap.
DX::ThrowIfFailed( converter->Initialize( frame.Get(), GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, nullptr, 0.0f, WICBitmapPaletteTypeCustom // premultiplied BGRA has no paletting, so this is ignored ) );
L’interface IWICFormatConverter est dérivée de l’interface IWICBitmapSource , ce qui vous permet de transmettre le convertisseur à l’effet source bitmap .
Étape 6 : Créer un effet et passer un IWICBitmapSource
Utilisez la méthode CreateEffect pour créer un objet bitmapsourceID2D1Effect à l’aide du contexte Direct2Ddevice.
Utilisez la méthode ID2D1Effect::SetValue pour définir la propriété D2D1_BITMAPSOURCE_PROP_WIC_BITMAP_SOURCE sur le convertisseurWICformat.
Remarque
L’effet source bitmap ne prend pas d’entrée à partir de la méthode SetInput , comme de nombreux effets Direct2D. Au lieu de cela, l’objet IWICBitmapSource est spécifié en tant que propriété.
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.
Maintenant que vous avez l’effet source bitmap , vous pouvez l’utiliser comme entrée dans n’importe quel ID2D1Effect et créer un graphique d’effet.
Exemple complet
Voici le code complet de cet exemple.
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.
}