在哪里可以找到关于实现用于计算“脏矩形”的算法以最小化帧缓冲器更新的参考? 一种显示模型,允许任意编辑并计算更新显示所需的最小“位blit”操作集。

===============>>#1 票数:3

听起来你需要的是你要渲染到屏幕的每个形状的边界框。 请记住,多边形的边界框可以定义为“左下”(最小点)和“右上角”(最大点)。 也就是说,最小点的x分量被定义为多边形中每个点的所有x分量的最小值。 对y分量(在2D的情况下)和边界框的最大点使用相同的方法。

如果每个多边形有一个边界框(也就是“脏矩形”)就足够了,你就完成了。 如果您需要一个整体复合边界框,则应用相同的算法,除了您可以使用最小和最大点填充单个框。

现在,如果您在Java中执行所有这些操作,则可以使用getBound2D()方法直接获取Area (可以从任何Shape构造)的边界框。

===============>>#2 票数:3

Vexi是对此的参考实现。 该类是org.vexi.util.DirtyList (Apache许可证),用作生产系统的一部分,即经过全面测试,并且评论很好。

需要注意的是,当前的类描述有点不准确, “用于保存需要重新绘制的矩形区域列表的通用数据结构,具有智能合并功能。” 实际上它目前没有合并。 因此,您可以将此视为一个基本的DirtyList实现,因为它只与dirty()请求相交,以确保没有重叠的脏区域。

该实现的一个细微差别在于,不是使用Rect或其他类似的区域对象,而是将区域存储在一个int数组中,即在一维数组中以4个int的块存储。 这是为了提高运行时效率,尽管回想起来我不确定它是否有很多优点。 (是的,我实现了它。)将Rect替换为正在使用的数组块应该很简单。

课程的目的是要 对于Vexi,每帧可能会调用脏数千次,因此脏区域与脏请求的交叉必须尽可能快。 不超过4个数字比较用于确定两个区域的相对位置。

由于缺少聚结,它并不完全是最佳的。 虽然它确实确保脏/涂区域之间没有重叠,但最终可能会出现排列的区域并且可以合并到更大的区域 - 因此减少了绘制调用的数量。

代码段。 在线完整代码。

public class DirtyList {

    /** The dirty regions (each one is an int[4]). */
    private int[] dirties = new int[10 * 4]; // gets grown dynamically

    /** The number of dirty regions */
    private int numdirties = 0;

    ...

    /** 
     *  Pseudonym for running a new dirty() request against the entire dirties list
     *  (x,y) represents the topleft coordinate and (w,h) the bottomright coordinate 
     */
    public final void dirty(int x, int y, int w, int h) { dirty(x, y, w, h, 0); }

