抗锯齿图像变换 (Aaform)
最优图像变换
引言
Aaform
(抗锯齿图像变换)是我开发的一种将矩形位图转换为任意四边形(包括凸/复杂四边形)的技术。我相信这是变换现有图像的最佳方法。Aaform
使用了许多将在本文中提到的几何概念。您可以 在此处 阅读相关内容(代码示例是 VB.NET,但任何程序员都应该能够理解它们)。
下面是此网站 Logo 的一个任意样本变换。

工作原理 - 简介
Aaform
包含两个主要函数:Transform
和 CreateTransform
。Transform
用于将一个图像变换为另一个图像。当您想在保持边缘美观的同时将一个图像变换为另一个图像时,这很有用。CreateTransform
只是创建一个足够大的空白图像来容纳变换后的图像,然后调用 Transform
。下面是 transform
函数的 C++ 原型:
transform(HBITMAP src, HBITMAP dst, std::vector<double> xcorner,
std::vector<double> ycorner, aaf_callback callbackfunc)
src
- 要变换的Bitmap
dst
- 用于绘制变换后图像的Bitmap
xcorner
- 变换后图像的x
坐标数组。xcorner.size()
必须等于4
ycorner
- 变换后图像的y
坐标数组。ycorner.size()
必须等于4
callbackfunc
- 回调函数有两个目的。首先,它允许客户端代码更新transform
的进度;其次,它为客户端代码提供了取消变换的机会。
(xcorner[0], ycorner[0])
构成变换后图像的左上角,(xcorner[1], ycorner[1])
是右上角,(xcorner[2], ycorner[2])
是右下角,(xcorner[3], ycorner[3])
是左下角。
工作原理 - 生成网格
在检查完一些条件并分配内存后,transform
所做的第一件事就是为变换后图像中的每个像素创建角的网格。srcwidth
是传递给 src
的 bitmap
的宽度,srcheight
是传递给 src
的 bitmap
的高度。
循环从 x = 0
到 srcwidth
,creategrid
创建一条线(以 AX + BY = C 的形式)从点 (x / srcwidth)
百分比处的线段(由 (xcorner[0], ycorner[0])-(xcorner[1],ycorner[1])
组成 [顶边])向下延伸,然后沿由 (xcorner[3], ycorner[3])-(xcorner[2],ycorner[2])
组成的线段([底边])向下以相同的百分比延伸。
接下来,执行一个嵌套的 for
循环,该循环从 y = 0
到 srcheight
。它创建一条线,从点 (y / srcheight)
百分比处的线段(由 (xcorner[0], ycorner[0])-(xcorner[3],ycorner[3])
组成 [左边])向下延伸,然后沿由 (xcorner[1], ycorner[1])-(xcorner[2],ycorner[2])
组成的线段([右边])向下以相同的百分比延伸。
最后,它找到两条线的交点,并将该点添加到我们的网格中,作为位于 (x, y)
的像素的右上角。由于像素共享角,因此无需计算每个像素的所有四个角。例如,要获得像素 (0, 0)
的右上角,只需找到像素 (1, 0)
的左上角即可。
工作原理 - 主循环
现在我们有了每个变换后像素每个角的坐标,我们所要做的就是找出每个目标像素上的重叠区域。显然,我们不想将每个变换后的像素与每个目标像素进行比较,因此我们将每个变换后的像素与变换后像素的 x 和 y 坐标的最小 floor 和最大 ceil 之间的每个目标像素进行比较。然后,我们为扫描区域内的每个目标像素找到变换后像素的多边形与目标像素的正方形的重叠面积。多边形重叠相当复杂,如果您想了解其工作原理,请 在此处 查看。(多边形重叠部分在多边形部分介绍)然后,这两个多边形的重叠可以用来确定变换后的像素在目标像素中应占的比例。
每个目标像素都是 1x1 的正方形,因此最大面积为 1 平方单位。因此,在变换后的像素完全包围目标像素的情况下,最大重叠面积为 1。因此,重叠 1.0 表示变换后的像素在目标像素中占 100% 的比例,因此它们应该是相同的颜色。重叠 0.5 表示 50% 的比例,重叠 0.0 表示没有比例。这就是 Aaform
的精髓。

附加功能
Aaform
还包含几个使用 CreateTransform
执行更具体任务的函数:
Rotate
:按指定的度数旋转图像Stretch
:按指定的比例拉伸图像SkewHorizontal
:按指定的度数(-90, 90)水平倾斜图像SkewVerticle
:按指定的度数(-90, 90)垂直倾斜图像
实现
我用三种语言(C++、VB6 和 VB.NET)编写了 Aaform
。因此,我将不详细介绍如何在每种语言中使用该算法。有关每个函数用法的详细信息,请参阅上面列出的示例项目。
结论
我相信 Aaform
在数据表示方面能产生最佳质量的图像变换(数据丢失最少)。我不是视觉如何解释光的专家,所以很难说它在视觉上代表变换后的图像效果如何(但显然,效果相当好)。
历史
- 2006 年 2 月 24 日:首次发布