【问题标题】:Floodfill algorithm - problem with implementing pseudocode填充算法 - 实现伪代码的问题
【发布时间】:2021-08-18 02:40:28
【问题描述】:

我正在尝试实现洪水填充算法的伪代码。我从 Graphics Gemes 1 中获取它。
这是伪代码:

不幸的是,当我在 JavaScript 中实现它时,当我使用我的填充工具时它会挂起。 这是我的代码:

function inside(x, y) {
    const q = 4 * (x + y * that.w);
    const color = [img.data[q], img.data[q + 1], img.data[q + 2], img.data[q + 3]];
    return color[0] === toolColor[0] &&
        color[1] === toolColor[1] &&
        color[2] === toolColor[2];
}

function set(x, y) {
    const q = 4 * (x + y * that.w);
    img.data[q] = that.color.r;
    img.data[q + 1] = that.color.g;
    img.data[q + 2] = that.color.b;
    img.data[q + 3] = that.color.a;
}

function doFloodFill(x, y) {
    let skip = false, x1, x2, dy, start;
    const s = [];

    s.push([y, x, x, 1]);
    s.push([y + 1, x, x, -1]);

    while (s.length > 0) {
        const n = s.pop();
        y = n[3] + n[0];
        x1 = n[1];
        x2 = n[2];
        dy = n[3];
        x = x1;
        while (x >= 0 && inside(x, y)) {
            set(x, y);
            x--;
        }
        if (x >= x1) {
            //skip
            skip = true;
        }
        if (!skip) {
            start = x + 1;
            if (start < x1) {
                s.push([y, start, x1 - 1, -dy]);
            }
            x = x1 + 1;
        }
        do {
            if (!skip) {
                while (x <= that.w && inside(x, y)) {
                    set(x, y);
                    x++;
                }
                s.push([y, start, x - 1, dy]);
                if (x > x2 + 1) {
                    s.push([y, x2 + 1, x - 1, -dy]);
                }
            }
            //skip
            x++;
            while (x <= x2 && !inside(x, y)) {
                x++;
            }
            skip = false;
        } while (x < x2);
        start = x;
    }
}

img.data 是稍后显示在浏览器中的平面数组。
toolColor 是包含要填充区域颜色的 4 元素数组。
我做错了什么? 其他更简单的算法适用于 inside 和 set 函数,因此它们似乎没问题。

如果您需要更多代码,我可以私下发送。

编辑:我更新了代码,现在它只填充了部分区域。

【问题讨论】:

    标签: javascript graphics 2d implementation flood-fill


    【解决方案1】:

    好的,我修复了代码。它非常快。也许有人会利用它。

    这里是更新的代码:

    function inside(x, y) {
        const q = 4 * (x + y * that.w);
        const color = [img.data[q], img.data[q + 1], img.data[q + 2], img.data[q + 3]];
        return color[0] === toolColor[0] &&
            color[1] === toolColor[1] &&
            color[2] === toolColor[2];
    }
    
    function set(x, y) {
        const q = 4 * (x + y * that.w);
        img.data[q] = that.color.r;
        img.data[q + 1] = that.color.g;
        img.data[q + 2] = that.color.b;
        img.data[q + 3] = that.color.a;
    }
    
    function doFloodFill(x, y) {
        let skip = false, x1, x2, dy, start;
        const s = [];
    
        s.push([y, x, x, 1]);
        s.push([y + 1, x, x, -1]);
    
        while (s.length > 0) {
            const n = s.pop();
            y = n[3] + n[0];
            x1 = n[1];
            x2 = n[2];
            dy = n[3];
            x = x1;
            while (x >= 0 && inside(x, y)) {
                set(x, y);
                x--;
            }
            if (x >= x1) {
                //skip
                skip = true;
            }
            if (!skip) {
                start = x + 1;
                if (start < x1) {
                    s.push([y, start, x1 - 1, -dy]);
                }
                x = x1 + 1;
            }
            do {
                if (!skip) {
                    while (x <= that.w && inside(x, y)) {
                        set(x, y);
                        x++;
                    }
                    s.push([y, start, x - 1, dy]);
                    if (x > x2 + 1) {
                        s.push([y, x2 + 1, x - 1, -dy]);
                    }
                }
                //skip
                x++;
                while (x <= x2 && !inside(x, y)) {
                    x++;
                }
                start = x;
                skip = false;
            } while (x < x2);
        }
    }
    

    我犯了一个基本错误。 skip 值在最后一个循环之外,但它应该在里面。

    另外,y 值在循环中被错误初始化,应该是:y = n[3] + n[0]; 而不是y = n[0];

    英文维基百科上与此算法相关的代码似乎不正确。

    我对这个算法进行了速度测试。我的实现比维基百科上的代码快大约 1.5 倍。

    【讨论】:

    • 主题通常由您作为作者“关闭”,接受答案。这可以是你的答案。但是您应该包含有助于未来读者解决类似问题的详细信息。你是如何修复代码的?
    • 或者您似乎用更新的代码更新了您的问题?如果是这样,请将其移至您的答案,以便线程遵循问答格式。这样,未来的读者可以轻松地将您的原始代码与您的解决方案进行比较。
    猜你喜欢
    • 2019-01-07
    • 1970-01-01
    • 2017-05-09
    • 1970-01-01
    • 2013-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多