Обзор маски непрозрачности
В этом разделе описывается, как использовать растровые изображения и кисти для определения маски непрозрачности. Он содержит следующие разделы.
- Предварительные требования
- Что такое маска непрозрачности?
- Использовать растровое изображение в качестве маски непрозрачности с помощью метода FillOpacityMask
- Использовать кисть в качестве маски непрозрачности с помощью метода FillGeometry
- Применить маску непрозрачности к уровню
- Связанные темы
Необходимые условия
В этом обзоре предполагается, что вы знакомы с основными операциями рисования 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 установлены на D2D1_EXTEND_MODE_CLAMP.
- Третий параметр, ID2D1Brush, указывает кисть, используемую в качестве маски непрозрачности. Эта кисть может быть ID2D1LinearGradientBrush, ID2D1RadialGradientBrushили ID2D1BitmapBrush. (Технически вы можете использовать ID2D1SolidColorBrush, но использование сплошной кисти цвета в качестве маски непрозрачности не дает интересных результатов.)
В следующих разделах описывается использование ID2D1LinearGradientBrush и объектов ID2D1RadialGradientBrush в качестве маски непрозрачности.
Использование линейной градиентной кисти как маски непрозрачности
На следующей схеме показан эффект применения линейной градиентной кисти к прямоугольнику, заполненного растровым изображением цветов.
В следующих шагах описано, как повторно создать этот эффект.
Определите содержимое для маскирования. В следующем примере создается 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++ }
Определите маску непрозрачности. В следующем примере кода создается диагональная линейная градиентная кисть (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();
}
- Используйте метод 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++ |
---|
|
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;
}
Для получения дополнительной информации об использовании слоев см. "Обзор слоев" .
Связанные разделы
-
Обзор кистей