Flood fill Algorithm – how to implement fill() in paint?

In MS-Paint, when we take the brush to a pixel and click, the color of the region of that pixel is replaced with a new selected color. Following is the problem statement to do this task. 
Given a 2D screen, location of a pixel in the screen and a color, replace color of the given pixel and all adjacent same colored pixels with the given color.

Example: 

Input:
screen[M][N] = {{1, 1, 1, 1, 1, 1, 1, 1},
               {1, 1, 1, 1, 1, 1, 0, 0},
               {1, 0, 0, 1, 1, 0, 1, 1},
               {1, 2, 2, 2, 2, 0, 1, 0},
               {1, 1, 1, 2, 2, 0, 1, 0},
               {1, 1, 1, 2, 2, 2, 2, 0},
               {1, 1, 1, 1, 1, 2, 1, 1},
               {1, 1, 1, 1, 1, 2, 2, 1},
               };
    x = 4, y = 4, newColor = 3
The values in the given 2D screen
  indicate colors of the pixels.
x and y are coordinates of the brush,
   newColor is the color that
should replace the previous color on 
   screen[x][y] and all surrounding
pixels with same color.

Output:
Screen should be changed to following.
screen[M][N] = {{1, 1, 1, 1, 1, 1, 1, 1},
               {1, 1, 1, 1, 1, 1, 0, 0},
               {1, 0, 0, 1, 1, 0, 1, 1},
               {1, 3, 3, 3, 3, 0, 1, 0},
               {1, 1, 1, 3, 3, 0, 1, 0},
               {1, 1, 1, 3, 3, 3, 3, 0},
               {1, 1, 1, 1, 1, 3, 1, 1},
               {1, 1, 1, 1, 1, 3, 3, 1},
               };


This question can be solved using either Recursion or BFS. Both the solutions are discussed below 
1:- Using Recursion 
The idea is simple, we first replace the color of the current pixel, then recur for 4 surrounding points. The following is a detailed algorithm. 

// A recursive function to replace 
// previous color 'prevC' at  '(x, y)' 
// and all surrounding pixels of (x, y)
// with new color 'newC' and
floodFil(screen[M][N], x, y, prevC, newC)
1) If x or y is outside the screen, then return.
2) If color of screen[x][y] is not same as prevC, then return
3) Recur for north, south, east and west.
    floodFillUtil(screen, x+1, y, prevC, newC);
    floodFillUtil(screen, x-1, y, prevC, newC);
    floodFillUtil(screen, x, y+1, prevC, newC);
    floodFillUtil(screen, x, y-1, prevC, newC); 


The following is the implementation of the above algorithm.  

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// A C++ program to implement flood fill algorithm
#include<iostream>
using namespace std;
 
// Dimentions of paint screen
#define M 8
#define N 8
 
// A recursive function to replace previous color 'prevC' at  '(x, y)'
// and all surrounding pixels of (x, y) with new color 'newC' and
void floodFillUtil(int screen[][N], int x, int y, int prevC, int newC)
{
    // Base cases
    if (x < 0 || x >= M || y < 0 || y >= N)
        return;
    if (screen[x][y] != prevC)
        return;
    if (screen[x][y] == newC)
        return;
 
    // Replace the color at (x, y)
    screen[x][y] = newC;
 
    // Recur for north, east, south and west
    floodFillUtil(screen, x+1, y, prevC, newC);
    floodFillUtil(screen, x-1, y, prevC, newC);
    floodFillUtil(screen, x, y+1, prevC, newC);
    floodFillUtil(screen, x, y-1, prevC, newC);
}
 
// It mainly finds the previous color on (x, y) and
// calls floodFillUtil()
void floodFill(int screen[][N], int x, int y, int newC)
{
    int prevC = screen[x][y];
    floodFillUtil(screen, x, y, prevC, newC);
}
 
