Vue d'ensemble des masques d'opacité

Cette rubrique explique comment utiliser des bitmaps et des pinceaux pour définir des masques d’opacité. Elle contient les sections suivantes.

Prérequis

Cette vue d’ensemble suppose que vous êtes familiarisé avec les opérations de dessin Direct2D de base, comme décrit dans la procédure pas à pas Créer une application Direct2D simple . Vous devez également être familiarisé avec les différents types de pinceaux, comme décrit dans la vue d’ensemble des pinceaux.

Qu’est-ce qu’un masque d’opacité ?

Un masque d’opacité est un masque, décrit par un pinceau ou une bitmap, qui est appliqué à un autre objet pour rendre cet objet partiellement ou complètement transparent. Un masque d’opacité utilise des informations de canal alpha pour spécifier la façon dont les pixels sources de l’objet sont fusionnés dans la cible de destination finale. Les parties transparentes du masque indiquent les zones où l’image sous-jacente est masquée, tandis que les parties opaques du masque indiquent où l’objet masqué est visible.

Il existe plusieurs façons d’appliquer un masque d’opacité :

  • Utilisez la méthode ID2D1RenderTarget::FillOpacityMask . La méthode FillOpacityMask peint une zone rectangulaire d’une cible de rendu, puis applique un masque d’opacité, défini par une bitmap. Utilisez cette méthode lorsque votre masque d’opacité est une bitmap et que vous souhaitez remplir une zone rectangulaire.
  • Utilisez la méthode ID2D1RenderTarget::FillGeometry . La méthode FillGeometry peint l’intérieur de la géométrie avec l’id2D1BitmapBrush spécifié, puis applique un masque d’opacité, défini par un pinceau. Utilisez cette méthode lorsque vous souhaitez appliquer un masque d’opacité à une géométrie ou utiliser un pinceau comme masque d’opacité.
  • Utilisez un ID2D1Layer pour appliquer un masque d’opacité. Utilisez cette approche lorsque vous souhaitez appliquer un masque d’opacité à un groupe de contenu de dessin, et pas seulement à une seule forme ou image. Pour plus d’informations, consultez Vue d’ensemble des couches.

Utiliser une bitmap comme masque d’opacité avec la méthode FillOpacityMask

La méthode FillOpacityMask peint une région rectangulaire d’une cible de rendu, puis applique un masque d’opacité, défini par un ID2D1Bitmap. Utilisez cette méthode lorsque vous avez une bitmap que vous souhaitez utiliser comme masque d’opacité pour une région rectangulaire.

Le diagramme suivant montre un effet de l’application du masque d’opacité ( id2D1Bitmap avec une image d’une fleur) à un ID2D1BitmapBrush avec une image d’une plante de fougère. L’image obtenue est une image bitmap d’une plante coupée à la forme de fleur.

diagramme d’une bitmap de fleur utilisée comme masque d’opacité sur une image d’une plante de fougère

Les exemples de code suivants montrent comment procéder.

Le premier exemple charge la bitmap suivante, m_pBitmapMask, pour l’utiliser comme masque bitmap. L’illustration suivante montre la sortie produite. Notez que, bien que la partie opaque de la bitmap apparaisse en noir, les informations de couleur dans la bitmap n’ont aucun effet sur le masque d’opacité ; seules les informations d’opacité de chaque pixel de la bitmap sont utilisées. Les pixels entièrement opaques de cette bitmap ont été colorés en noir à titre d’illustration uniquement.

illustration du masque bitmap de fleur

Dans cet exemple, l’ID2D1Bitmap est chargé par une méthode d’assistance, LoadResourceBitmap, définie ailleurs dans l’exemple.

            if (SUCCEEDED(hr))
            {
                hr = LoadResourceBitmap(
                    m_pRenderTarget,
                    m_pWICFactory,
                    L"BitmapMask",
                    L"Image",
                    &m_pBitmapMask
                    );
            }

L’exemple suivant définit le pinceau , m_pFernBitmapBrush, auquel le masque d’opacité est appliqué. Cet exemple utilise un ID2D1BitmapBrush qui contient une image d’une fougère, mais vous pouvez utiliser un ID2D1SolidColorBrush, ID2D1LinearGradientBrush ou ID2D1RadialGradientBrush à la place. L’illustration suivante montre la sortie produite.

