脏矩形
在哪里可以找到实现一种用于计算"脏矩形"以最小化帧缓冲区更新的算法的参考?一个显示模型,它允许任意编辑并计算更新显示所需的最少"位位模糊"操作集。
解决方案
回答
要构建包含所有需要重新粉刷区域的最小矩形:
- 从空白区域开始(也许将矩形设置为0,0,0,0-我们可以将其检测为"不需要更新")
对于添加的每个脏区:
- 归一化新区域(即确保左小于右,上小于下)
- 如果脏矩形当前为空,则将其设置为提供的区域
- 否则,将脏矩形的左坐标和顶坐标设置为{dirty,new}中的最小值,将右坐标和底坐标设置为{dirty,new}中的最大值。
Windows至少会维护已获悉的更改的更新区域,以及由于遮挡和显示窗口而需要进行的任何重新绘制。区域是由许多可能不连续的矩形,多边形和椭圆组成的对象。我们通过调用InvalidateRect告诉Windows有关需要重绘屏幕的一部分,对于更复杂的区域,还有一个InvalidateRgn函数。如果我们选择在下一个WM_PAINT消息到达之前进行一些绘制,并且希望将其从脏区中排除,则可以使用ValidateRect和ValidateRgn函数。
当我们开始使用BeginPaint绘画时,我们将提供一个PAINTSTRUCT,Windows会填充有关需要绘画的内容的信息。成员之一是包含无效区域的最小矩形。如果要在有多个小的无效区域时最小化绘图,则可以使用GetUpdateRgn获取区域本身(必须在BeginPaint之前调用此区域,因为BeginPaint将整个窗口标记为有效)。
我想假设,当最初编写这些环境时,在Mac和X上最小化绘图很重要,因此存在维护更新区域的等效机制。
回答
我们使用什么语言?在Python中,Pygame可以为我们做到这一点。使用RenderUpdates组和一些带有image和rect属性的Sprite对象。
例如:
#!/usr/bin/env python import pygame class DirtyRectSprite(pygame.sprite.Sprite): """Sprite with image and rect attributes.""" def __init__(self, some_image, *groups): pygame.sprite.Sprite.__init__(self, *groups) self.image = pygame.image.load(some_image).convert() self.rect = self.image.get_rect() def update(self): pass #do something here def main(): screen = pygame.display.set_mode((640, 480)) background = pygame.image.load(open("some_bg_image.png")).convert() render_group = pygame.sprite.RenderUpdates() dirty_rect_sprite = DirtyRectSprite(open("some_image.png")) render_group.add(dirty_rect_sprite) while True: dirty_rect_sprite.update() render_group.clear(screen, background) pygame.display.update(render_group.draw(screen))
如果我们不使用Python + Pygame,则可以执行以下操作:
- 制作一个由update(),move()等组成的Sprite类。方法设置一个"脏"标志。
- 为每个精灵保持一个矩形
- 如果API支持更新rect列表,请在sprite脏的rect列表上使用该列表。在SDL中,这是SDL_UpdateRects。
- 如果API不支持更新rect列表(我从来没有机会使用SDL之外的任何东西,所以我不知道),请测试一下是否多次调用blit函数或者一次调用blit函数更快大矩形。我怀疑使用一个大的rect会更快地使用任何API,但是同样,我除了SDL之外没有使用其他任何东西。
回答
听起来我们需要的是一个要在屏幕上渲染的每种形状的边界框。请记住,多边形的边界框可以定义为"左下"(最小点)和"右上"(最大点)。即,最小点的x分量被定义为多边形中每个点的所有x分量的最小值。对y分量(在2D情况下)和边界框的最大点使用相同的方法。
如果每个多边形都有一个边界框(又称"脏矩形")就足够了,那就好了。如果我们需要一个整体的合成边界框,则可以应用相同的算法,只是我们可以使用最小和最大点填充单个框。
现在,如果我们使用Java进行所有操作,则可以使用getBound2D()方法直接获取"区域"的边界框(可以从任何"形状"构建)。
回答
我最近才写了一个Delphi类来计算两个图像的差异矩形,并且它运行的速度足够快,可以在短时间内运行,并在鼠标/键盘消息记录屏幕活动之后运行,这让我感到惊讶。
其工作原理的逐步要点是:
- 通过矩形将图像细分为逻辑12x12.
- 循环遍历每个像素,如果存在差异,则告诉子矩形该像素所属的像素之一,以及其中一个像素存在差异。
- 每个子矩形都记住它自己的最左,最顶,最右和最底的差异的坐标。
- 找到所有差异后,我将遍历所有具有差异的子矩形,如果它们彼此相邻并使用最左侧,最顶部,最右侧和最底部的矩形,则在其中形成更大的矩形这些子矩形的大多数差异使我使用的实际差异矩形。
这对我来说似乎很好。如果我们尚未实现自己的解决方案,请告诉我,如果我们愿意,我会通过电子邮件将代码发送给我们。另外,到目前为止,我是StackOverflow的新用户,因此,如果我们欣赏我的回答,请对其进行投票。 :)