如何使用 GDI 将方形位图渲染为任意四边形多边形?

Posted

技术标签:

【中文标题】如何使用 GDI 将方形位图渲染为任意四边形多边形?【英文标题】:How can I render a square bitmap to an arbitrary four-sided polygon using GDI? 【发布时间】:2012-03-25 09:37:48 【问题描述】:

我需要绘制一个正方形图像,映射或转换为编译时未知的四边多边形。我该怎么做?

更长的解释

具体问题是使用非矩形地图投影渲染地图图块。假设我有以下磁贴:

我知道四个角点需要在这里:

鉴于此,我想得到以下输出:

方块可能是:

已旋转;和/或 一端比另一端窄。

认为第二项意味着这需要非仿射变换。

随机附注

四面? 完全正确,瓷砖应该是 映射到具有四个以上点的多边形,但出于我们的目的 并按照绘制的比例,一个正方形->其他四角多边形 改造应该就够了。

为什么最好只使用 GDI? 到目前为止,所有的渲染都是使用 GDI 完成的,我希望保持代码 (a) 快速和 (b) 只需要很少的额外代码 图书馆尽可能。我知道some support for transformations in GDI 并一直在尝试它们 今天,但即使在对它们进行试验之后,我也不确定它们是否 为此目的足够灵活。如果他们是,我还没有设法 弄清楚,所以我真的很感激一些示例代码。

GDI+ 也可以,因为我们在其他地方使用它,但我知道它可能很慢,而且速度是 这里很重要。

另一种选择是Delphi- / C++Builder-特定;这个程序主要是用 C++ 编写的 VCL,并且有问题的图形当前被绘制到 混合了TCanvas methods 和原始 WinAPI/GDI 调用的 TCanvas。

叠加图像: 最后一个警告是图块中的一种颜色可能是颜色键 透明度:即上面图块中的所有白色(比方说)方块 当绘制在下面的任何东西上时应该是透明的。 目前,瓷砖被绘制成正方形或轴对齐的矩形 目标使用TransparentBlt。

对于让这个问题变得更加复杂的所有额外警告,我深表歉意 而不是“我应该使用什么算法?”但我会很乐意接受答案 也只有算法信息。

【问题讨论】:

@NGLN:看起来很完美。我要么忘记了,要么从来不知道这个功能!我明天会尝试它(这里是深夜。)同时,您介意添加它作为答案吗? 糟糕,抱歉:PlgBlt 只能生成平行四边形。 如果速度很重要,您应该放弃 GDI 并开始使用 OpenGL。 Delphi 附带OpenGL 单元,因此您可以快速入门。 (GDI 可能很快足够,但既然你提到速度的重要性......) @AndreasRejbrand,是的... OpenGL 会更快,当然为此。不过,我正在添加到现有视图中,并且不想重写整个内容,因此我更愿意与现有代码集成。但谢谢你的想法!我们实际上是considering using OpenGL elsewhere in the program 很快... @DavidM,我真的不明白你还想要什么......你有完整的来源、项目名称和所需的输出。看看Graphics32的优秀demo:这不是“具体库如何解决问题的具体例子”吗? 【参考方案1】:

您可能还想看看Graphics32。 下面的屏幕截图显示了 GR32 中的 transfrom 演示如何看起来像

【讨论】:

这在演示应用程序中运行良好,但在集成到更大的现有应用程序中时遇到了问题(我在 GR32 论坛上发帖,无需混乱,但主要问题是一些方法链接器找不到 TBitmap32 类,尽管它们在生成的 .hpp 文件中,我看不出有什么问题。)您是否将它与 C++ Builder 一起使用,您是否知道必须做些什么才能获得任何东西演示工作? @David,对不起,我是 Delphi 唯一的人。但是看看我在 GR32 论坛上的回复 @David :) 谢谢。在您的一个 cmets 中,您提到缺少文档。这不是真的,但有些隐蔽。看看here【参考方案2】:

看看3D Lab Vector graphics。 (特别是演示中的“足球场”)。


另一个很酷的资源是AggPas,包含完整源代码 (download)

AggPas 是开源和免费的 2D 矢量图形库。它是 Anti-Grain Geometry 库 - AGG 的 Object Pascal 原生端口,最初由 Maxim Shemanarev 用 C++ 编写。 AggPas 不依赖于任何图形 API 或技术。基本上,您可以将 AggPas 视为一种渲染引擎,它从一些矢量数据在内存中生成像素图像。

perspective 演示如下所示:

改造后:

【讨论】:

看起来很酷。但它只是矢量吗?我正在处理位图 - 光栅图像。 @DavidM,我只看了一眼。我不确定。【参考方案3】:

George Wolberg 的“数字图像变形”中描述了通用技术。看起来this abstract 包含相关数学,this paper 也是如此。您需要创建一个从一个四边形映射到另一个四边形的透视矩阵。上面的链接显示了如何创建矩阵。一旦你有了矩阵,你就可以扫描你的输出缓冲区,执行转换(或者可能是相反的 - 取决于他们给你的),这会给你原始图像中的点,你可以从中复制。

使用 OpenGL 在 4 个点之间绘制一个带纹理的四边形可能更容易,但这并不像您想要的那样使用 GDI。

【讨论】:

所以你实现了一个扫描线算法,很像渲染一个 3D 多边形,使用矩阵来查找原始图像中的像素值? 我将赏金授予上述 Graphics32 答案 - 这是一个有用且快速的库。但这也是一个很好的答案,我很高兴知道算法,如果可以的话,我会给你不止一个投票。

以上是关于如何使用 GDI 将方形位图渲染为任意四边形多边形?的主要内容,如果未能解决你的问题,请参考以下文章

GDI 中的多边形函数

如何在三个js中将多个纹理裁剪为多边形

如何计算具有特定中心的正方形多边形?

FreeType - 纹理图集 - 为什么我的文字渲染为四边形?

GDI 和 GDI+ 中的多边形填充模式

如何在图例中有一个多边形