Direct2D教程(八)梯度色画刷

2020年StyleGAN2人脸生成与梯度追踪实战解析 生成对抗网络(GAN)是生成式AI早期实现高保真人脸合成的核心范式,其原理依赖判别器与生成器的动态博弈,在潜在空间中构建可微分、可干预的数据分布映射。技术价值在于突破传统图像建模的重构约束,支持亚像素级细节生成与细粒度语义控制;典型应用场景涵盖AI头像服务、虚拟人内容生产及AIGC可解释性审计。而梯度追踪与潜在空间监控(如W空间漂移检测、层间梯度热力图)构成模型可观测性的工程基石,使‘黑箱生成’具备调试路径与质量锚点。本文聚焦2020年工业级落地关键——StyleGAN2架构下的全链路拆解与Tracking 阅读详情

概述

单色画刷产生的颜色是单一的,比如一个红色画刷只能输出红色,而梯度色画刷则不同,它可以输出多种颜色,这些颜色通常是连续的,从一个颜色平滑过渡到另一个颜色,看起来有渐变的效果。梯度色画刷又分为两种,一种是ID2D1LinearGradientBrush(线性梯度色画刷),另一种是ID2D1RadialGradientBrush(放射梯度色画刷),下图显示了这两种画刷的效果。

线性梯度色画刷

这种画刷的颜色从一个位置线性渐变到另外一个位置,所以在创建这种画刷之前需要确定以下两个属性

  • 起始位置及颜色
  • 终止位置及颜色

在Direct2D中,结构体D2D1_GRADIENT_STOP用来表示一个位置及其颜色,其定义如下:

struct D2D1_GRADIENT_STOP {
  FLOAT        position;
  D2D1_COLOR_F color;
};

其中第一个成员position表示位置,这个值得范围必须是[0.0, 1.0]。第二个成员color表示颜色。我们用两个这样的结构体变量就可以表示起始/终止位置及颜色了。

在创建画刷时,需要指定画刷的会制范围,如果待填充图形的范围大于画刷的会制范围,我们需要告诉D2D如何处填充超出范围的部分。这需要通过颜色的扩展方式来指定,颜色扩展的方式用D2D1_EXTEND_MODE这个枚举类型来表示,它的定义如下:

typedef enum  { 
  D2D1_EXTEND_MODE_CLAMP   = 0,
  D2D1_EXTEND_MODE_WRAP    = 1,
  D2D1_EXTEND_MODE_MIRROR  = 2
} D2D1_EXTEND_MODE;

如果大家了解纹理的话,对这几种方式一定不陌生,他们的含义如下:

  • D2D1_EXTEND_MODE_CLAMP,表示按照边缘的颜色进行扩展
  • D2D1_EXTEND_MODE_WRAP,表示重复画刷的颜色
  • D2D1_EXTEND_MODE_MIRROR,也是重复画刷的颜色,不过是以相反的方向进行,所以像镜面效果一样

这三种扩展方式的效果图如下,这里,矩形的宽度是画刷绘制范围的2倍,也就是说,颜色的扩展是从矩形的中间开始的。

D2D1_EXTEND_MODE_CLAMP

D2D1_EXTEND_MODE_WRAP

D2D1_EXTEND_MODE_MIRROR

下面开始具体的创建步骤,首先定义两个梯度点并指定其位置及颜色,这里第一个点位置是0,颜色是黄色,第二个点位置是1,颜色是红色。

D2D1_GRADIENT_STOP gradientStops[2] ;
gradientStops[0].color = D2D1::ColorF(D2D1::ColorF::Yellow) ;
gradientStops[0].position = 0.f ;
gradientStops[1].color = D2D1::ColorF(D2D1::ColorF::Red) ;
gradientStops[1].position = 1.f ;

其次,创建梯度点集合,这个集合将作为参数用来创建梯度色画刷,我们使用函数CreateGradientStopCollection来完成这个任务,它的定义如下:

virtual HRESULT CreateGradientStopCollection(
  [in]   const D2D1_GRADIENT_STOP *gradientStops,
  UINT gradientStopsCount,
  D2D1_GAMMA colorInterpolationGamma,
  D2D1_EXTEND_MODE extendMode,
  [out]  ID2D1GradientStopCollection **gradientStopCollection
) = 0;

参数说明:

  • gradientStops,梯度点数组,也就是上面刚刚创建的。
  • gradientStopsCount,梯度点个数,这里是两个。
  • colorInterpolationGamma,这个参数用来控制颜色插值的方式,有如下两种:

typedef enum  { 
  D2D1_GAMMA_2_2  = 0,
  D2D1_GAMMA_1_0  = 1
} D2D1_GAMMA;
这两种方式的效果图如下,这里我们使用D2D1_GAMMA_2_2。