    /** 
     *  Add a new rectangle to the dirty list; returns false if the
     *  region fell completely within an existing rectangle or set of
     *  rectangles (i.e. did not expand the dirty area)
     */
    private void dirty(int x, int y, int w, int h, int ind) {
        int _n;
        if (w<x || h<y) {
            return;
        }
        for (int i=ind; i<numdirties; i++) {
            _n = 4*i;
            // invalid dirties are marked with x=-1
            if (dirties[_n]<0) {
                continue;
            }

            int _x = dirties[_n];
            int _y = dirties[_n+1];
            int _w = dirties[_n+2];
            int _h = dirties[_n+3];

            if (x >= _w || y >= _h || w <= _x || h <= _y) {
                // new region is outside of existing region
                continue;
            }

            if (x < _x) {
                // new region starts to the left of existing region

                if (y < _y) {
                    // new region overlaps at least the top-left corner of existing region

                    if (w > _w) {
                        // new region overlaps entire width of existing region

                        if (h > _h) {
                            // new region contains existing region
                            dirties[_n] = -1;
                            continue;
                        }// else {
                        // new region contains top of existing region
                        dirties[_n+1] = h;
                        continue;

                    } else {
                        // new region overlaps to the left of existing region

                        if (h > _h) {
                            // new region contains left of existing region
                            dirties[_n] = w;
                            continue;
                        }// else {
                        // new region overlaps top-left corner of existing region
                        dirty(x, y, w, _y, i+1);
                        dirty(x, _y, _x, h, i+1);
                        return;

                    }
                } else {
                    // new region starts within the vertical range of existing region

                    if (w > _w) {
                        // new region horizontally overlaps existing region

                        if (h > _h) {
                            // new region contains bottom of existing region
                            dirties[_n+3] = y;
                            continue;
                        }// else {
                        // new region overlaps to the left and right of existing region
                        dirty(x, y, _x, h, i+1);
                        dirty(_w, y, w, h, i+1);
                        return;

                    } else {
                        // new region ends within horizontal range of existing region

                        if (h > _h) {
                            // new region overlaps bottom-left corner of existing region
                            dirty(x, y, _x, h, i+1);
                            dirty(_x, _h, w, h, i+1);
                            return;
                        }// else {
                        // existing region contains right part of new region
                        w = _x;
                        continue;
                    }
                }
            } else {
                // new region starts within the horizontal range of existing region

                if (y < _y) {
                    // new region starts above existing region

                    if (w > _w) {
                        // new region overlaps at least top-right of existing region

                        if (h > _h) {
                            // new region contains the right of existing region
                            dirties[_n+2] = x;
                            continue;
                        }// else {
                        // new region overlaps top-right of existing region
                        dirty(x, y, w, _y, i+1);
                        dirty(_w, _y, w, h, i+1);
                        return;

                    } else {
                        // new region is horizontally contained within existing region

                        if (h > _h) {
                            // new region overlaps to the above and below of existing region
                            dirty(x, y, w, _y, i+1);
                            dirty(x, _h, w, h, i+1);
                            return;
                        }// else {
                        // existing region contains bottom part of new region
                        h = _y;
                        continue;
                    }
                } else {
                    // new region starts within existing region

                    if (w > _w) {
                        // new region overlaps at least to the right of existing region

                        if (h > _h) {
                            // new region overlaps bottom-right corner of existing region
                            dirty(x, _h, w, h, i+1);
                            dirty(_w, y, w, _h, i+1);
                            return;
                        }// else {
                        // existing region contains left part of new region
                        x = _w;
                        continue;
                    } else {
                        // new region is horizontally contained within existing region

                        if (h > _h) {
                            // existing region contains top part of new region
                            y = _h;
                            continue;
                        }// else {
                        // new region is contained within existing region
                        return;
                    }
                }
            }
        }

        // region is valid; store it for rendering
        _n = numdirties*4;
        size(_n);
        dirties[_n] = x;
        dirties[_n+1] = y;
        dirties[_n+2] = w;
        dirties[_n+3] = h;
        numdirties++;
    }

    ...
}

===============>>#3 票数:3

要构建包含需要重新绘制的所有区域的最小矩形:

  • 从一个空白区域开始(可能是一个设置为0,0,0,0的矩形 - 您可以检测到'无需更新')

对于每个脏区添加:

  • 标准化新区域(即确保左侧小于右侧,顶部小于底部)
  • 如果脏矩形当前为空,请将其设置为提供的区域
  • 否则,将脏矩形的左侧和顶部坐标设置为{dirty,new}中最小的坐标,将右侧和底部坐标设置为{dirty,new}中最大的坐标。

Windows至少维护了一个更新区域 ,该更新区域已被告知,并且由于窗口被遮挡和显示而需要进行任何重新绘制。 区域是由许多可能不连续的矩形,多边形和椭圆组成的对象。 您通过调用InvalidateRect告诉Windows需要重新绘制的部分屏幕 - 对于更复杂的区域,还有一个InvalidateRgn函数。 如果您选择在下一个WM_PAINT消息到达之前进行一些绘制,并且您希望将其从脏区域中排除,则可以使用ValidateRect和ValidateRgn函数。

当您使用BeginPaint开始绘画时,您提供了一个PAINTSTRUCT,Windows填充了有关需要绘制内容的信息。 其中一个成员是包含无效区域的最小矩形。 你可以使用GetUpdateRgn获取区域本身(你必须在BeginPaint之前调用它,因为BeginPaint将整个窗口标记为有效)如果你想在有多个小的无效区域时最小化绘图。

我认为,因为在最初编写这些环境时,最小化绘图在Mac和X上很重要,所以有相同的机制来维护更新区域。

===============>>#4 票数:2

我刚刚写了一个Delphi类来计算两个图像的差异矩形,并且对它的运行速度感到非常惊讶 - 足够快以在短计时器中运行以及在用于记录屏幕活动的鼠标/键盘消息之后运行。

关于它是如何工作的一步一步的要点是:

  1. 通过矩形将图像细分为逻辑12x12。

  2. 循环遍历每个像素,如果有差异,那么我告诉像素所属的子矩形,其中一个像素和其中的区别。

  3. 每个子矩形都会记住它自己最左边,最顶部,最右边和最底部差异的坐标。

  4. 一旦发现所有差异,我会遍历所有有差异的子矩形,如果它们彼此相邻则形成更大的矩形,并使用最左边,最顶部,最右边和底部 - 这些子矩形的大多数差异,以使我使用的实际差异矩形。