// Driver code
int main()
{
    int screen[M][N] = {{1, 1, 1, 1, 1, 1, 1, 1},
                      {1, 1, 1, 1, 1, 1, 0, 0},
                      {1, 0, 0, 1, 1, 0, 1, 1},
                      {1, 2, 2, 2, 2, 0, 1, 0},
                      {1, 1, 1, 2, 2, 0, 1, 0},
                      {1, 1, 1, 2, 2, 2, 2, 0},
                      {1, 1, 1, 1, 1, 2, 1, 1},
                      {1, 1, 1, 1, 1, 2, 2, 1},
                     };
    int x = 4, y = 4, newC = 3;
    floodFill(screen, x, y, newC);
 
    cout << "Updated screen after call to floodFill: \n";
    for (int i=0; i<M; i++)
    {
        for (int j=0; j<N; j++)
           cout << screen[i][j] << " ";
        cout << endl;
    }
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program to implement flood fill algorithm
class GFG
{
 
// Dimentions of paint screen
static int M = 8;
static int N = 8;
 
// A recursive function to replace previous color 'prevC' at '(x, y)'
// and all surrounding pixels of (x, y) with new color 'newC' and
static void floodFillUtil(int screen[][], int x, int y,
                                    int prevC, int newC)
{
    // Base cases
    if (x < 0 || x >= M || y < 0 || y >= N)
        return;
    if (screen[x][y] != prevC)
        return;
 
    // Replace the color at (x, y)
    screen[x][y] = newC;
 
    // Recur for north, east, south and west
    floodFillUtil(screen, x+1, y, prevC, newC);
    floodFillUtil(screen, x-1, y, prevC, newC);
    floodFillUtil(screen, x, y+1, prevC, newC);
    floodFillUtil(screen, x, y-1, prevC, newC);
}
 
// It mainly finds the previous color on (x, y) and
// calls floodFillUtil()
static void floodFill(int screen[][], int x, int y, int newC)
{
    int prevC = screen[x][y];
    floodFillUtil(screen, x, y, prevC, newC);
}
 
// Driver code
public static void main(String[] args)
{
    int screen[][] = {{1, 1, 1, 1, 1, 1, 1, 1},
                    {1, 1, 1, 1, 1, 1, 0, 0},
                    {1, 0, 0, 1, 1, 0, 1, 1},
                    {1, 2, 2, 2, 2, 0, 1, 0},
                    {1, 1, 1, 2, 2, 0, 1, 0},
                    {1, 1, 1, 2, 2, 2, 2, 0},
                    {1, 1, 1, 1, 1, 2, 1, 1},
                    {1, 1, 1, 1, 1, 2, 2, 1},
                    };
    int x = 4, y = 4, newC = 3;
    floodFill(screen, x, y, newC);
 
    System.out.println("Updated screen after call to floodFill: ");
    for (int i = 0; i < M; i++)
    {
        for (int j = 0; j < N; j++)
        System.out.print(screen[i][j] + " ");
        System.out.println();
    }
    }
}
 
// This code has been contributed by 29AjayKumar

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 program to implement
# flood fill algorithm
 
# Dimentions of paint screen
M = 8
N = 8
 
# A recursive function to replace
# previous color 'prevC' at '(x, y)'
# and all surrounding pixels of (x, y)
# with new color 'newC' and
def floodFillUtil(screen, x, y, prevC, newC):
     
    # Base cases
    if (x < 0 or x >= M or y < 0 or
        y >= N or screen[x][y] != prevC or
        screen[x][y] == newC):
        return
 
    # Replace the color at (x, y)
    screen[x][y] = newC
 
    # Recur for north, east, south and west
    floodFillUtil(screen, x + 1, y, prevC, newC)
    floodFillUtil(screen, x - 1, y, prevC, newC)
    floodFillUtil(screen, x, y + 1, prevC, newC)
    floodFillUtil(screen, x, y - 1, prevC, newC)
 
# It mainly finds the previous color on (x, y) and
# calls floodFillUtil()
def floodFill(screen, x, y, newC):
    prevC = screen[x][y]
    floodFillUtil(screen, x, y, prevC, newC)
 
# Driver Code
screen = [[1, 1, 1, 1, 1, 1, 1, 1],
          [1, 1, 1, 1, 1, 1, 0, 0],
          [1, 0, 0, 1, 1, 0, 1, 1],
          [1, 2, 2, 2, 2, 0, 1, 0],
          [1, 1, 1, 2, 2, 0, 1, 0],
          [1, 1, 1, 2, 2, 2, 2, 0],
          [1, 1, 1, 1, 1, 2, 1, 1],
          [1, 1, 1, 1, 1, 2, 2, 1]]
 
x = 4
y = 4
newC = 3
floodFill(screen, x, y, newC)
 
print ("Updated screen after call to floodFill:")
for i in range(M):
    for j in range(N):
        print(screen[i][j], end = ' ')
    print()
 
# This code is contributed by Ashutosh450

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program to implement
// flood fill algorithm
using System;
     
class GFG
{
 
// Dimentions of paint screen
static int M = 8;
static int N = 8;
 
// A recursive function to replace
// previous color 'prevC' at '(x, y)'
// and all surrounding pixels of (x, y)
// with new color 'newC' and
static void floodFillUtil(int [,]screen,
                          int x, int y,
                          int prevC, int newC)
{
    // Base cases
    if (x < 0 || x >= M ||
        y < 0 || y >= N)
        return;
    if (screen[x, y] != prevC)
        return;
 
    // Replace the color at (x, y)
    screen[x, y] = newC;
 
    // Recur for north, east, south and west
    floodFillUtil(screen, x + 1, y, prevC, newC);
    floodFillUtil(screen, x - 1, y, prevC, newC);
    floodFillUtil(screen, x, y + 1, prevC, newC);
    floodFillUtil(screen, x, y - 1, prevC, newC);
}
 
// It mainly finds the previous color
// on (x, y) and calls floodFillUtil()
static void floodFill(int [,]screen, int x,
                      int y, int newC)
{
    int prevC = screen[x, y];
    floodFillUtil(screen, x, y, prevC, newC);
}
 
// Driver code
public static void Main(String[] args)
{
    int [,]screen = {{1, 1, 1, 1, 1, 1, 1, 1},
                     {1, 1, 1, 1, 1, 1, 0, 0},
                     {1, 0, 0, 1, 1, 0, 1, 1},
                     {1, 2, 2, 2, 2, 0, 1, 0},
                     {1, 1, 1, 2, 2, 0, 1, 0},
                     {1, 1, 1, 2, 2, 2, 2, 0},
                     {1, 1, 1, 1, 1, 2, 1, 1},
                     {1, 1, 1, 1, 1, 2, 2, 1}};
    int x = 4, y = 4, newC = 3;
    floodFill(screen, x, y, newC);
 
    Console.WriteLine("Updated screen after" +
                      "call to floodFill: ");
    for (int i = 0; i < M; i++)
    {
        for (int j = 0; j < N; j++)
        Console.Write(screen[i, j] + " ");
        Console.WriteLine();
    }
    }
}
 
// This code is contributed by PrinciRaj1992

chevron_right


Output



Updated screen after call to floodFill: 
1 1 1 1 1 1 1 1 
1 1 1 1 1 1 0 0 
1 0 0 1 1 0 1 1 
1 3 3 3 3 0 1 0 
1 1 1 3 3 0 1 0 
1 1 1 3 3 3 3 0 
1 1 1 1 1 3 1 1 
1 1 1 1 1 3 3 1 


Method 2: Using the BFS approach

Algorithm for BFS based approach :

  1. Create a queue of pairs.
  2. Insert an initial index given in the queue.
  3. Mark initial index as visited in vis[][] matrix.
  4. Until the queue is not empty repeat step 3.1 to 3.6
    • Take the front element from the queue
    • Pop from the queue
    • Store current value/colour at coordinate taken out from queue (precolor)
    • Update the value/color of the current index which is taken out from the queue
    • Check for all 4 direction i.e (x+1,y),(x-1,y),(x,y+1),(x,y-1) is valid or not and if valid then check that value at that coordinate should be equal to precolor and value of that coordinate in vis[][] is 0.
    • If all the above condition is true push the corresponding coordinate in queue and mark as 1 in vis[][]
  5. Print the matrix.

Below is the implementation of the above approach:  

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// CPP program for above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to check valid coordinate
int validCoord(int x, int y, int n, int m)
{
 
    if (x < 0 || y < 0) {
        return 0;
    }
    if (x >= n || y >= m) {
        return 0;
    }
    return 1;
}
 
// Function to run bfs
void bfs(int n, int m, int data[][8],
                     int x, int y, int color)
{
   
  // Visiing array
  int vis[101][101];
   
  // Initialing all as zero
  memset(vis, 0, sizeof(vis));
   
  // Creating queue for bfs
  queue<pair<int, int> > obj;
   
  // Pushing pair of {x, y}
  obj.push({ x, y });
   
  // Marking {x, y} as visited
  vis[x][y] = 1;
   
  // Untill queue is emppty
  while (obj.empty() != 1)
  {
 
    // Extrating front pair
    pair<int, int> coord = obj.front();
    int x = coord.first;
    int y = coord.second;
    int preColor = data[x][y];
 
    data[x][y] = color;
     
    // Poping front pair of queue
    obj.pop();
 
    // For Upside Pixel or Cell
    if (validCoord(x + 1, y, n, m)
        && vis[x + 1][y] == 0
        && data[x + 1][y] == preColor)
    {
      obj.push({ x + 1, y });
      vis[x + 1][y] = 1;
    }
     
    // For Downside Pixel or Cell
    if (validCoord(x - 1, y, n, m)
        && vis[x - 1][y] == 0
        && data[x - 1][y] == preColor)
    {
      obj.push({ x - 1, y });
      vis[x - 1][y] = 1;
    }
     
    // For Right side Pixel or Cell
    if (validCoord(x, y + 1, n, m)
        && vis[x][y + 1] == 0
        && data[x][y + 1] == preColor)
    {
      obj.push({ x, y + 1 });
      vis[x][y + 1] = 1;
    }
     
    // For Left side Pixel or Cell
    if (validCoord(x, y - 1, n, m)
        && vis[x][y - 1] == 0
        && data[x][y - 1] == preColor)
    {
      obj.push({ x, y - 1 });
      vis[x][y - 1] = 1;
    }
  }
   
  // Printing The Changed Matrix Of Pixels
  for (int i = 0; i < n; i++)
  {
    for (int j = 0; j < m; j++)
    {
      cout << data[i][j] << " ";
    }
    cout << endl;
  }
  cout << endl;
}
 
// Driver Code
int main()
{
  int n, m, x, y, color;
  n = 8;
  m = 8;
 
  int data[8][8] = {
    { 1, 1, 1, 1, 1, 1, 1, 1 },
    { 1, 1, 1, 1, 1, 1, 0, 0 },
    { 1, 0, 0, 1, 1, 0, 1, 1 },
    { 1, 2, 2, 2, 2, 0, 1, 0 },
    { 1, 1, 1, 2, 2, 0, 1, 0 },
    { 1, 1, 1, 2, 2, 2, 2, 0 },
    { 1, 1, 1, 1, 1, 2, 1, 1 },
    { 1, 1, 1, 1, 1, 2, 2, 1 },
  };
 
  x = 4, y = 4, color = 3;
   
  // Function Call
  bfs(n, m, data, x, y, color);
  return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

/*package whatever //do not write package name here */
import java.io.*;
import java.util.*;
 
// Class to store the pairs
class Pair implements Comparable<Pair> {
    int first;
    int second;
 
    public Pair(int first, int second) {
        this.first = first;
        this.second = second;
    }
 
    @Override
    public int compareTo(Pair o) {
        return second - o.second;
    }
}
 
class GFG {
    public static int validCoord(int x, int y, int n, int m)
    {
        if (x < 0 || y < 0) {
            return 0;
        }
        if (x >= n || y >= m) {
            return 0;
        }
        return 1;
    }
    // Function to run bfs
    public static void bfs(int n, int m, int data[][],int x, int y, int color)
    {
   
        // Visiing array
         int vis[][]=new int[101][101];
         
        // Initialing all as zero
        for(int i=0;i<=100;i++){
            for(int j=0;j<=100;j++){
                vis[i][j]=0;
            }
        }
         
        // Creating queue for bfs
         Queue<Pair> obj = new LinkedList<>();
   
        // Pushing pair of {x, y}
         Pair pq=new Pair(x,y);
         obj.add(pq);
          
        // Marking {x, y} as visited
         vis[x][y] = 1;
   
        // Untill queue is emppty
        while (!obj.isEmpty())
        {
            // Extrating front pair
            Pair coord = obj.peek();
            int x1 = coord.first;
            int y1 = coord.second;
            int preColor = data[x1][y1];
             
            data[x1][y1] = color;
     
            // Poping front pair of queue
            obj.remove();
 
            // For Upside Pixel or Cell
            if ((validCoord(x1 + 1, y1, n, m)==1) && vis[x1 + 1][y1] == 0 && data[x1 + 1][y1] == preColor)
            {
                Pair p=new Pair(x1 +1, y1);
                obj.add(p);
                vis[x1 + 1][y1] = 1;
            }
     
            // For Downside Pixel or Cell
            if ((validCoord(x1 - 1, y1, n, m)==1) && vis[x1 - 1][y1] == 0 && data[x1 - 1][y1] == preColor)
            {
                Pair p=new Pair(x1-1,y1);
                obj.add(p);
                vis[x1- 1][y1] = 1;
            }
     
            // For Right side Pixel or Cell
            if ((validCoord(x1, y1 + 1, n, m)==1) && vis[x1][y1 + 1] == 0 && data[x1][y1 + 1] == preColor)
            {
                Pair p=new Pair(x1,y1 +1);
                obj.add(p);
                vis[x1][y1 + 1] = 1;
            }
     
            // For Left side Pixel or Cell
            if ((validCoord(x1, y1 - 1, n, m)==1) && vis[x1][y1 - 1] == 0 && data[x1][y1 - 1] == preColor)
            {
                Pair p=new Pair(x1,y1 -1);
                obj.add(p);
                vis[x1][y1 - 1] = 1;
            }
        }
   
         // Printing The Changed Matrix Of Pixels
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {  
             System.out.print(data[i][j]+" ");
            }
            System.out.println();
        }
        System.out.println();
    }
    public static void main (String[] args) {
        int nn, mm, xx, yy, colorr;
        nn = 8;
        mm = 8;
 
        int dataa[][] = {{ 1, 1, 1, 1, 1, 1, 1, 1 },
                          { 1, 1, 1, 1, 1, 1, 0, 0 },
                          { 1, 0, 0, 1, 1, 0, 1, 1 },
                          { 1, 2, 2, 2, 2, 0, 1, 0 },
                          { 1, 1, 1, 2, 2, 0, 1, 0 },
                          { 1, 1, 1, 2, 2, 2, 2, 0 },
                          { 1, 1, 1, 1, 1, 2, 1, 1 },
                          { 1, 1, 1, 1, 1, 2, 2, 1 },};
 
        xx = 4; yy = 4; colorr = 3;
   
        // Function Call
        bfs(nn, mm, dataa, xx, yy, colorr);
    }
}
// This code is contributed by Manu Pathria

chevron_right


Output

1 1 1 1 1 1 1 1 
1 1 1 1 1 1 0 0 
1 0 0 1 1 0 1 1 
1 3 3 3 3 0 1 0 
1 1 1 3 3 0 1 0 
1 1 1 3 3 3 3 0 
1 1 1 1 1 3 1 1 
1 1 1 1 1 3 3 1 



References: 

http://en.wikipedia.org/wiki/Flood_fill

This article is contributed by Anmol. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.




My Personal Notes arrow_drop_up