extendMode,指定颜色超出绘制范围时如何扩展。这里我们使用D2D1_EXTEND_MODE_CLAMP,也就是按照边缘色扩展。

gradientStopCollection,这个参数用来接收创建后的梯度点集合。

创建梯度点集合的代码如下,所有参数前面均已说明。

// Create gradient stops collection
ID2D1GradientStopCollection* pGradientStops = NULL ;
hr = pRenderTarget->CreateGradientStopCollection(
    gradientStops,
    2, 
    D2D1_GAMMA_2_2,
    D2D1_EXTEND_MODE_CLAMP,
    &pGradientStops
    ) ;
if (FAILED(hr))
{
    MessageBox(NULL, "Create gradient stops collection failed!", "Error", 0);
}

最后,创建线性梯度色画刷。我们使用函数CreateLinearGradientBrush,看看它的定义:

virtual HRESULT CreateLinearGradientBrush(
  [in]            const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES *linearGradientBrushProperties,
  [in, optional]  const D2D1_BRUSH_PROPERTIES *brushProperties,
  [in]            ID2D1GradientStopCollection *gradientStopCollection,
  [out]           ID2D1LinearGradientBrush **linearGradientBrush
) = 0;
参数说明:

  • linearGradientBrushProperties,用来指定画刷的起始位置和终止位置。
  • brushProperties,这是个可选参数,用来指定画刷的透明度及变换矩阵,这里我们指定其为NULL。
  • gradientStopCollection,梯度点集合,一般我们指定两个即可,分别是起始位置和终止位置。
  • linearGradientBrush,用来接收创建好的画刷。

具体代码如下,画刷的起始和结束位置分别对应矩形的左上角点和右下角点。

// Create a linear gradient brush to fill in the rectangle
hr = pRenderTarget->CreateLinearGradientBrush(
    D2D1::LinearGradientBrushProperties(
    D2D1::Point2F(roundRect.rect.left, roundRect.rect.top),
    D2D1::Point2F(roundRect.rect.right, roundRect.rect.bottom)),
    pGradientStops,
    &pLinearGradientBrush
    ) ;

if (FAILED(hr))
{
    MessageBox(hWnd, "Create linear gradient brush failed!", "Error", 0) ;
    return ;
}

效果图

放射梯度色画刷

这种画刷的颜色从一个中心点向周围扩散,呈放射状,这可能也是其名字的由来吧。创建这种画刷的步骤和上面一样,先创建梯度点及其集合,然后使用函数CreateRadialGradientBrush创建画刷,关于如何创建梯度点及其集合,前面已经说了,所以这里只看创建画刷的步骤。函数CreateRadialGradientBrush的定义如下:

HRESULT CreateRadialGradientBrush(
  const D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES &radialGradientBrushProperties,
  [in]   ID2D1GradientStopCollection *gradientStopCollection,
  [out]  ID2D1RadialGradientBrush **radialGradientBrush
);
参数说明:

  • radialGradientBrushProperties,画刷属性,用以下结构体来表示:
    struct D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES {
      D2D1_POINT_2F center;
      D2D1_POINT_2F gradientOriginOffset;
      FLOAT         radiusX;
      FLOAT         radiusY;
    };
    • center, 梯度中心点,从此点开始向外围放射
    • gradientOriginOffset,起始点偏移,一般设置为(0,0)
    • radiusX,椭圆x轴长度
    • radiusY,椭圆y轴长度
  • gradientStopCollection,梯度点集合
  • radialGradientBrush,用来接收创建后的画刷

代码如下:

创建椭圆

D2D1_ELLIPSE g_Ellipse = D2D1::Ellipse(D2D1::Point2F(300, 300), 200, 150);
创建画刷,这里我们指定起始颜色为黄色,终止颜色为蓝色,填充图形为椭圆,颜色从椭圆的中心向周围发散。

// Create a linear gradient brush to fill in the rectangle
hr = pRenderTarget->CreateRadialGradientBrush(
    D2D1::RadialGradientBrushProperties(
    g_Ellipse.point,
    D2D1::Point2F(0, 0),
    g_Ellipse.radiusX,
    g_Ellipse.radiusY),
    pGradientStops,
    &pRadialGradientBrush
    ) ;

if (FAILED(hr))
{
    MessageBox(hWnd, "Create linear gradient brush failed!", "Error", 0) ;
    return ;
}
效果图

使用梯度色画刷配合椭圆及圆角矩形可以创建出非常漂亮的Button控件,如果你喜欢自定义控件,不妨试一试。

== Happy Coding ==

http://www.cnblogs.com/graphics/archive/2012/11/22/2764876.html

