【问题标题】:Pattern Flood Fill Algorithm图案填充算法
【发布时间】:2016-01-22 22:47:54
【问题描述】:

我已经实现了一个泛色填充算法,该算法可以正确地用于纯色填充。现在我正在研究图案填充,并决定添加一个标志来查看如何填充该区域(使用颜色或图案)。但是,当使用带有图案填充的算法时,在绘制区域时会卡住。

这是我使用纯色的原始代码:

void floodFillStack(int x, int y, byte newColor, byte oldColor) {
    int y1;
    if (oldColor == newColor) return;
    if (get_pixel(x, y) != oldColor) return;
    //draw current scanline from start position to the top 
    y1 = y;
    while (y1 < h && get_pixel(x, y1) == oldColor) {
        plot_pixel(x, y1, newColor);
        y1++;
    }    

    //draw current scanline from start position to the bottom
    y1 = y - 1;
    while (y1 >= 0 && get_pixel(x, y1) == oldColor) {
        plot_pixel(x, y1, newColor);
        y1--;
    }

    //test for new scanlines to the left
    y1 = y;
    while (y1 < h && get_pixel(x, y1) == newColor) {
        if (x > 0 && get_pixel(x - 1, y1) == oldColor) {
            floodFillStack(x - 1, y1, newColor, oldColor);
        } 
        y1++;
    }
    y1 = y - 1;
    while (y1 >= 0 && get_pixel(x, y1) == newColor) {
        if (x > 0 && get_pixel(x - 1, y1) == oldColor) {
            floodFillStack(x - 1, y1, newColor, oldColor);
        }
        y1--;
    } 

    //test for new scanlines to the right 
    y1 = y;
    while (y1 < h && get_pixel(x, y1) == newColor) {
        if (x < w - 1 && get_pixel(x + 1, y1) == oldColor) {           
            floodFillStack(x + 1, y1, newColor, oldColor);
        } 
        y1++;
    }
    y1 = y - 1;
    while (y1 >= 0 &&get_pixel(x, y1) == newColor) {
        if (x < w - 1 && get_pixel(x + 1, y1) == oldColor) {
            floodFillStack(x + 1, y1, newColor, oldColor);
        }
        y1--;
    }
}

这是模式修改(它仍然适用于纯色)。

int pattern1[6][6] = { {0,1,0,1,0,1},
                       {1,0,1,0,1,0},
                       {0,1,0,1,0,1},
                       {1,0,1,0,1,0},
                       {0,1,0,1,0,1},
                       {1,0,1,0,1,0} };             
int pattern2[6][6] = { {0,0,1,1,0,0},
                       {0,1,0,0,1,0},
                       {1,0,0,0,0,1},
                       {1,0,0,0,0,1},
                       {0,1,0,0,1,0},
                       {0,0,1,1,0,0} };

void floodFillStack(int x, int y, byte newColor, byte oldColor, int pattern_fill) {
    int y1;
    if (oldColor == newColor) return;
    if (get_pixel(x, y) != oldColor) return;
    //draw current scanline from start position to the top 
    y1 = y;
    while (y1 < h && get_pixel(x, y1) == oldColor) {
        if (pattern_fill == 0) {
            if (fill_pattern == 1) {
                if (pattern1[x%6][y1%6] == 1) {
                    plot_pixel(x, y1, newColor);
                }
            } else {
                if (pattern2[x%6][y1%6] == 1) {
                    plot_pixel(x, y1, newColor);    
                }               
            }
        } else {                
            plot_pixel(x, y1, newColor);
        }
        y1++;
    }    
    //draw current scanline from start position to the bottom
    y1 = y - 1;
    while (y1 >= 0 && get_pixel(x, y1) == oldColor) {
        if (pattern_fill == 0) {
            if (fill_pattern == 1) {
                if (pattern1[x%6][y1%6] == 1) {
                    plot_pixel(x, y1, newColor);
                }
            } else {
                if (pattern2[x%6][y1%6] == 1) {
                    plot_pixel(x, y1, newColor);
                }               
            }
        } else {
            plot_pixel(x, y1, newColor);
        }
        y1--;
    }
    //test for new scanlines to the left
    y1 = y;
    while (y1 < h && get_pixel(x, y1) == newColor) {
        if (x > 0 && get_pixel(x - 1, y1) == oldColor) {
            floodFillStack(x - 1, y1, newColor, oldColor, pattern_fill);
        } 
        y1++;
    }
    y1 = y - 1;
    while (y1 >= 0 && get_pixel(x, y1) == newColor) {
        if (x > 0 && get_pixel(x - 1, y1) == oldColor) {
            floodFillStack(x - 1, y1, newColor, oldColor, pattern_fill);
        }
        y1--;
    } 
    //test for new scanlines to the right 
    y1 = y;
    while (y1 < h && get_pixel(x, y1) == newColor) {
        if (x < w - 1 &&get_pixel(x + 1, y1) == oldColor) {           
            floodFillStack(x + 1, y1, newColor, oldColor, pattern_fill);
        } 
        y1++;
    }
    y1 = y - 1;
    while (y1 >= 0 && get_pixel(x, y1) == newColor) {
        if (x < w - 1 && get_pixel(x + 1, y1) == oldColor) {
            floodFillStack(x + 1, y1, newColor, oldColor, pattern_fill);
        }
        y1--;
    }
}

谁能帮我看看问题所在?

编辑:

感谢 WeatherVane 的建议。该算法不再卡住,但它并没有覆盖整个区域。这是一张照片:

【问题讨论】:

  • 去掉空行并正确缩进代码。
  • @PabloEstrada 如果你的洪水空间不是太大,你可以考虑使用递归。代码会简单很多。
  • 感谢您的建议,但我担心内存问题。我确实尝试过使用递归,但是在使用该算法时我的堆栈用完了,这就是为什么我将其更改为问题中的那个。
  • 我可以看到pattern_fill,但看不到fill_pattern。当pattern1pattern2 中有0 元素时,您不会填充。您是否应该使用这些蒙版填充两种颜色中的一种,而不是什么都不做?
  • 您好,谢谢。 fill_pattern 是我程序中的一个全局变量,仅用于在模式 1 和模式 2 之间进行选择。我现在总是将其设置为 1。我将 0 表示为“空”像素,所以如果我的矩阵上有 1,我只关心绘画。你认为这是算法的问题吗?

标签: c algorithm graphics


【解决方案1】:

如果您忽略模式掩码中的 0 值,您的填充可能会失败。取而代之的是,总是用两种颜色中的一种填充(两者都不同于背景)。

您还必须更改一些条件测试。而不是

(... == newColor)

你可以使用

(... != oldColor)

(... == newColor1 || ... == newColor2)

【讨论】:

    【解决方案2】:

    当您使用纯色填充时,从oldColor 开始的每个像素都会更改为newColor。这意味着在此过程中稍后对该像素的测试将不会再次与它匹配。

    当您尝试填充图案时,其中一些像素将保持为oldColor。你陷入了一个无限循环,一遍又一遍地重新测试那些相同的像素。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-03
      • 1970-01-01
      • 2012-06-14
      • 2023-03-23
      相关资源
      最近更新 更多