0

I wrote a classic queue floodfill:

public static void floodFill(int y, int x, byte originalvalue, byte newvalue, byte[][] arr) {
    Deque queue = new ArrayDeque();
    queue.add(new int[]{y, x});
    while (!queue.isEmpty()) {
        int[] t = (int[]) queue.poll();
        y = t[0];
        x = t[1];
        if (arr[y][x] == originalvalue) {
            arr[y][x] = newvalue;
            for (int i = 0; i < 8; i++) {
                if (x + dx[i] < arr[0].length && y + dy[i] < arr.length && x + dx[i] > -1 && y + dy[i] > -1 && arr[y + dy[i]][x + dx[i]] == originalvalue) {
                    queue.add(new int[]{y + dy[i], x + dx[i]});
                }
            }
        }
    }
}

And now I want to write scan line Flood Fill, which is much faster. I can't find any pseudocode, and I don't understand this code.

Can you help me optimize my flood fill or write scan line one?

I call this flood fill for a byte array with dimensions 1000–2000 by 1000–2000 (not necessarily square) for a large area once, and then about 1000 to 1,000,000 times for smaller areas.

JohnDow
  • 1,242
  • 4
  • 22
  • 40
  • 1
    scan line, not skyline ! –  Mar 28 '14 at 17:39
  • This explains why you don't find traces of this algorithm. But beware that this name covers two things: scanline filling of polygons (known as a sequence of vertices), and scanline seed filling (within a region). –  Mar 28 '14 at 18:10

1 Answers1

1

This is a modified flood-fill algorithm. Rather than filling a pixel and then its neighbors, you fill a whole horizontal "run" of pixels and then its neighbors.

The recursion goes as follows:

To Fill(X0, X1, Y, Old, New):

# Precondition: the segment [X0 X1]/Y has the old color and can't be lengthened

Find all connected runs [X0' X1'] in row Y-1 having old color and Fill(X0', X1', Y-1, Old, New)

Find all connected runs [X0' X1'] in row Y+1 having old color and Fill(X0', X1', Y+1, Old, New)

To find all connected runs in a new row, start from X0 and move left as long as you are on an old pixel, or move right as long as you are on an non-old pixel (stop at X1); you have X0'. Then continue to the right on old pixels; you have X1'. Repeat the search to the right as long as X0' is in [X0 X1].

A few implementation details depend on the 4/8 connexity rule you choose.

  • 1
    Do not rely on an optimization that would consider 'since I came from row Y to find the runs in row Y+1, I needn't compare rows Y+1 and Y again'. –  Mar 28 '14 at 18:27