Condividi tramite


Cenni preliminari sulle maschere di opacità

Questo argomento descrive come usare bitmap e pennelli per definire maschere di opacità. Include le sezioni seguenti:

Prerequisiti

Questa panoramica presuppone che si abbia familiarità con le operazioni di disegno Direct2D di base, come descritto nella procedura dettagliata Creare una semplice applicazione Direct2D . È anche necessario avere familiarità con i diversi tipi di pennelli, come descritto in Cenni preliminari sui pennelli.

Che cos'è una maschera di opacità?

Una maschera di opacità è una maschera, descritta da un pennello o una bitmap, applicata a un altro oggetto per rendere l'oggetto parzialmente o completamente trasparente. Una maschera di opacità usa informazioni sul canale alfa per specificare la modalità di fusione dei pixel di origine dell'oggetto nella destinazione finale. Le parti trasparenti della maschera indicano le aree in cui l'immagine sottostante è nascosta, mentre le parti opache della maschera indicano dove l'oggetto mascherato è visibile.

Esistono diversi modi per applicare una maschera di opacità:

  • Usare il metodo ID2D1RenderTarget::FillOpacityMask . Il metodo FillOpacityMask disegna un'area rettangolare di una destinazione di rendering e quindi applica una maschera di opacità, definita da una bitmap. Usa questo metodo quando la maschera di opacità è una bitmap e vuoi riempire un'area rettangolare.
  • Usare il metodo ID2D1RenderTarget::FillGeometry . Il metodo FillGeometry disegna l'interno della geometria con l'ID2D1BitmapBrush specificato, quindi applica una maschera di opacità, definita da un pennello. Utilizzare questo metodo quando si desidera applicare una maschera di opacità a una geometria o si vuole usare un pennello come maschera di opacità.
  • Usare un ID2D1Layer per applicare una maschera di opacità. Utilizzare questo approccio quando si desidera applicare una maschera di opacità a un gruppo di contenuto di disegno, non solo a una singola forma o immagine. Per informazioni dettagliate, vedere Panoramica dei livelli.

Usare una bitmap come maschera di opacità con il metodo FillOpacityMask

Il metodo FillOpacityMask disegna un'area rettangolare di una destinazione di rendering e quindi applica una maschera di opacità definita da id2D1Bitmap. Usa questo metodo quando hai una bitmap che vuoi usare come maschera di opacità per un'area rettangolare.

Il diagramma seguente mostra un effetto dell'applicazione della maschera di opacità ( ID2D1Bitmap con un'immagine di un fiore) a un oggetto ID2D1BitmapBrush con un'immagine di una pianta di felce. L'immagine risultante è una bitmap di una pianta ritagliata alla forma del fiore.

diagramma di una bitmap di fiori utilizzata come maschera di opacità su un'immagine di una pianta di felci

Gli esempi di codice seguenti illustrano come viene eseguita questa operazione.

Il primo esempio carica la bitmap seguente, m_pBitmapMask, da usare come maschera bitmap. La figura seguente mostra l'output prodotto. Si noti che, anche se la parte opaca della bitmap appare nera, le informazioni sul colore nella bitmap non hanno alcun effetto sulla maschera di opacità; vengono usate solo le informazioni di opacità di ogni pixel nella bitmap. I pixel completamente opachi in questa bitmap sono stati colorati in nero solo a scopo illustrativo.

illustrazione della maschera bitmap del fiore

In questo esempio l'ID2D1Bitmap viene caricato da un metodo helper, LoadResourceBitmap, definito altrove nell'esempio.

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

Nell'esempio seguente viene definito il pennello m_pFernBitmapBrush a cui viene applicata la maschera di opacità. In questo esempio viene usato un oggetto ID2D1BitmapBrush che contiene un'immagine di una felce, ma è possibile usare invece id2D1SolidColorBrush, ID2D1LinearGradientBrush o ID2D1RadialGradientBrush . La figura seguente mostra l'output prodotto.

illustrazione della bitmap usata dal pennello 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
                    );


            }

Ora che la maschera di opacità e il pennello sono definiti, è possibile usare il metodo FillOpacityMask nel metodo di rendering dell'applicazione. Quando si chiama il metodo FillOpacityMask , è necessario specificare il tipo di maschera di opacità in uso: D2D1_OPACITY_MASK_CONTENT_GRAPHICS, D2D1_OPACITY_MASK_CONTENT_TEXT_NATURAL e D2D1_OPACITY_MASK_CONTENT_TEXT_GDI_COMPATIBLE. Per i significati di questi tre tipi, vedere D2D1_OPACITY_MASK_CONTENT.

Nota

