Общие сведения о масках непрозрачности
В этом разделе описывается использование растровых изображений и кистей для определения масок непрозрачности. В него входят следующие разделы.
- Предварительные условия
- Что такое маска непрозрачности?
- Использование растрового изображения в качестве маски непрозрачности с методом 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-extend задано значение 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;
}
Дополнительные сведения об использовании слоев см. в разделе Общие сведения о слоях.
Связанные темы