使用 Windows GDI 进行抗锯齿
一篇关于使用纯 Windows GDI 实现简单但高效的抗锯齿方法的文章


引言
本文介绍了一种简单但有效的方法,仅使用纯 Windows GDI 实现实时抗锯齿(是的,实时)。GDI 中没有默认方法可以直接执行此操作。所有 GDI 方法,如 LineTo()
、Ellipse()
等,都会执行绘图,但在将像素渲染到内存或屏幕位图中时不会考虑抗锯齿。那么该如何实现呢?嗯,这里有一个可能的答案。
背景
在 Code Project 上有一些(但不多)文章讨论了在 Windows GDI 下进行绘图时的抗锯齿问题。事实上,抗锯齿应该产生高质量的渲染效果,没有锯齿边缘。完成绘图需要更多的 CPU 周期,但最终效果非常好。有关锯齿问题和可能解决方案的详细说明,请阅读 CT Graphics - Anti Alias C++ Drawing 或 Antialiasing - Wu Algorithm。人们会找到足够的信息来构建他们自己的抗锯齿渲染方法,毋庸置疑。
Using the Code
本文没有提供特殊的类或方法,只有非常容易实现的通用算法和下载部分中的演示项目。以下是伪代码
//
// 1. Create original bitmap for drawing
// 2. Create temporary bitmap (2x, 4x or 8x) larger than the original bitmap
// 3. Render your graphics to this large temporary bitmap
// (use any GDI method, pen or brush you like)
// but scale the graphics appropriately
// 4. Draw this temporary bitmap on the original bitmap scaled
// (i.e. using StretchDIBits() method or any other you like),
// but call SetStretchBltMode(HALFTONE)
// before this last step for the original DC
// (which holds the original bitmap), and after scaling restore it back
//
完成这四个步骤后,你就完成了。你将在目标位图上获得非常漂亮的图形。
关于性能代价
在考虑应用所述方法的性能代价时,必须考虑一些事项
- 由于 Windows GDI 在渲染方面并非速度之王,因此原始位图必须具有合理的尺寸,例如 640*480 像素,才能使用 4x4 抗锯齿进行超采样,或者 320*240 像素才能使用 8x8 抗锯齿进行超采样。这些设置可以在几乎没有优化的实时循环中工作,但如果你更喜欢更大的高质量渲染图像,那么就忘记使用 GDI 进行实时渲染吧。对于这种情况来说,它太慢了。但是,如果你没有要处理的实时项目,你可以渲染任何大小的图像。只有系统上可用的空闲 RAM 才能阻止你。
- 将抗锯齿网格从 2x2 增加到 4x4 会使内存消耗增加 4 倍,而这比保存原始位图所需的内存多 16 倍。这是使用这种简单方法所付出的真正代价。
- 对于动画,请保持较低的抗锯齿网格大小,不超过 2x2。这既能提供相当好的渲染效果,又能提供良好的帧速率。
关注点
我发现了一种简单的方法,仅使用 Windows GDI 实现抗锯齿,而无需第三方库,无需 GDI+ 等。将最终结果与商业库进行比较非常有趣。