illustration de la bitmap utilisée par le pinceau bitmap

            if (SUCCEEDED(hr))
            {
                D2D1_BITMAP_BRUSH_PROPERTIES propertiesXClampYClamp = 
                    D2D1::BitmapBrushProperties(
                    D2D1_EXTEND_MODE_CLAMP,
                    D2D1_EXTEND_MODE_CLAMP,
                    D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR
                    );
                hr = m_pRenderTarget->CreateBitmapBrush(
                    m_pFernBitmap,
                    propertiesXClampYClamp,
                    &m_pFernBitmapBrush
                    );


            }

Maintenant que le masque d’opacité et le pinceau sont définis, vous pouvez utiliser la méthode FillOpacityMask dans la méthode de rendu de votre application. Lorsque vous appelez la méthode FillOpacityMask , vous devez spécifier le type de masque d’opacité que vous utilisez : D2D1_OPACITY_MASK_CONTENT_GRAPHICS, D2D1_OPACITY_MASK_CONTENT_TEXT_NATURAL et D2D1_OPACITY_MASK_CONTENT_TEXT_GDI_COMPATIBLE. Pour connaître les significations de ces trois types, consultez D2D1_OPACITY_MASK_CONTENT.

Notes

À compter de Windows 8, le D2D1_OPACITY_MASK_CONTENT n’est pas obligatoire. Consultez la méthode ID2D1DeviceContext::FillOpacityMask , qui n’a aucun paramètre D2D1_OPACITY_MASK_CONTENT .

 

L’exemple suivant définit le mode anticrénelage de la cible de rendu sur D2D1_ANTIALIAS_MODE_ALIASED afin que le masque d’opacité fonctionne correctement. Il appelle ensuite la méthode FillOpacityMask et lui transmet le masque d’opacité (m_pBitmapMask), le pinceau auquel le masque d’opacité est appliqué (m_pFernBitmapBrush), le type de contenu à l’intérieur du masque d’opacité (D2D1_OPACITY_MASK_CONTENT_GRAPHICS) et la zone à peindre. L’illustration suivante montre la sortie produite.

illustration de l’image de la plante de fougère avec un masque d’opacité appliqué

        D2D1_RECT_F rcBrushRect = D2D1::RectF(5, 5, 155, 155);


        // D2D1_ANTIALIAS_MODE_ALIASED must be set for FillOpacityMask to function properly
        m_pRenderTarget->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
        m_pRenderTarget->FillOpacityMask(
            m_pBitmapMask,
            m_pFernBitmapBrush,
            D2D1_OPACITY_MASK_CONTENT_GRAPHICS,
            &rcBrushRect
            );
        m_pRenderTarget->SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);

Le code a été omis dans cet exemple.

Utiliser un pinceau comme masque d’opacité avec la méthode FillGeometry

La section précédente a décrit comment utiliser un ID2D1Bitmap comme masque d’opacité. Direct2D fournit également la méthode ID2D1RenderTarget::FillGeometry , qui vous permet de spécifier éventuellement le pinceau comme masque d’opacité lorsque vous remplissez un ID2D1Geometry. Cela vous permet de créer des masques d’opacité à partir de dégradés (à l’aide de ID2D1LinearGradientBrush ou ID2D1RadialGradientBrush) et de bitmaps (à l’aide de ID2D1Bitmap).

La méthode FillGeometry prend trois paramètres :

Les sections suivantes décrivent comment utiliser des objets ID2D1LinearGradientBrush et ID2D1RadialGradientBrush en tant que masques d’opacité.

Utiliser un pinceau dégradé linéaire comme masque d’opacité

Le diagramme suivant montre l’effet de l’application d’un pinceau de dégradé linéaire à un rectangle rempli d’une bitmap de fleurs.

diagramme d’une bitmap de fleur avec un pinceau de dégradé linéaire appliqué

