最好的一组脏矩形

时间:2011-03-23 19:38:07

标签: optimization graphics geometry rectangles dirtyrectangle

我在这里寻找一种算法,独立于特定的编程语言。

问题:

  

我们有一个二维显示区域   (想想像素的简单缓冲区)。   一些像素是周期性的   改变。我们需要找到一套   封装所有的矩形   改变像素。

     

这将是微不足道的,但不可取的,   计算单个,可能   封装所有的大型矩形   改变像素。我们宁愿拥有   多个,小,紧身   矩形下降到指定的最小值   大小(这是一个可变的变量   改变)。

     

例如,假设在...内   整个显示区域,几个像素   左上角改变了一个   右下角有几个像素   改变。我们不想计算   整个单脏的矩形   区域 - 我们反而想要两个脏   矩形:鞋面中的一个小矩形   左边和下面的一个小的   右。

表现至关重要,因此这个问题。

我认为,这个问题一直存在,绝对是在视频编解码器和远程桌面压缩区域。就我而言,在图形图像处理过程中,这是一个反复出现的问题,涉及多个用户同时在共享区域绘图。

是否有人知道已发布的算法或了解您过去使用的解决方案?

谢谢!

3 个答案:

答案 0 :(得分:5)

屏幕视频/远程桌面编解码器通常将屏幕划分为磁贴,然后仅传输已更改磁贴的位图。然后,平铺图像通常是ZLIB压缩的。

有各种方法可以改进这一点,例如

  • 为每个图块添加自己的边界矩形,覆盖该图块中已更改的像素(如果只有少数像素发生更改,则避免重新传输整个图块。)
  • 使用磁贴的先前内容填充压缩器(如果您正在录制正在拖动的窗口或在2D游戏中移动精灵,这会大大提高压缩效率。)

例如,Adobe Flash在其“屏幕视频2”编解码器中使用了所有这三种技术的组合。

如果您不想使用压缩,可以使用拼贴和拼凑的组合。边界框是一个很好的妥协。例如。如果在对角处只有两个更改的像素,则只会更新这两个像素,但如果您有一个分散更改的区域(例如,在文本编辑器中键入),则更改将合并为一些大矩形,这可能比把它分成几百个小矩形。)

答案 1 :(得分:2)

查看R-treequadtree数据结构。

答案 2 :(得分:1)

我的想法,有两个决策选项:

我用某种伪代码写了它。

基本上,对于第一个选项,您决定您的区域必须符合的百分比,以满足最小脏像素数。

对于第二个选项,如果展开以包含此像素,则可以确定此因子的差异或每个区域的脏像素是否会发生太大变化。

    struct DirtyPixelArea
{
    Vec2 topLeft;
    Vec2 size;
    list<Vec2> dirtyPixels;

    void AddPixelToArea();

    int Area();
    int DirtyPixelsArea(); // sums all dirty pixels in area
};

list<DirtyPixelArea>  dirtyPixelsAreaList

void add_dirty_pixel(Vec2 dirtyPixel)
{
    closest_area = find_closest_area_to_pixel(dirtyPixel).copy();

    //option 1 - begin

    closest_area.add_dirty_pixel(dirtyPixel);

    if (closest_area.DirtyPixelsArea() > (closest_area.Area() * 0.25))   // you can experiment on choosing your own dirty pixel factor
    {
        update_area_in_list(closest_area);
    }
    else
    {
        new_area = new DirtyPixelArea();
        new_area.AddPixelToArea(dirtyPixel);
        add_area_in_list(new_area);
    }

    //option 1 - end

    // option 2 - begin
    original_area = find_closest_area_to_pixel(dirtyPixel);
    closest_area.add_dirty_pixel(dirtyPixel)

    original_area_factor = original_area.DirtyPixelsArea() / original_area.Area();
    closest_area_factor = closest_area.DirtyPixelArea() / closest_area.Area();

    if ( closest_area_factor / original_area_factor > 0.5)
    {
        update_area_in_list(closest_area);
    }
    else
    {
        new_area = new DirtyPixelArea();
        new_area.AddPixelToArea(dirtyPixel);
        add_area_in_list(new_area);
    }

    // option 2 - end

}