direct_visual_lidar_calibration全攻略:5分钟搞定任意型号雷达相机标定 本文详细介绍了direct_visual_lidar_calibration工具,这是一种无需标定板、支持任意雷达与相机型号的通用外参标定方案。通过像素级直接稀疏对齐算法,该工具能在单帧数据上实现全自动标定,声称五分钟内即可完成从数据采集到结果输出的全过程,极大提升了多传感器融合工程部署的效率与鲁棒性。 阅读详情

相关推荐

YOLOv11改进 - C3k2融合 | C3k2融合加权卷积wConv2D:无损替换标准卷积,增强空间建模与特征提取质量

本文介绍了加权卷积及其在YOLOv11中的结合。加权卷积是一种新型卷积机制,通过引入密度函数,根据邻域像素与中心像素的距离自适应调整权重,打破传统卷积等权处理的局限。它在不增加可训练参数的情况下实现“距离感知”的特征提取,通过哈达玛积将密度函数与卷积核结合。其优化框架采用双优化器,分别对卷积核权重和密度函数进行优化。我们将加权卷积集成进YOLOv11的C3k2模块,形成C3k2_wConv2d。实验显示,与标准卷积相比,加权卷积显著降低了损失,降低了参数。

魔改工程师的博客 785

深入浅出WPF学习笔记

Property理解为对象的属性,本质上是访问字段提供的一种封装方法(get/set)。 Attribute是对象的特性,本质上是一个类,其为目标元素提供关联附加信息,并在运行期以反射的方式来获取附加信息。它的作用更类似于注释。

weixin_45955386的博客 600

火电厂网络安全监测装置技术规范拆解:I/II区旁路部署与51台设备接入

电力监控系统网络安全监测涉及主机设备、网络设备与安全防护设备的统一接入与事件上送。其核心原理是通过旁路部署采集安全事件,经DL/T634.5104协议上送调度平台,实现涉网区域的可观测性。技术价值在于不中断生产业务的前提下满足合规要求,适用于火电厂I/II区安防改造场景。本文围绕新澳火电厂技术规范,拆解51台设备的AGENT适配、SNMP V3配置及104双向认证等落地要点。

weixin_30595035的博客 422

如何实现弧形渐变(以WPF为例)

三种方法实现渐变圆环

羽木落凡的博客 2685

3分钟搞懂欧式距离变换(EDT):从暴力算法到Felzenszwalb的演进史

本文系统梳理了欧式距离变换(EDT)从暴力算法到高效线性算法的演进历程。重点解析了光栅扫描算法和Felzenszwalb算法的核心思想与实现,并探讨了其在机器人路径规划中生成欧几里得符号距离场(ESDF)的关键应用,为开发者提供了清晰的算法选型与实战指南。

fern8的博客 978

使用TinyProxy搭建代理服务器

背景 办公电脑所在网络无法连接外网,机房服务器可以连接外网,通过服务器代理上网; 一、CentOS下TinyProxy安装–搭建代理服务器 TinyProxy是个轻量级简单的HTTP/HTTPS代理程序,GitHub和官网,安装方式这里主要介绍两种 CentOS下yum安装,参考:TinyProxy安装 Docker安装 先安装docker环境yum install docker -y 二、Win10下使用 ...

椰汁菠萝 1万+

Direct2D教程IV——笔刷(Brush)对象

