Información general sobre las máscaras de opacidad

En este tema se describe cómo usar mapas de bits y pinceles para definir máscaras de opacidad. Contiene las siguientes secciones:

Requisitos previos

En esta introducción se da por supuesto que está familiarizado con las operaciones básicas de dibujo de Direct2D, como se describe en el tutorial Creación de una aplicación direct2D sencilla . También debe estar familiarizado con los diferentes tipos de pinceles, como se describe en Información general sobre pinceles.

¿Qué es una máscara de opacidad?

Una máscara de opacidad es una máscara, descrita por un pincel o mapa de bits, que se aplica a otro objeto para que ese objeto sea parcialmente o completamente transparente. Una máscara de opacidad usa información de canal alfa para especificar cómo se combinan los píxeles de origen del objeto en el destino de destino final. Las partes transparentes de la máscara indican las áreas donde se oculta la imagen subyacente, mientras que las partes opacas de la máscara indican dónde está visible el objeto enmascarado.

Hay varias maneras de aplicar una máscara de opacidad:

  • Use el método ID2D1RenderTarget::FillOpacityMask . El método FillOpacityMask pinta una región rectangular de un destino de representación y, a continuación, aplica una máscara de opacidad definida por un mapa de bits. Use este método cuando la máscara de opacidad sea un mapa de bits y desee rellenar una región rectangular.
  • Use el método ID2D1RenderTarget::FillGeometry . El método FillGeometry pinta el interior de la geometría con el id2D1BitmapBrush especificado y, a continuación, aplica una máscara de opacidad definida por un pincel. Use este método cuando desee aplicar una máscara de opacidad a una geometría o desee usar un pincel como máscara de opacidad.
  • Use un ID2D1Layer para aplicar una máscara de opacidad. Use este enfoque cuando desee aplicar una máscara de opacidad a un grupo de contenido de dibujo, no solo una sola forma o imagen. Para obtener más información, consulte La introducción a las capas.

Usar un mapa de bits como máscara de opacidad con el método FillOpacityMask

El método FillOpacityMask pinta una región rectangular de un destino de representación y, a continuación, aplica una máscara de opacidad definida por un ID2D1Bitmap. Use este método cuando tenga un mapa de bits que desee usar como máscara de opacidad para una región rectangular.

En el diagrama siguiente se muestra un efecto de aplicar la máscara de opacidad ( id2D1Bitmap con una imagen de una flor) a un ID2D1BitmapBrush con una imagen de una planta fern. La imagen resultante es un mapa de bits de una planta recortada a la forma de la flor.

diagrama de un mapa de bits de flores utilizado como máscara de opacidad en una imagen de una planta ferrón

En los ejemplos de código siguientes se muestra cómo se logra esto.

En el primer ejemplo se carga el siguiente mapa de bits, m_pBitmapMask, para su uso como máscara de mapa de bits. En la ilustración siguiente se muestra la salida que se genera. Tenga en cuenta que, aunque la parte opaca del mapa de bits aparece negra, la información de color del mapa de bits no tiene ningún efecto en la máscara de opacidad; solo se usa la información de opacidad de cada píxel del mapa de bits. Los píxeles totalmente opacos de este mapa de bits se han coloreado negro únicamente con fines ilustrativos.

ilustración de la máscara de mapa de bits de flores

En este ejemplo, id2D1Bitmap se carga mediante un método auxiliar, LoadResourceBitmap, definido en otra parte del ejemplo.

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

En el ejemplo siguiente se define el pincel, m_pFernBitmapBrush, al que se aplica la máscara de opacidad. En este ejemplo se usa un ID2D1BitmapBrush que contiene una imagen de un fern, pero podría usar un ID2D1SolidColorBrush, ID2D1LinearGradientBrush o ID2D1RadialGradientBrush en su lugar. En la ilustración siguiente se muestra la salida que se genera.

Ilustración del mapa de bits usado por el pincel de mapa de bits

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


            }

Ahora que se define la máscara de opacidad y el pincel, puede usar el método FillOpacityMask en el método de representación de la aplicación. Al llamar al método FillOpacityMask , debe especificar el tipo de máscara de opacidad que usa: D2D1_OPACITY_MASK_CONTENT_GRAPHICS, D2D1_OPACITY_MASK_CONTENT_TEXT_NATURAL y D2D1_OPACITY_MASK_CONTENT_TEXT_GDI_COMPATIBLE. Para conocer los significados de estos tres tipos, vea D2D1_OPACITY_MASK_CONTENT.

Nota

