GDI+ Graphics Obj - 使用 GDI 直接绘制到 DC 时消除锯齿丢失

Posted

技术标签:

【中文标题】GDI+ Graphics Obj - 使用 GDI 直接绘制到 DC 时消除锯齿丢失【英文标题】:GDI+ Graphics Obj - antialias lost when drawing straight to DC with GDI 【发布时间】:2015-12-29 09:07:15 【问题描述】:

我们目前正在将旧应用程序转换为通过 GDI+ 进行绘图,而不是直接使用 GDI。随着我们逐步翻译系统,有时我们需要从 Gdiplus::Graphics 对象中获取 HDC,以便允许尚未翻译的代码使用 GDI 直接绘制到它。

绘图进行得很好,只是我们似乎在使用 GDI 直接绘制到 DC 的图像上丢失了抗锯齿。如果从 Graphics 对象中获取 DC 后,我们在整个区域上绘制一个填充的矩形,然后继续绘制,结果很好。如果我们直接绘制所有内容,则无需抗锯齿。

void Draw(Gdiplus::Graphics& renderContext)

    auto hdc = renderContext.GetHDC();
    auto dc = HDC::FromHandle(nativeDC);

    //Required to antialias drawing below
    dc->FillSolidRect(GetClientRect(), RGB(255, 255, 255));
    /* Do Drawing */

    dc ->Detach();
    renderContext.ReleaseHDC(hdc );

更准确地说,抗锯齿 alpha 似乎被展平了,这解释了为什么在绘制之前在 GDI 中填充一个矩形会消除伪影。 如果您在一个位图上绘制抗锯齿,然后尝试在另一个位图上进行 alphablend 混合,您可能会得到类似的效果 - 顶部的 alpha 信息被展平,然后在 ColorMatrix 中指定的新 alpha 值应用于整个图像。

如果有人能提供一些见解,了解当您从图形对象中获取/释放 HDC 时究竟发生了什么,以及为什么使用 GDI 绘图会直接丢失 alpha,我将不胜感激。

【问题讨论】:

图像没有抗锯齿。如果图像包含透明像素(alpha 【参考方案1】:

支持 HDC 的位图是副本,而不是原件,如 described here。

在位图支持的 GDI+ 图形对象上使用 GDI

当为支持的 Graphics 对象调用 Graphics::GetHDC() 时 通过位图而不是屏幕,创建了一个内存 HDC,并创建了一个新的 HBITMAP 被创建并选择到内存 HDC 中。这段新记忆 位图不是用原始位图的图像初始化的,而是 带有哨兵模式,它允许 GDI+ 跟踪对 位图。通过使用对内存位图所做的任何更改 GDI 代码的变化在哨兵模式的变化中变得明显。什么时候 Graphics::ReleaseHDC() 被调用,这些更改被复制回 原始位图......此外,这种方法存在性能成本,因为 GDI+ 必须将更改复制回原始位图。

显然,当您使用 GDI 在 HDC 上绘图时,您不会获得任何抗锯齿功能。 GDI 不支持它。这就是 GDI+ 的用途。

【讨论】:

以上是关于GDI+ Graphics Obj - 使用 GDI 直接绘制到 DC 时消除锯齿丢失的主要内容,如果未能解决你的问题,请参考以下文章

C# WPF 怎样使用 Graphics呢?

C# 获取指定 “QQ头像“ 绘制 “圆形头像框“GDI(Graphics)

C# 使用GDI(Graphics)绘制 应用 网站 “登录验证码“

C# 使用GDI(Graphics)绘制 应用 网站 “登录验证码“

GDI+ 绘图基础-图形设备&创建Graphics对象

C# 获取指定 “QQ头像“ 绘制 “圆形头像框“GDI(Graphics)