将绘图描述转换为位图的快速方法?
Posted
技术标签:
【中文标题】将绘图描述转换为位图的快速方法?【英文标题】:Fast way of converting a drawing description into a bitmap? 【发布时间】:2022-01-18 10:39:31 【问题描述】:首先,不知道具体如何发布,甚至不知道在哪里问,所以请多多包涵。
在我们正在开发的软件中,我们有描述场景的形状......将其视为高度简化的 svg。在我们的例子中,我们只有矩形(半打,给或取),由它们的高度、宽度、旋转和中心位置定义。
我们需要用这种场景的图像(150x100px)以高频率(大约每 10 毫秒)渲染一个矩阵(即二维数组),但我找不到这样做的算法或库;我能做到的最好的事情是使用自制算法约 50 毫秒,但这还不够好。
我自己的算法大致可以:
drawing = [[0 for i in width] for _ in height]
for shape in shapes:
__calculate_intersection(shape, 0, width, 0, height)
def __calculate_intersection(shape, x1, x2, y1, y2):
global drawing
if x1 == x2 or y1 == y2:
return
if x1 + 1 == x2 and y1 + 1 == y2:
# If we are in a single cell, it is just
# checking whether the center of the cell is inside the object
if drawing[x1][y1] == 0:
if shape.is_point_in_obj(x1, y1):
drawing[x1][y1] = 100
return
if shape.bounding_box() does not touch our drawing:
return
else:
# if the area intersects the object bbox,
# then we iterate the recursion by dividing
# the area along its longer side
if i2 - i1 > j2 - j1:
self.__calculate_intersection(o, i1, i1 + (i2 - i1) // 2, j1, j2)
self.__calculate_intersection(o, i1 + (i2 - i1) // 2, i2, j1, j2)
else:
self.__calculate_intersection(o, i1, i2, j1, j1 + (j2 - j1) // 2)
self.__calculate_intersection(o, i1, i2, j1 + (j2 - j1) // 2, j2)
return
显然我需要一个更好的算法。外面有这样的东西吗?或者更好的是,是否有任何 Python 库来实现这个目标?还是我必须进行一些 GPU 编程?为什么 Tkinter Canvas 可以在不到 1 毫秒的时间内以高清质量渲染它,而我却在为这么简单的要求而苦恼?
【问题讨论】:
分享6个典型形状的参数和你的演绎如何... 150x100 像素很小,几乎没有足够的空间来绘制几个矩形。 10 毫秒的渲染时间似乎是永恒的。您需要对边缘进行抗锯齿处理吗? 【参考方案1】:解决方案的简要说明:
计算四个顶点的坐标,并按Y递增排序(不需要全排序,有8种可能的排序);
将多边形分成三个水平线区域(你会得到 2 个三角形和一个梯形);
对于三个区域,在穿过它们的整数纵坐标处绘制所有水平线,并计算与斜边的两个交点;
填充交叉点之间的水平线。
【讨论】:
有很多可能的微优化。【参考方案2】:有很多方法。一种适用于这种情况的简单快速的方法是:
-
用 0s 初始化矩阵
对于每个形状:
对于形状接触的每条线:
为形状左边界的像素添加 +1。如果它不在图像的左边缘,则只需将 +1 添加到行首即可。
在形状右边界之后的像素上添加 -1。如果那会超出图像的右边缘,那么就跳过它。 (如果它不在左边缘,那么你不应该做这条线 - 形状不会碰到它)。
完成所有形状后,对于每一行:
计算每行的总和,将像素更改为 100(黑色),总和 > 0,和 0,总和 == 0。
这样,任何被形状覆盖的像素都将变为黑色。这非常快,因为您只处理单个形状的边缘,最后一次完成所有区域着色。
【讨论】:
以上是关于将绘图描述转换为位图的快速方法?的主要内容,如果未能解决你的问题,请参考以下文章