So laden Sie ein Bild mit dem FilePicker in Direct2D-Effekte
Zeigt, wie Sie Windows::Storage::Pickers::FileOpenPicker verwenden, um ein Bild in Direct2D-Effekte zu laden. Wenn Sie den Benutzer*innen in einer Windows Store-App die Möglichkeit geben möchten, eine gespeicherte Bilddatei auszuwählen, empfehlen wir Ihnen, den FileOpenPicker zu verwenden.
Wichtige Informationen
Technologie
Voraussetzungen
- Sie benötigen ein ID2D1DeviceContext-Objekt, um Effekte zu erstellen.
- Sie benötigen ein IWICImagingFactory-Objekt, um WIC-Objekte zu erstellen.
Anweisungen
Schritt 1: Öffnen Sie den File-Picker
Erstellen Sie ein FileOpenPicker-Objekt, und legen Sie den ViewMode, SuggestedStartLocation und den FileTypeFilter für die Auswahl von Bildern fest. Rufen Sie die Methode PickSingleFileAsync auf.
FileOpenPicker^ openPicker = ref new FileOpenPicker();
openPicker->ViewMode = PickerViewMode::Thumbnail;
openPicker->SuggestedStartLocation = PickerLocationId::PicturesLibrary;
openPicker->FileTypeFilter->Append(".jpg");
auto pickOperation = openPicker->PickSingleFileAsync();
Nachdem PickSingleFileAsync abgeschlossen ist, erhalten Sie einen File-Stream von der IAsyncOperation-Schnittstelle.
Schritt 2: Abrufen eines File-Streams
Deklarieren Sie einen Handler, der nach der Rückkehr des asynchronen Vorgangs des File-Pickers ausgeführt wird. Verwenden Sie die Methode GetResults, um die Datei abzurufen und das File-Stream-Objekt zu erhalten.
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);
});
}
});
Im nächsten Schritt konvertieren Sie das IRandomAccessStream-Objekt in einen IStream, den Sie an WIC übergeben können.
Schritt 3: Konvertieren Sie den File-Stream
Verwenden Sie die Funktion CreateStreamOverRandomAccessStream, um den File-Stream zu konvertieren. Windows Runtime-APIs repräsentieren Streams über IRandomAccessStream, während WIC IStream verwendet.
ComPtr<IStream> istream;
DX::ThrowIfFailed(
CreateStreamOverRandomAccessStream(
reinterpret_cast<IUnknown*>(fileStream),
IID_PPV_ARGS(&istream)
)
);
Hinweis
Um die Funktion CreateStreamOverRandomAccessStream zu verwenden, sollten Sie shcore.h in Ihr Projekt aufnehmen.
Schritt 4: Erstellen Sie einen WIC-Decoder, und holen Sie sich den Frame
Erstellen Sie ein IWICBitmapDecoder-Objekt mit der IWICImagingFactory::CreateDecoderFromStream-Methode.
ComPtr<IWICBitmapDecoder> decoder;
DX::ThrowIfFailed(
m_wicFactory->CreateDecoderFromStream(
istream.Get(),
nullptr,
WICDecodeMetadataCacheOnDemand,
&decoder
)
);
Rufen Sie mit der Methode IWICBitmapDecoder::GetFrame den ersten Frame des Bildes vom Decoder ab.
ComPtr<IWICBitmapFrameDecode> frame;
DX::ThrowIfFailed(
decoder->GetFrame(0, &frame)
);
Schritt 5: Erstellen Sie einen WIC-Konverter, und initialisieren Sie ihn
Konvertieren Sie das Bild in das BGRA-Farbformat mit WIC. IWICBitmapFrameDecode wird das native Pixelformat des Bildes zurückgeben (so wie JPEGs in GUID_WICPixelFormat24bppBGR gespeichert werden). Um die Leistung von Direct2D zu optimieren, empfehlen wir Ihnen jedoch eine Konvertierung in WICPixelFormat32bppPBGRA.
Erstellen Sie ein IWICFormatConverter-Objekt mithilfe der Methode IWICImagingFactory::CreateFormatConverter.
ComPtr<IWICFormatConverter> converter; DX::ThrowIfFailed( m_wicFactory->CreateFormatConverter(&converter) );
Initialisieren Sie den Formatkonverter zur Verwendung von WICPixelFormat32bppPBGRA, und übergeben Sie das Bitmap-Frame.
DX::ThrowIfFailed( converter->Initialize( frame.Get(), GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, nullptr, 0.0f, WICBitmapPaletteTypeCustom // premultiplied BGRA has no paletting, so this is ignored ) );
Die Schnittstelle IWICFormatConverter ist von der Schnittstelle IWICBitmapSource abgeleitet, sodass Sie den Konverter an den Effekt Bitmap-Quelle übergeben können.
Schritt 6: Erstellen Sie einen Effekt, und übergeben Sie eine IWICBitmapSource
Verwenden Sie die Methode CreateEffect, um ein Bitmap Source ID2D1Effect-Objekt unter Verwendung des Direct2D-Gerätekontextes zu erstellen.
Verwenden Sie die Methode ID2D1Effect::SetValue, um die Eigenschaft D2D1_BITMAPSOURCE_PROP_WIC_BITMAP_SOURCE für den WIC-Formatkonverter festzulegen.
Hinweis
Der Bitmap Source Effekt nimmt keinen Input von der SetInput-Methode wie viele Direct2D-Effekte. Stattdessen wird das IWICBitmapSource-Objekt als Eigenschaft angegeben.
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.
Jetzt, da Sie den Bitmap Source-Effekt haben, können Sie ihn als Eingabe für jeden ID2D1Effect verwenden und einen Effekt-Graphen erstellen.
Vollständiges Beispiel
Hier ist der vollständige Code für dieses Beispiel.
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.
}