Search code examples
javarecursionstack-overflow

How to make fill method for photo editor?


I am making a pixel art editor in java, just for fun, and I ran into a problem. the problem occurred when I was trying to make the fill function. here is the code

private void fill(int x, int y){
    Color beforeColor = img[x][y];
    img[x][y] = foregroundColor;

    if(x-1 >= 0){
        if(img[x-1][y] == beforeColor){
            fill(x-1, y);
        }
    }

    if(x+1 >= 0){
        if(img[x+1][y] == beforeColor){
            fill(x+1, y);
        }
    }

    if(y-1 >= 0){
        if(img[x][y-1] == beforeColor){
            fill(x, y-1);
        }
    }

    if(y+1 >= 0){
        if(img[x][y+1] == beforeColor){
            fill(x, y+1);
        }
    }
}

img is an array of awt Color objects.

this method basically checks around the specified pixel for pixels of the same colour and then runs the method again for the next and the next until the whole area get filled.

if you know anything about the stack in the computer and recursion, then you'll probably realise that this will quickly cause a stackoverflowerror and halt the program. what I am trying to figure out is a way around recursion. Could someone please point me in the right direction around recursion and stackoverflowerror? thanks in advance to people who can help.


Solution

  • Might be that you could use a list: initially you fill it with the pixel that you want to start with. Then you have a loop that iterates until the list is empty. In the loop you take one pixel from the list and check its color. If the color matches recolor it and its neightbors to the list. If the color does not match ignore the pixel. So I would use a little helper class that stores the coordinates of a pixel. So it could look like that (some error checks,... might be missing, but that might be a way to go):

    class PixelCoordinate {
        public int x;
        public int y;
        public PixelCoordinate(int x, int y) {
            this.x = x; this.y = y;
        }
    }
    
    Color beforeColor = img[x][y];
    List<PixelCoordinate> worklist = new ArrayList<PixelCoordinate>();
    // The pixel to start with
    worklist.add(new PixelCoordinate(x, y));
    while (worklist.isEmpty() == false) {
        // Take one pixel from the list
        PixelCoordinate pixel = list.get(0);
        list.remove(0);
    
        // Check its color
        if (img[x][y].equals(beforeColor) {
            // Apply new color
            img[x][y] = foregroundColor;
            // Check neighbors
            if (x-1 >= 0) {
                list.add(new PixelCoordinate(x-y, y));
            }
            // Add other neighbors...
        }
    }