Поделиться через


Общие сведения о масках непрозрачности

В этом разделе описывается использование растровых изображений и кистей для определения масок непрозрачности. В него входят следующие разделы.

Предварительные требования

В этом обзоре предполагается, что вы знакомы с основными операциями рисования Direct2D, как описано в пошаговом руководстве Создание простого приложения Direct2D . Вы также должны быть знакомы с различными типами кистей, как описано в обзоре кистей.

Что такое маска непрозрачности?

Маска непрозрачности — это маска, описанная кистью или растровым изображением, которая применяется к другому объекту, чтобы сделать этот объект частично или полностью прозрачным. Маска непрозрачности использует сведения альфа-канала, чтобы указать, как исходные пиксели объекта смешиваются с конечным целевым объектом назначения. Прозрачные части маски указывают области, в которых скрыто базовое изображение, в то время как непрозрачные части маски указывают, где отображается маскировка.

Существует несколько способов применения маски непрозрачности:

  • Используйте метод ID2D1RenderTarget::FillOpacityMask . Метод FillOpacityMask закрашивает прямоугольную область целевого объекта отрисовки, а затем применяет маску непрозрачности, определяемую растровым изображением. Используйте этот метод, если маска непрозрачности является растровым изображением и требуется заполнить прямоугольную область.
  • Используйте метод ID2D1RenderTarget::FillGeometry . Метод FillGeometry закрашивает внутреннюю часть геометрии указанным id2D1BitmapBrush, а затем применяет маску непрозрачности, определяемую кистью. Используйте этот метод, если вы хотите применить маску непрозрачности к геометрии или использовать кисть в качестве маски непрозрачности.
  • Используйте ID2D1Layer для применения маски непрозрачности. Используйте этот подход, если вы хотите применить маску непрозрачности к группе содержимого рисунка, а не только к одной фигуре или изображению. Дополнительные сведения см. в разделе Общие сведения о слоях.

Использование растрового изображения в качестве маски непрозрачности с методом FillOpacityMask

Метод FillOpacityMask закрашивает прямоугольную область целевого объекта отрисовки, а затем применяет маску непрозрачности, определяемую id2D1Bitmap. Используйте этот метод при наличии растрового изображения, которое вы хотите использовать в качестве маски непрозрачности для прямоугольной области.

На следующей схеме показан эффект применения маски непрозрачности ( ID2D1Bitmap с изображением цветка) к ID2D1BitmapBrush с изображением растения папоротника. Полученное изображение представляет собой растровое изображение растения, обрезанного по форме цветка.

схема цветочного рисунка, используемого в качестве маски непрозрачности на изображении растения папоротника

В следующих примерах кода показано, как это делается.

В первом примере загружается следующее растровое изображение , m_pBitmapMask, для использования в качестве маски растрового изображения. На следующем рисунке показаны выходные данные, которые создаются. Обратите внимание, что, хотя непрозрачная часть растрового изображения отображается черным цветом, информация о цвете на растровом рисунке не влияет на маску непрозрачности. Используются только сведения о непрозрачности каждого пикселя на растровом рисунке. Полностью непрозрачные пиксели на этом растровом изображении были окрашены в черный цвет только для иллюстрации.

Изображение маски точечных рисунков цветов

В этом примере ID2D1Bitmap загружается вспомогательным методом LoadResourceBitmap, определенным в другом месте примера.

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

В следующем примере определяется кисть m_pFernBitmapBrush, к которой применяется маска непрозрачности. В этом примере используется ID2D1BitmapBrush , содержащий изображение папоротника, но вместо него можно использовать ID2D1SolidColorBrush, ID2D1LinearGradientBrush или ID2D1RadialGradientBrush . На следующем рисунке показаны выходные данные, которые создаются.

иллюстрация растрового рисунка, используемого кистью растрового рисунка

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


            }

Теперь, когда маска непрозрачности и кисть определены, можно использовать метод FillOpacityMask в методе отрисовки приложения. При вызове метода FillOpacityMask необходимо указать тип используемой маски непрозрачности: D2D1_OPACITY_MASK_CONTENT_GRAPHICS, D2D1_OPACITY_MASK_CONTENT_TEXT_NATURAL и D2D1_OPACITY_MASK_CONTENT_TEXT_GDI_COMPATIBLE. Значения этих трех типов см. в разделе D2D1_OPACITY_MASK_CONTENT.

Примечание

Начиная с Windows 8, D2D1_OPACITY_MASK_CONTENT не требуется. См. метод ID2D1DeviceContext::FillOpacityMask , который не имеет D2D1_OPACITY_MASK_CONTENT параметра.

 