A partir de Windows 8, no es necesario el D2D1_OPACITY_MASK_CONTENT. Consulte el método ID2D1DeviceContext::FillOpacityMask , que no tiene ningún parámetro D2D1_OPACITY_MASK_CONTENT .

 

En el ejemplo siguiente se establece el modo de suavizado de contorno del destino de representación en D2D1_ANTIALIAS_MODE_ALIASED para que la máscara de opacidad funcione correctamente. A continuación, llama al método FillOpacityMask y le pasa la máscara de opacidad (m_pBitmapMask), el pincel al que se aplica la máscara de opacidad (m_pFernBitmapBrush), el tipo de contenido dentro de la máscara de opacidad (D2D1_OPACITY_MASK_CONTENT_GRAPHICS) y el área que se va a pintar. En la ilustración siguiente se muestra la salida que se genera.

ilustración de la imagen de la planta ferrón con una máscara opacidad aplicada

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

El código se ha omitido en este ejemplo.

Usar un pincel como máscara de opacidad con el método FillGeometry

En la sección anterior se describe cómo usar id2D1Bitmap como máscara de opacidad. Direct2D también proporciona el método ID2D1RenderTarget::FillGeometry , que permite especificar opcionalmente el pincel como máscara de opacidad al rellenar un ID2D1Geometry. Esto le permite crear máscaras de opacidad a partir de degradados (mediante ID2D1LinearGradientBrush o ID2D1RadialGradientBrush) y mapas de bits (mediante ID2D1Bitmap).

El método FillGeometry toma tres parámetros:

En las secciones siguientes se describe cómo usar los objetos ID2D1LinearGradientBrush e ID2D1RadialGradientBrush como máscaras de opacidad.

Usar un pincel de degradado lineal como máscara de opacidad

En el diagrama siguiente se muestra el efecto de aplicar un pincel de degradado lineal a un rectángulo que se rellena con un mapa de bits de flores.

diagrama de un mapa de bits de flores con un pincel degradado lineal aplicado

Los pasos siguientes describen cómo volver a crear este efecto.

  1. Defina el contenido que se va a enmascarar. En el ejemplo siguiente se crea un ID2D1BitmapBrush, m_pLinearFadeFlowersBitmap. El modo de extensión x e y- para m_pLinearFadeFlowersBitmap se establece en D2D1_EXTEND_MODE_CLAMP para que se pueda usar con una máscara de opacidad mediante el método 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. Defina la máscara de opacidad. En el siguiente ejemplo de código se crea un pincel de degradado lineal diagonal (m_pLinearGradientBrush) que desaparece de negro totalmente opaco en la posición 0 a blanco completamente transparente en la posición 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. Use el método FillGeometry . En el ejemplo final se usa el método FillGeometry en el pincel de contenido para rellenar un ID2D1RectangleGeometry (m_pRectGeo) con un ID2D1BitmapBrush (m_pLinearFadeFlowersBitmap) y se aplica una máscara de opacidad (m_pLinearGradientBrush).
            m_pRenderTarget->FillGeometry(
                m_pRectGeo, 
                m_pLinearFadeFlowersBitmapBrush, 
                m_pLinearGradientBrush
                );

El código se ha omitido en este ejemplo.

Usar un pincel de degradado radial como máscara de opacidad

En el diagrama siguiente se muestra el efecto visual de aplicar un pincel de degradado radial a un rectángulo que se rellena con un mapa de bits del follaje.

diagrama de un mapa de bits de follaje con un pincel de degradado radial aplicado

En el primer ejemplo se crea un ID2D1BitmapBrush, m_pRadialFadeFlowersBitmapBrush. Para que se pueda usar con una máscara de opacidad mediante el método FillGeometry , el modo de extensión x e y- para m_pRadialFadeFlowersBitmapBrush se establecen en 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++
            }

En el ejemplo siguiente se define el pincel de degradado radial que se usará como máscara de opacidad.

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

En el ejemplo de código final se usa ID2D1BitmapBrush (m_pRadialFadeFlowersBitmapBrush) y la máscara de opacidad (m_pRadialGradientBrush) para rellenar un ID2D1RectangleGeometry (m_pRectGeo).

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

El código se ha omitido en este ejemplo.

Aplicar una máscara de opacidad a una capa

Cuando llamas a PushLayer para insertar un ID2D1Layer en un destino de representación, puedes usar la estructura D2D1_LAYER_PARAMETERS para aplicar un pincel como una máscara de opacidad. En el ejemplo de código siguiente se usa id2D1RadialGradientBrush como máscara de opacidad.

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

Para obtener más información sobre el uso de capas, consulte La información general sobre capas.

Información general sobre los pinceles

Introducción a las capas