Krzysztof Papciak
Krzysztof Papciak

Reputation: 37

Floodfill algorithm - problem with implementing pseudocode

I'm trying to implement the pseudocode for flood fill algorithm. I took it from Graphics Gemes 1.
Here is the pseudocode:

enter image description here

Unfortunateley, when I implemented it in JavaScript, it hangs when I use my floodfill tool. Here is my code:

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 is a flat array later displayed in the browser.
toolColor is 4-element array containing color for area to be filled with.
What I'm doing wrong? Other more simple algorithms works with inside and set functions so they seem to be ok.

If You need more of the code I can send it privately.

Edit: I updated the code and now it fills only part of area.
enter image description here

Upvotes: 0

Views: 186

Answers (1)

Krzysztof Papciak
Krzysztof Papciak

Reputation: 37

Ok, I fixed the code. It is very fast. Maybe someone will make use of it.

Here is updated code:

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);
    }
}

I made a basic mistake. skip value was outside the last loop, but it should be inside.

Moreover, y value was incorrectly initialized in loop, should be: y = n[3] + n[0]; instead of y = n[0];

The code on English Wikipedia related to this algorithm seems to be incorrect.

I made speed tests of this algorithm. My implementation is about 1.5 times faster than the code on Wikipedia.

Upvotes: 1

Related Questions