Comment charger une image dans des effets Direct2D à l’aide de FilePicker

montre comment utiliser l' 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

Instructions

Étape 1 : ouvrir le sélecteur de fichiers

Créez un objet FileOpenPicker et définissez ViewMode, SuggestedStartLocation et FileTypeFilter pour la sélection d’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 le PickSingleFileAsync terminé, vous recevez un flux de fichier à partir de l’interface IAsyncOperation qu’il retourne.

Étape 2 : obtenir un flux de fichier

Déclarez un gestionnaire d’achèvement à exécuter après le retour de l’opération Async du sélecteur de fichiers. Utilisez la méthode GetResults pour récupérer le fichier et obtenir l’objet de flux de fichier.

    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 allez convertir l’objet IRandomAccessStream en IStream que vous pouvez passer à WIC.

Étape 3 : convertir le flux de fichier

Utilisez la fonction CreateStreamOverRandomAccessStream pour convertir le flux de fichier. Windows Les API de Runtime 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
                    )
          );

Récupérez le premier frame 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 fichiers JPEG sont stockés dans le GUID _ WICPixelFormat24bppBGR. Toutefois, en tant qu’optimisation des performances avec Direct2D, nous vous recommandons de convertir en WICPixelFormat32bppPBGRA.

  1. Créez un objet IWICFormatConverter à l’aide de la méthode IWICImagingFactory :: CreateFormatConverter .

        ComPtr<IWICFormatConverter> converter;
        DX::ThrowIfFailed(
            m_wicFactory->CreateFormatConverter(&converter)
            ); 
    
    
  2. Initialisez le convertisseur de format pour utiliser le 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 . vous pouvez donc passer le convertisseur à l’effet de source bitmap .

Étape 6 : créer un effet et passer un IWICBitmapSource

Utilisez la méthode CreateEffect pour créer un objet ID2D1Effect source bitmap à l’aide du contexte de périphérique Direct2D .

Utilisez la méthode ID2D1Effect :: SetValue pour définir la propriété source de la _ _ _ _ _ source bitmap d2d1 BITMAPSOURCE prop avec le convertisseur de format WIC .

Notes

L’effet de source bitmap ne prend pas d’entrée 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 de source bitmap , vous pouvez l’utiliser comme entrée pour 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.
}