目前博客园中成系列的Direct2D的教程有 1、万一的 Direct2D 系列,用的是Delphi 2009 2、zdd的 Direct2D 系列,用的是VS中的C++ 3、本文所在的 Direct2D教程 系列,用的是VS2010的Visual Basic语言(可以很方便的转为C#),基于Windows API Code Pack 1.1。   还有官方的说明文档 Direct2D ...

weixin_34417200的博客 229

【芯片驱动】2. CMT2300A配合硬件测试(灵敏度和发射功率)的软件实现

前言 在开发一款无线射频产品的时候,软件是一部分,硬件也是一部分。而决定无线收发性能的,首先是硬件的匹配电路,然后才到软件部分的优化。 一款无线射频产品,首先需要先决定是在那个频率范围内(当然是国家允许的范围内),然后硬件则需要在基于这个频点范围进行硬件的参数匹配,具体又分为发送功率匹配、天线匹配、和接收灵敏度的匹配。 现在我们使用2300a这款无线芯片来说,除非自己的团队是射频专家,则可以自己进行无线外围电路的设计外,另外一种更加快捷的方式,就是寻找原厂技术支持,他们会给...

sishuihuahua的博客 7055

createRadialGradient用法

方法的核心原理是通过定义两个圆来指定渐变的范围,并在此范围内进行颜色插值。通过调整圆心位置、半径以及颜色停止点,可以创建各种复杂的渐变效果。希望这些解释能帮助你更好地理解和使用方法。如果你有更多问题或需要进一步的帮助,请随时告诉我!

909

在树莓派上部署训练好的YOLO模型

.pt.模型转换为onnx格式的模型,树莓派上部署模型

pai_da_xing8的博客 3887

MPC模型预测控制实战:从理论到代码实现(Python示例)

本文详细介绍了MPC模型预测控制的实战应用,从理论到Python代码实现。通过构建系统模型、预测方程、优化问题及约束处理,展示了如何实现一个完整的MPC控制器。文章还提供了水箱液位控制的应用案例,帮助读者掌握MPC在工业控制中的实际应用。

weixin_42653691的博客 461

Direct2D教程(七)单色画刷

概述画刷是D2D中最重要的资源之一,无论绘制什么图形,都离不开画刷,它好比是画家手中的画笔。画刷由render target创建,是设备相关的资源,如果渲染设备重建了,那么需要重新建立画刷。Direct2D中有以下四种类型的画刷,这些画刷全部继承自ID2D1Brush,并且有一些共同特征(比如设置和获取opacity,以及transform)。ID2D1SolidColorBrush 单色画刷ID

Augusdi的专栏 2872

摄像头模组CCM简介

摄像头模组,全称Camera Compact Module,简写为CCM。CCM 包含几大件: 镜头(lens)、音圈马达(VCM)、传感器(sensor)、软板(FPC)、图像处理芯片(DSP)。工作原理:物体通过镜头(lens)聚集的光,通过CMOS或CCD集成电路,把光信号转换成电信号,再经过内部图像处理器(ISP)转换成数字图像信号输出到数字信号处理器(DSP)加工处理,转换成标准的GRB、YUV等格式图像信号。摄像头模组主要由以下几个部分组成:镜头(Lens):将光线汇聚到图像传感器上。

m0_73482095的博客 1万+

Direct2D教程(十一)几何变换

什么是几何变换(Transform) 在图形学中,主要有三种几何变换,分别是平移(Translate),旋转(Rotation)和缩放(Scaling)。在D2D中,这三种变换都有实现,而且还有一种不太常见的变换,倾斜(Skewing)。 Transform是指将一个点从一个坐标系映射到另一个坐标系,或者将一个点从同一个坐标系的...

weixin_34252686的博客 558

ROS从入门到精通2-7:Gazebo仿真之动态生成障碍物

动态生成障碍物在机器人导航、碰撞避障算法测试、多机协同等领域应用广泛,可以帮助开发人员快速测试,本文介绍该技术并提供基于ROS Gazebo的实现

FRIGIDWINTER的博客 4899

YOLO11涨点优化:卷积魔改 | DCNv2升级版本,助力检测

在DCN的基础上,增加了2个创新点,分别是调制模块和使用多个调制后的DCN模块,从形成了DCN的升级版本——DCNv2

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 967

EDPLVO: Efficient Direct Point-Line Visual Odometry论文笔记

论文笔记EDPLVO: Efficient Direct Point-Line Visual Odometry。基于点和线的直接前端视觉里程计。如果有疑问或者我写错的,欢迎讨论交流。

qq_52383168的博客 1466

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

LDSO: Direct Sparse Odometry with Loop Closure(翻译)

准备把高博最新的论文LDSO翻译下来: 原文 摘要— 在本文中,我们提出直接视觉里程计(DSO)[1]到单目视觉SLAM具有闭环检测和姿势图优化的系统(LDSO)。作为直接法,DSO可以利用任何具有足够的强度梯度的图像像素,使其在缺少特征点的区域仍具有很强的鲁棒性。 LDSO保持这种鲁棒性,而同时确保在前端跟踪中检测到的特征角点的可重复性。这种可重复性保证了传统的基于特征的词袋(BoW)的闭...

qq_36122936的博客 3918

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

【大模型】通信元语和相关概念|NCCL梯度|Allreduce|Scatter|Broadcast|Gather

ReduceReduce(归约) 是一种聚合操作,与“拆分”相反,它的核心逻辑是将多个数据元素合并成一个结果。拆分是 Map 的职责,而非 Reduce。Reduce 的“归约”本质是通过迭代合并,逐步缩小数据规模,最终得到全局结果。以下是关键要点:1.定义与功能Reduce通过一个二元操作(如加法、取最大值等)逐步合并数据,最终输出一个单一值。例如:对执行 Reduce(求和),结果为10。2.与 Map 的关系在MapReduce模型中:Map。

我的笔记本 3959

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

上一篇: Direct2D教程(七)单色画刷
下一篇: Direct2D教程(九)渲染位图
Augusdi
博客等级 码龄19年 1万+粉丝 1016原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值