这对我来说似乎很有效。 如果您还没有实现自己的解决方案,请告诉我,如果您愿意,我会通过电子邮件发送给您我的代码。 截至目前,我是StackOverflow的新用户,所以如果你欣赏我的答案,请投票。 :)

===============>>#5 票数:2

查看R树四叉树数据结构。

===============>>#6 票数:2

你用的是什么语言? 在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,我会这样做:

  • 创建一个sprite类,它的update(),move()等方法设置了一个“脏”标志。
  • 为每个精灵保持一个矩形
  • 如果您的API支持更新rects列表,请在sprite为脏的rects列表中使用它。 在SDL中,这是SDL_UpdateRects。
  • 如果你的API不支持更新rects列表(我从来没有机会使用除SDL以外的任何东西,所以我不知道),测试一下是否可以更快地调用blit函数多次或使用一次大直。 我怀疑使用一个大矩形的任何API都会更快,但同样,除了SDL之外我还没有使用任何东西。

  ask by translate from so

未解决问题?本站智能推荐:

3回复

最好的一组脏矩形

我在这里寻找一种算法,独立于特定的编程语言。 问题: 我们有一个二维显示区域(想象简单的像素缓冲区)。 定期地,一些像素被改变。 我们需要找到一组封装所有更改像素的矩形。 计算一个封装所有已更改像素的单个可能很大的矩形将是微不足道的,但这是不可取的。 我们宁愿将多个
2回复

饼切片边界矩形

如何计算饼图切片边界矩形。 半径(r),中心点(x0,y0),StartAngle(a0),EndAngle(a1)和drawDirection(顺时针或逆时针)变量是已知的。
1回复

WPF性能。 错误的脏矩形计算

我目前正在处理与WPF富客户端LOB应用程序中的性能问题有关的客户分配。 问题是该应用程序运行非常缓慢/缓慢。 特别是数据表的处理(滚动,排序,选择)非常慢,并且使应用程序无法使用。 当一个包含几个文本框,组合框和标签的选项卡被打开并保持空闲状态(等待用户输入)时,我分析了系统状态
2回复

如何在任意四边形内刻出矩形或圆形

这可能是一个更注重数学的问题,但由于在CS上下文中,所以想在这里提出。 我正在寻找在另一个(任意)四边形内刻一个矩形,该四边形具有最大可能的高度和宽度。 由于我认为算法会相似,因此我想看看是否也可以用一个圆来做。 更清楚地说,以边界四边形为例,我的意思是。 这是我要实现的刻刻最大
5回复

如何确定多个元素的边界矩形?

我想实现一个算法,它将找到轮廓的边界矩形(已经由另一个算法确定)。 我唯一拥有的是二值化图像(如下图所示)。 基本想法是: 采取这样的事情 - 预处理的二值化图像 并产生这样的东西
1回复

Raspberry PI上XBMC上的脏区

我有一个树莓派,并从raspbmc.com加载了最新的独立版。 使用XBMC时,我看到CPU使用率始终高于90%。 在查看XBMC Wiki和常见问题解答之后,脏区域似乎是减少CPU使用率的一种流行方法。 我在/home/pi/.xbmc/userdata/创建了文件advanceds
1回复

如何逐像素比较两个图像并从图像的脏部分中构筑新图像

我正在使用robot.screenCapture()和frame bufferedImage1捕获屏幕。 我再次捕获桌面屏幕和帧bufferedImage2 。 请告诉我如何逐像素比较这两个图像( bufferedImage1和bufferedImage2 )。 如果存在任何差异,那么
1回复

位图并不完全适合android中的矩形

我正在使用android-V11开发一个RDP客户端应用程序。 服务器:屏幕分为4个部分,以字节[],左,上,右,下,每帧的屏幕分辨率(宽度 - > 1024/1280,高度 - ?768/1024)值发送图像数据对客户。 客户端:我使用表面视图来显示从服务器接收的图像。 我
1回复

查找给定重叠矩形集合的多边形顶点的算法

寻找最少的矩形以覆盖一组矩形而不重叠的算法 很好的解释,加雷斯。 我想弄清楚的是如何实现解决方案的反面,即如何从一组矩形开始并到达多边形。 我的解决方案适用于所有情况,除非两个或多个矩形的部分或整个边缘相互重叠。 如何消除构成重叠边缘的点?
1回复

分组矩形(获取矩形的边界框)

什么是获取一组随机(最多40个,不多)矩形的“最终”边界框的好方法? 最后,我的意思是所有边界框都不会相交。 编辑:我的第一个例子是错误的。 我要寻找的结果是一组rect,其中每组重叠时形成一个实体几何体。 他们不是分开的。 由于rect每次都是随机的,并且rect的数量相对较