Les étapes suivantes décrivent comment recréer cet effet.

  1. Définissez le contenu à masquer. L’exemple suivant crée un objet ID2D1BitmapBrush, m_pLinearFadeFlowersBitmap. Le mode d’extension x- et y- pour m_pLinearFadeFlowersBitmap sont définis sur D2D1_EXTEND_MODE_CLAMP afin qu’il puisse être utilisé avec un masque d’opacité par la méthode FillGeometry .

    if (SUCCEEDED(hr))
    {
        // Create the bitmap to be used by the bitmap brush.
        hr = LoadResourceBitmap(
            m_pRenderTarget,
            m_pWICFactory,
            L"LinearFadeFlowers",
            L"Image",
            &m_pLinearFadeFlowersBitmap
            );
    }
    
    if (SUCCEEDED(hr))
        {
            D2D1_BITMAP_BRUSH_PROPERTIES propertiesXClampYClamp = 
                D2D1::BitmapBrushProperties(
                D2D1_EXTEND_MODE_CLAMP,
                D2D1_EXTEND_MODE_CLAMP,
                D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR
                );
    
    C++
                    if (SUCCEEDED(hr))
                    {
                        hr = m_pRenderTarget->CreateBitmapBrush(
                            m_pLinearFadeFlowersBitmap,
                            propertiesXClampYClamp,
                            &m_pLinearFadeFlowersBitmapBrush
                            );
                    }
    C++
                }
  2. Définissez le masque d’opacité. L’exemple de code suivant crée un pinceau de dégradé linéaire diagonal (m_pLinearGradientBrush) qui passe du noir entièrement opaque à la position 0 au blanc complètement transparent à la position 1.

                if (SUCCEEDED(hr))
                {
                    ID2D1GradientStopCollection *pGradientStops = NULL;

                    static const D2D1_GRADIENT_STOP gradientStops[] =
                    {
                        {   0.f,  D2D1::ColorF(D2D1::ColorF::Black, 1.0f)  },
                        {   1.f,  D2D1::ColorF(D2D1::ColorF::White, 0.0f)  },
                    };

                    hr = m_pRenderTarget->CreateGradientStopCollection(
                        gradientStops,
                        2,
                        &pGradientStops);


                    if (SUCCEEDED(hr))
                    {
                        hr = m_pRenderTarget->CreateLinearGradientBrush(
                            D2D1::LinearGradientBrushProperties(
                                D2D1::Point2F(0, 0),
                                D2D1::Point2F(150, 150)),
                            pGradientStops,
                            &m_pLinearGradientBrush);
                    }

    
                pGradientStops->Release();
                }
  1. Utilisez la méthode FillGeometry . Le dernier exemple utilise la méthode FillGeometry pour le pinceau de contenu pour remplir un ID2D1RectangleGeometry (m_pRectGeo) avec un ID2D1BitmapBrush (m_pLinearFadeFlowersBitmap) et applique un masque d’opacité (m_pLinearGradientBrush).
            m_pRenderTarget->FillGeometry(
                m_pRectGeo, 
                m_pLinearFadeFlowersBitmapBrush, 
                m_pLinearGradientBrush
                );

Le code a été omis dans cet exemple.

Utiliser un pinceau dégradé radial comme masque d’opacité

Le diagramme suivant montre l’effet visuel de l’application d’un pinceau dégradé radial à un rectangle rempli d’une bitmap de feuillage.

diagramme d’une bitmap de feuillage avec un pinceau dégradé radial appliqué

Le premier exemple crée un objet ID2D1BitmapBrush, m_pRadialFadeFlowersBitmapBrush. Afin qu’il puisse être utilisé avec un masque d’opacité par la méthode FillGeometry , les modes d’extension x- et y- pour m_pRadialFadeFlowersBitmapBrush sont définis sur D2D1_EXTEND_MODE_CLAMP.

            if (SUCCEEDED(hr))
            {
                // Create the bitmap to be used by the bitmap brush.
                hr = LoadResourceBitmap(
                    m_pRenderTarget,
                    m_pWICFactory,
                    L"RadialFadeFlowers",
                    L"Image",
                    &m_pRadialFadeFlowersBitmap
                    );
            }


            if (SUCCEEDED(hr))
            {
                D2D1_BITMAP_BRUSH_PROPERTIES propertiesXClampYClamp = 
                    D2D1::BitmapBrushProperties(
                    D2D1_EXTEND_MODE_CLAMP,
                    D2D1_EXTEND_MODE_CLAMP,
                    D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR
                    );
C++
                if (SUCCEEDED(hr))
                {
                    hr = m_pRenderTarget->CreateBitmapBrush(
                        m_pLinearFadeFlowersBitmap,
                        propertiesXClampYClamp,
                        &m_pLinearFadeFlowersBitmapBrush
                        );
                }
C++
            }

