【问题标题】:How does the fill operation work in paint applications?填充操作在油漆应用中是如何工作的?
【发布时间】:2010-09-21 09:54:54
【问题描述】:

所有绘画程序,无论它们多么简单或复杂,都带有填充工具。这基本上用另一种颜色替换了封闭区域的颜色。我知道有不同的 API 可以做到这一点,但我对算法很感兴趣。实现此工具的有效算法是什么?

我能很快想到的几件事是:

  1. 将图像转换为二进制图,其中要替换颜色的像素为1,所有其他颜色为0
  2. 在要更改的点周围找到一个封闭区域,使内部所有像素为 1,所有相邻像素为 0。

Sample Image

【问题讨论】:

  • @dbr:“邻居”?你们英国人说我们的语言很有趣。 :-) 不过更好的标题!

标签: algorithm image-processing


【解决方案1】:

许多实现都是作为递归的征服和划分算法完成的。如果您对“洪水填充算法”进行快速 google,您会发现大量资源,包括 the topic 上的优秀维基百科页面。

【讨论】:

  • 天哪,动画太棒了!我记得我什么时候可以在我的 Amiga 500 上观看 Deluxe Paint 中的算法。
  • @akuhn 或者在 486 上玩 Scorched Earth 时在游戏中观看。
【解决方案2】:

如果你想要一个不太关心内存效率的高效算法,你可以这样做:

1) 保留您已经访问过的单元格的布尔内存:Vis[]

2) 保留您已访问但尚未标记邻居的点列表:Busy[]

3) 将两者都设为空

4) 将起点添加到Busy

5)

while you have a point P in Busy:
{
    for each neighbour N of the point P for which Vis[N] is still false
    {
       if appropriate (not crossing the boundary of the fill region)
       {
           set Vis[N] to true
           update the colour of N in the bitmap
           add N to the end of Busy[]
       }
       remove P from Busy[]
    }
}

【讨论】:

    【解决方案3】:

    Flood Fill 算法是最常用的。以下是直接来自我的旧大学教科书“使用 OpenGL 的计算机图形学”的一个幼稚版本,作者是 Hearn Baker,第 3 版:

    void floodFill4 (int x, int y, int fillColor, int interiorColor)
    {
      int color;
    
      /* Set current color to fillColor, then perform the following operations */
      getPixel(x, y, color);
      if (color == interiorColor) 
      {
        setPixel(x,y);  // Set color of pixel to fillColor.
        floodFill4(x + 1, y, fillColor, interiorColor);
        floodFill4(x - 1, y, fillColor, interiorColor);
        floodFill4(x, y + 1, fillColor, interiorColor);
        floodFill4(x, y - 1, fillColor, interiorColor);
      }
    }
    

    但是,对于大图像,由于对每个像素进行递归,上述内容可能会给您一个堆栈溢出错误。通常,该算法会被修改,以便在填充一行像素时使用迭代,然后递归地填充上面和下面的行。正如@kasperjj 所说,维基百科有一篇很好的文章。

    【讨论】:

    • 因在上下文中提到堆栈溢出而升级...!
    【解决方案4】:

    这些算法在@​​987654321@ 中有详细讨论。如果你有兴趣了解如何在不使用 DirectX 或 OpenGL API 的情况下光栅化线条、填充多边形、编写 3d 代码,我强烈推荐这本书。当然,对于现实世界的应用程序,您可能希望使用现有的库,但如果您对这些库的工作方式感到好奇,那么这是一本很棒的读物。

    【讨论】:

    • 我引用的《Computer Graphics with OpenGL》这本书对于深入研究 2d 和 3d 渲染背后的理论也是一本极好的书,而且写得很好。它只使用 OpenGL 来展示一些算法和方程是如何应用的。不过,它在数学上相当密集。
    【解决方案5】:

    还可以阅读有关连接组件标签的信息。这是一种查找连接像素的有效方法,同时只访问每个像素两次。

    Wikipedia article.

    这样做的好处是像素值不必相同,或者将像素描述为连接的函数可能不是原始值——也许是梯度。

    【讨论】:

      【解决方案6】:

      总体思路被描述为Flood Fill Algorithm,并且对其进行了各种修改。一种常见的方法是扫描线填充。查看相关问题How Scanline based 2d rendering engines works?

      【讨论】:

        猜你喜欢
        • 2013-03-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多