В следующем примере в режиме сглаживания целевого объекта отрисовки задается значение D2D1_ANTIALIAS_MODE_ALIASED , чтобы маска непрозрачности работала правильно. Затем он вызывает метод FillOpacityMask и передает ему маску непрозрачности (m_pBitmapMask), кисть, к которой применяется маска непрозрачности (m_pFernBitmapBrush), тип содержимого внутри маски непрозрачности (D2D1_OPACITY_MASK_CONTENT_GRAPHICS) и область для рисования. На следующем рисунке показаны выходные данные, которые создаются.

изображение растения папоротника с примененной маской непрозрачности

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

Код в этом примере опущен.

Использование кисти в качестве маски непрозрачности с методом FillGeometry

В предыдущем разделе описано, как использовать ID2D1Bitmap в качестве маски непрозрачности. Direct2D также предоставляет метод ID2D1RenderTarget::FillGeometry , который позволяет при необходимости указать кисть в качестве маски непрозрачности при заполнении ID2D1Geometry. Это позволяет создавать маски непрозрачности из градиентов (с помощью ID2D1LinearGradientBrush или ID2D1RadialGradientBrush) и растровых изображений (с помощью ID2D1Bitmap).

Метод FillGeometry принимает три параметра:

  • Первый параметр, ID2D1Geometry, определяет фигуру для рисования.
  • Второй параметр, ID2D1Brush, указывает кисть, используемую для рисования геометрии. Этот параметр должен быть id2D1BitmapBrush , для которого для режимов x- и y-extend задано значение D2D1_EXTEND_MODE_CLAMP.
  • Третий параметр, ID2D1Brush, указывает кисть, используемую в качестве маски непрозрачности. Это может быть ID2D1LinearGradientBrush, ID2D1RadialGradientBrush или ID2D1BitmapBrush. (Технически можно использовать ID2D1SolidColorBrush, но использование сплошной цветной кисти в качестве маски непрозрачности не дает интересных результатов.)

В следующих разделах описывается использование объектов ID2D1LinearGradientBrush и ID2D1RadialGradientBrush в качестве масок непрозрачности.

Использование кисти линейного градиента в качестве маски непрозрачности

На следующей схеме показан эффект применения линейной градиентной кисти к прямоугольнику, заполненном растровым изображением цветов.

схема цветочного растрового рисунка с примененной линейной градиентной кистью

В следующих шагах описывается, как повторно создать этот эффект.

  1. Определите маскировку содержимого. В следующем примере создается ID2D1BitmapBrush, m_pLinearFadeFlowersBitmap. Для режима расширения x- и y- для m_pLinearFadeFlowersBitmap задано значение D2D1_EXTEND_MODE_CLAMP , чтобы его можно было использовать с маской непрозрачности с помощью метода 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. Определите маску непрозрачности. В следующем примере кода создается диагональная линейная кисть градиента (m_pLinearGradientBrush), которая исчезает из полностью непрозрачного черного цвета в позиции 0 до полностью прозрачного белого в позиции 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. Используйте метод FillGeometry . В последнем примере метод FillGeometry используется для кисти содержимого для заполнения ID2D1RectangleGeometry (m_pRectGeo) идентификатором ID2D1BitmapBrush (m_pLinearFadeFlowersBitmap) и применения маски непрозрачности (m_pLinearGradientBrush).
            m_pRenderTarget->FillGeometry(
                m_pRectGeo, 
                m_pLinearFadeFlowersBitmapBrush, 
                m_pLinearGradientBrush
                );

Код в этом примере опущен.

Использование радиальной градиентной кисти в качестве маски непрозрачности

На следующей схеме показан визуальный эффект применения радиальной градиентной кисти к прямоугольнику, заполненном растровым изображением листвы.

Схема растрового изображения листвы с примененной радиальной градиентной кистью

В первом примере создается ID2D1BitmapBrush, m_pRadialFadeFlowersBitmapBrush. Чтобы его можно было использовать с маской непрозрачности методом FillGeometry , для режима расширения x- и y- для m_pRadialFadeFlowersBitmapBrush устанавливается значение 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++
            }

В следующем примере определяется радиальная кисть градиента, которая будет использоваться в качестве маски непрозрачности.

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

В последнем примере кода используется ID2D1BitmapBrush (m_pRadialFadeFlowersBitmapBrush) и маска непрозрачности (m_pRadialGradientBrush) для заполнения ID2D1RectangleGeometry (m_pRectGeo).

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

Код в этом примере опущен.

Применение маски непрозрачности к слою

При вызове PushLayer для отправки ID2D1Layer в целевой объект отрисовки можно использовать структуру D2D1_LAYER_PARAMETERS для применения кисти в качестве маски непрозрачности. В следующем примере кода в качестве маски непрозрачности используется ID2D1RadialGradientBrush .

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

Дополнительные сведения об использовании слоев см. в разделе Общие сведения о слоях.

Обзор кистей

Общие сведения о слоях