L’exemple suivant définit le pinceau dégradé radial qui sera utilisé comme masque d’opacité.

            if (SUCCEEDED(hr))
            {
                ID2D1GradientStopCollection *pGradientStops = NULL;

                static const D2D1_GRADIENT_STOP gradientStops[] =
                {
                    {   0.f,  D2D1::ColorF(D2D1::ColorF::Black, 1.0f)  },
                    {   1.f,  D2D1::ColorF(D2D1::ColorF::White, 0.0f)  },
                };

                hr = m_pRenderTarget->CreateGradientStopCollection(
                    gradientStops,
                    2,
                    &pGradientStops);




                if (SUCCEEDED(hr))
                {
                    hr = m_pRenderTarget->CreateRadialGradientBrush(
                        D2D1::RadialGradientBrushProperties(
                            D2D1::Point2F(75, 75),
                            D2D1::Point2F(0, 0),
                            75,
                            75),
                        pGradientStops,
                        &m_pRadialGradientBrush);
                }
                pGradientStops->Release();
            }

L’exemple de code final utilise id2D1BitmapBrush (m_pRadialFadeFlowersBitmapBrush) et le masque d’opacité (m_pRadialGradientBrush) pour remplir un ID2D1RectangleGeometry (m_pRectGeo).

        m_pRenderTarget->FillGeometry(
            m_pRectGeo,
            m_pRadialFadeFlowersBitmapBrush, 
            m_pRadialGradientBrush
            );

Le code a été omis dans cet exemple.

Appliquer un masque d’opacité à un calque

Lorsque vous appelez PushLayer pour envoyer un objet ID2D1Layer à une cible de rendu, vous pouvez utiliser la structure D2D1_LAYER_PARAMETERS pour appliquer un pinceau en tant que masque d’opacité. L’exemple de code suivant utilise un ID2D1RadialGradientBrush comme masque d’opacité.

HRESULT DemoApp::RenderWithLayerWithOpacityMask(ID2D1RenderTarget *pRT)
{   

    HRESULT hr = S_OK;

    // Create a layer.
    ID2D1Layer *pLayer = NULL;
    hr = pRT->CreateLayer(NULL, &pLayer);

    if (SUCCEEDED(hr))
    {
        pRT->SetTransform(D2D1::Matrix3x2F::Translation(300, 250));

        // Push the layer with the content bounds.
        pRT->PushLayer(
            D2D1::LayerParameters(
                D2D1::InfiniteRect(),
                NULL,
                D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
                D2D1::IdentityMatrix(),
                1.0,
                m_pRadialGradientBrush,
                D2D1_LAYER_OPTIONS_NONE),
            pLayer
            );

        pRT->DrawBitmap(m_pBambooBitmap, D2D1::RectF(0, 0, 190, 127));

        pRT->FillRectangle(
            D2D1::RectF(25.f, 25.f, 50.f, 50.f), 
            m_pSolidColorBrush
            );
        pRT->FillRectangle(
            D2D1::RectF(50.f, 50.f, 75.f, 75.f),
            m_pSolidColorBrush
            ); 
        pRT->FillRectangle(
            D2D1::RectF(75.f, 75.f, 100.f, 100.f),
            m_pSolidColorBrush
            );    
 
        pRT->PopLayer();
    }
    SafeRelease(&pLayer);
   
    return hr;
    
}

Pour plus d’informations sur l’utilisation des couches, consultez vue d’ensemble des couches.

Vue d’ensemble des pinceaux

Vue d’ensemble des couches