A partire da Windows 8, il D2D1_OPACITY_MASK_CONTENT non è obbligatorio. Vedere il metodo ID2D1DeviceContext::FillOpacityMask , che non ha alcun parametro D2D1_OPACITY_MASK_CONTENT .

 

Nell'esempio seguente viene impostata la modalità di anti-aliasing della destinazione di rendering su D2D1_ANTIALIAS_MODE_ALIASED in modo che la maschera di opacità funzioni correttamente. Chiama quindi il metodo FillOpacityMask e lo passa la maschera di opacità (m_pBitmapMask), il pennello a cui viene applicata la maschera di opacità (m_pFernBitmapBrush), il tipo di contenuto all'interno della maschera di opacità (D2D1_OPACITY_MASK_CONTENT_GRAPHICS) e l'area da disegnare. La figura seguente mostra l'output prodotto.

illustrazione dell'immagine della pianta di felci con una maschera di opacità applicata

        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);

Il codice è stato omesso da questo esempio.

Usare un pennello come maschera di opacità con il metodo FillGeometry

La sezione precedente ha descritto come usare un ID2D1Bitmap come maschera di opacità. Direct2D fornisce anche il metodo ID2D1RenderTarget::FillGeometry , che consente di specificare facoltativamente il pennello come maschera di opacità quando si riempie un oggetto ID2D1Geometry. In questo modo è possibile creare maschere di opacità da sfumature (usando ID2D1LinearGradientBrush o ID2D1RadialGradientBrush) e bitmap (tramite ID2D1Bitmap).

Il metodo FillGeometry accetta tre parametri:

Le sezioni seguenti descrivono come usare gli oggetti ID2D1LinearGradientBrush e ID2D1RadialGradientBrush come maschere di opacità.

Usare un pennello sfumato lineare come maschera di opacità

Il diagramma seguente illustra l'effetto dell'applicazione di un pennello sfumato lineare a un rettangolo riempito con una bitmap di fiori.

diagramma di una bitmap di fiori con un pennello sfumato lineare applicato

I passaggi seguenti descrivono come ricreare questo effetto.

  1. Definire il contenuto da mascherare. Nell'esempio seguente viene creato un m_pLinearFadeFlowersBitmap ID2D1BitmapBrush. La modalità di estensione x e y- per m_pLinearFadeFlowersBitmap è impostata su D2D1_EXTEND_MODE_CLAMP in modo che possa essere usata con una maschera di opacità tramite il metodo 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. Definire la maschera di opacità. Nell'esempio di codice seguente viene creato un pennello sfumato lineare diagonale (m_pLinearGradientBrush) che si dissolve dal nero completamente opaco nella posizione 0 al bianco completamente trasparente nella posizione 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. Usare il metodo FillGeometry . L'esempio finale usa il metodo FillGeometry per il pennello di contenuto per riempire un oggetto ID2D1RectangleGeometry (m_pRectGeo) con id2D1BitmapBrush (m_pLinearFadeFlowersBitmap) e applica una maschera di opacità (m_pLinearGradientBrush).
            m_pRenderTarget->FillGeometry(
                m_pRectGeo, 
                m_pLinearFadeFlowersBitmapBrush, 
                m_pLinearGradientBrush
                );

Il codice è stato omesso da questo esempio.

Usare un pennello sfumato radiale come maschera di opacità

Il diagramma seguente illustra l'effetto visivo dell'applicazione di un pennello sfumato radiale a un rettangolo riempito con una bitmap di fogliame.

diagramma di una bitmap fogliame con un pennello sfumato radiale applicato

Il primo esempio crea un m_pRadialFadeFlowersBitmapBrush ID2D1BitmapBrush. In modo che possa essere usata con una maschera di opacità dal metodo FillGeometry , la modalità di estensione x e y- per m_pRadialFadeFlowersBitmapBrush sono impostate su 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++
            }

Nell'esempio seguente viene definito il pennello sfumato radiale che verrà usato come maschera di 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'esempio di codice finale usa id2D1BitmapBrush (m_pRadialFadeFlowersBitmapBrush) e la maschera di opacità (m_pRadialGradientBrush) per riempire un oggettoID2D1RectangleGeometry (m_pRectGeo).

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

Il codice è stato omesso da questo esempio.

Applicare una maschera di opacità a un livello

Quando chiami PushLayer per eseguire il push di un ID2D1Layer in una destinazione di rendering, puoi usare la struttura D2D1_LAYER_PARAMETERS per applicare un pennello come maschera di opacità. Nell'esempio di codice seguente viene usato un oggetto ID2D1RadialGradientBrush come maschera di 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;
    
}

Per altre informazioni sull'uso dei livelli, vedere Panoramica dei livelli.

Panoramica dei pennelli

Panoramica dei livelli