Open In App

Flood Fill Algorithm

Last Updated : 06 Nov, 2025
Comments
Improve
Suggest changes
28 Likes
Like
Report

Given a 2D grid img[][] representing an image, where each element img[i][j] is an integer that denotes the color of a pixel. Also there is a coordinates (sr, sc) representing the starting pixel (row sr and column sc) and an integer newColor, which represents the new color to apply.
We need to perform a flood fill on the image starting from (sr, sc).
It means we must change the color of the starting pixel and all other pixels that are connected to it (directly or indirectly) and have the same original color as the starting pixel.
Two pixels are considered connected if they are adjacent horizontally or vertically (not diagonally).

Example: 

Input: sr = 1, sc = 2, newColor = 2, img[][]= [[1, 1, 1, 0],
[0, 1, 1, 1],
[1, 0, 1, 1]]

111

Output: [[2, 2, 2, 0],
[0, 2, 2, 2],
[1, 0, 2,2]]
Explanation: Starting from pixel (1, 2) with value 1, flood fill updates all connected pixels (up, down, left, right) with value 1 to 2. The pixel at (2, 0) remains unchanged because it has no adjacent 1 connected to the starting pixel.

222

Input: sr = 0, sc = 1, newColor = 0, img[][] = [[0, 1, 0],
[0, 1, 0]]
Output: [[0, 0, 0],
[0, 0, 0]]
Explanation: Starting from pixel (0, 1) which has value 1, flood fill updates all connected pixels (up, down, left, right) with value 1 to 0.

[Approach 1] Using Depth-First Search - O(m * n) Time and O(m * n) Auxiliary Space

The idea is to use Depth-First Search (DFS) because DFS explores all connected cells deeply before backtracking. we need to change the color of the starting pixel and all other pixels that are connected to it having the same original color.
So, we can think of it like this:

We start from the given pixel (sr, sc) and store its color as oldColor. Then, we begin a DFS from that cell. For each cell, we check all its four neighboring cells, If the neighbor is inside the grid and has the same color as oldColor, then that means this pixel should also be filled with the new color. We update it with newColor and recursively call DFS for that neighbor to continue spreading the new color further. If a neighbor has a different color or is outside the grid, we simply return without going deeper. Once all connected cells are visited, we’ll have our final filled image.

C++
//Driver Code Starts
#include <iostream>
#include <vector>
using namespace std;

//Driver Code Ends

void dfs(vector<vector<int>>& img, int x, 
         int y, int oldColor, int newColor) {
    
    if (x < 0 || x >= img.size() || 
        y < 0 || y >= img[0].size() || img[x][y] != oldColor) {
              return; 
    }

    // Update the color of the current pixel
    img[x][y] = newColor;

    // Recursively visit all 4 connected neighbors
    dfs(img, x + 1, y, oldColor, newColor); 
    dfs(img, x - 1, y, oldColor, newColor); 
    dfs(img, x, y + 1, oldColor, newColor); 
    dfs(img, x, y - 1, oldColor, newColor); 
}

vector<vector<int>> floodFill(vector<vector<int>>& img, int sr, 
    int sc, int newColor) {

    // If the starting pixel already has the new color,
    // no changes are needed
    if (img[sr][sc] == newColor) {
        return img;
    }

    // Call DFS to start filling from the source pixel
     // Store original color
    int oldColor = img[sr][sc];
    dfs(img, sr, sc, oldColor, newColor);

    return img;
}


//Driver Code Starts
int main() {
    vector<vector<int>> img = {
        {1, 1, 1, 0},
        {0, 1, 1, 1},
        {1, 0, 1, 1}
    };

    int sr = 1, sc = 2;

    int newColor = 2;        

    vector<vector<int>> result = floodFill(img, sr, sc, newColor);

    for (auto& row : result) {
        for (auto& pixel : row) {
            cout << pixel << " ";
        }
        cout << "
";
    }
    return 0;
}

//Driver Code Ends
Java
//Driver Code Starts
class GFG {

//Driver Code Ends

    static void dfs(int[][] img, int x, int y, int oldColor, int newColor) {

        if (x < 0 || x >= img.length ||
            y < 0 || y >= img[0].length ||
            img[x][y] != oldColor) {

            return;
        }

        // Update the color of the current pixel
        img[x][y] = newColor;

        // Recursively visit all 4 connected neighbors
        dfs(img, x + 1, y, oldColor, newColor);
        dfs(img, x - 1, y, oldColor, newColor);
        dfs(img, x, y + 1, oldColor, newColor);
        dfs(img, x, y - 1, oldColor, newColor);
    }

    static int[][] floodFill(int[][] img, int sr, int sc, int newColor) {

        // If the starting pixel already has the new color,
        // no changes are needed
        if (img[sr][sc] == newColor) {
            return img;
        }

        // Call DFS to start filling from the source pixel
        // Store original color
        int oldColor = img[sr][sc];
        dfs(img, sr, sc, oldColor, newColor);

        return img;
    }


//Driver Code Starts
    public static void main(String[] args) {

        int[][] img = {
            {1, 1, 1, 0},
            {0, 1, 1, 1},
            {1, 0, 1, 1}
        };

        int sr = 1, sc = 2;
        int newColor = 2;

        int[][] result = floodFill(img, sr, sc, newColor);

        for (int[] row : result) {
            for (int pixel : row) {
                System.out.print(pixel + " ");
            }
            System.out.println();
        }
    }
}

//Driver Code Ends
Python
def dfs(img, x, y, oldColor, newColor):
    if (x < 0 or x >= len(img) or
        y < 0 or y >= len(img[0]) or
        img[x][y] != oldColor):
        return

    # Update the color of the current pixel
    img[x][y] = newColor

    # Recursively visit all 4 connected neighbors
    dfs(img, x + 1, y, oldColor, newColor)
    dfs(img, x - 1, y, oldColor, newColor)
    dfs(img, x, y + 1, oldColor, newColor)
    dfs(img, x, y - 1, oldColor, newColor)


def floodFill(img, sr, sc, newColor):
    
    # If the starting pixel already has the new color,
    # no changes are needed
    if img[sr][sc] == newColor:
        return img

    # Call DFS to start filling from the source pixel
    # Store original color
    oldColor = img[sr][sc]
    dfs(img, sr, sc, oldColor, newColor)

    return img
  

    
#Driver Code Starts
if __name__ == "__main__":
    img = [
        [1, 1, 1, 0],
        [0, 1, 1, 1],
        [1, 0, 1, 1]
    ]
    
    sr, sc = 1, 2
    newColor = 2
    
    result = floodFill(img, sr, sc, newColor)
    
    for row in result:
        print(*row)

#Driver Code Ends
C#
//Driver Code Starts
using System;

class GFG {
//Driver Code Ends

    static void dfs(int[,] img, int x, int y, int oldColor, int newColor) {

        if (x < 0 || x >= img.GetLength(0) ||
            y < 0 || y >= img.GetLength(1) ||
            img[x, y] != oldColor) {

            return;
        }

        // Update the color of the current pixel
        img[x, y] = newColor;

        // Recursively visit all 4 connected neighbors
        dfs(img, x + 1, y, oldColor, newColor);
        dfs(img, x - 1, y, oldColor, newColor);
        dfs(img, x, y + 1, oldColor, newColor);
        dfs(img, x, y - 1, oldColor, newColor);
    }

    static int[,] floodFill(int[,] img, int sr, int sc, int newColor) {

        // If the starting pixel already has the new color,
        // no changes are needed
        if (img[sr, sc] == newColor) {
            return img;
        }

        // Call DFS to start filling from the source pixel
        // Store original color
        int oldColor = img[sr, sc];
        dfs(img, sr, sc, oldColor, newColor);

        return img;
    }


//Driver Code Starts
    static void Main() {
        int[,] img = {
            {1, 1, 1, 0},
            {0, 1, 1, 1},
            {1, 0, 1, 1}
        };

        int sr = 1, sc = 2;
        int newColor = 2;

        int[,] result = floodFill(img, sr, sc, newColor);

        for (int i = 0; i < result.GetLength(0); i++) {
            for (int j = 0; j < result.GetLength(1); j++) {
                Console.Write(result[i, j] + " ");
            }
            Console.WriteLine();
        }
    }
}

//Driver Code Ends
JavaScript
function dfs(img, x, y, oldColor, newColor) {
    if (x < 0 || x >= img.length || y < 0 || y >= img[0].length ||
        img[x][y] !== oldColor) {
        return;
    }

    // Update the color of the current pixel
    img[x][y] = newColor;

    // Recursively visit all 4 connected neighbors
    dfs(img, x + 1, y, oldColor, newColor);
    dfs(img, x - 1, y, oldColor, newColor);
    dfs(img, x, y + 1, oldColor, newColor);
    dfs(img, x, y - 1, oldColor, newColor);
}

function floodFill(img, sr, sc, newColor) {

    // If the starting pixel already has the new color,
    // no changes are needed
    if (img[sr][sc] === newColor) {
        return img;
    }

    // Call DFS to start filling from the source pixel
    // Store original color
    let oldColor = img[sr][sc];
    dfs(img, sr, sc, oldColor, newColor);

    return img;
}



//Driver Code Starts
//Driver Code
let img = [
    [1, 1, 1, 0],
    [0, 1, 1, 1],
    [1, 0, 1, 1]
];

let sr = 1, sc = 2;
let newColor = 2;

let result = floodFill(img, sr, sc, newColor);

for (let row of result) {
    console.log(row.join(" "));
}

//Driver Code Ends

Output
2 2 2 0 
0 2 2 2 
1 0 2 2 

[Approach 2] Using Breadth-First Search - O(m * n) Time and O(m * n) Space

The idea is the same as DFS, but instead of using recursion, we use Breadth-First Search (BFS) because it avoids recursion overhead.

In BFS, we use a queue and traverse level by level. We start from the given pixel, change its color to the new one, and push it into the queue. Then, for each pixel we pop, we check all four adjacent cells—if any neighbor has the same old color, we update it with the new color and add it to the queue. This continues until all connected pixels are updated.

C++
//Driver Code Starts
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
//Driver Code Ends


vector<vector<int>> floodFill(vector<vector<int>>& img, int sr, 
    int sc, int newColor) {

    // If the starting pixel already has the new color
    if (img[sr][sc] == newColor) {
        return img;
    }

    // Direction vectors for traversing 4 directions
    vector<pair<int, int>> dir = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};

    queue<pair<int, int>> q;
    int oldColor = img[sr][sc];
    q.push({sr, sc});
    
    // Change the color of the starting pixel
    img[sr][sc] = newColor;

    // Perform BFS
    while (!q.empty()) {
        pair<int, int> front = q.front();
        int x = front.first, y = front.second;
        q.pop();
        
        // Traverse all 4 directions
        for (pair<int, int>& it : dir) {
            int nx = x + it.first;
            int ny = y + it.second;
            
            // Check boundary conditions and color match
            if (nx >= 0 && nx < img.size() && 
                ny >= 0 && ny < img[0].size() && 
                img[nx][ny] == oldColor) {
                img[nx][ny] = newColor;
                q.push({nx, ny});
            }
        }
    }

    return img;
}


//Driver Code Starts
int main() {

    vector<vector<int>> img = {
        {1, 1, 1, 0},
        {0, 1, 1, 1},
        {1, 0, 1, 1}
    };

    int sr = 1, sc = 2;

    int newColor = 2;

    vector<vector<int>> result = floodFill(img, sr, sc, newColor);

    for (auto& row : result) {
        for (auto& pixel : row) {

            cout << pixel << " ";  
        }

        cout << "
";  
    }
    
    return 0; 
}
//Driver Code Ends
Java
//Driver Code Starts
import java.util.Queue;
import java.util.LinkedList;
public class GFG {
//Driver Code Ends

    public static int[][] floodFill(int[][] img, int sr,
        int sc, int newColor) {

        // If the starting pixel already has the new color
        if (img[sr][sc] == newColor) {
            return img;
        }

        // Direction vectors for traversing 4 directions
        int[][] dir = { {1, 0}, {-1, 0}, {0, 1}, {0, -1}};

        Queue<int[]> q = new LinkedList<>();
        int oldColor = img[sr][sc];
        q.add(new int[]{sr, sc});

        // Change the color of the starting pixel
        img[sr][sc] = newColor;

        // Perform BFS
        while (!q.isEmpty()) {
            int[] front = q.poll();
            int x = front[0], y = front[1];

            // Traverse all 4 directions
            for (int[] it : dir) {
                int nx = x + it[0];
                int ny = y + it[1];

                // Check boundary conditions and color match
                if (nx >= 0 && nx < img.length &&ny >= 0 && ny < img[0].length && 
                  img[nx][ny] == oldColor) {
                    img[nx][ny] = newColor;
                    q.add(new int[]{nx, ny});
                }
            }
        }

        return img;
    }


//Driver Code Starts
    public static void main(String[] args) {
        int[][] img = {
            {1, 1, 1, 0},
            {0, 1, 1, 1},
            {1, 0, 1, 1}
        };

        int sr = 1, sc = 2;
        int newColor = 2;

        int[][] result = floodFill(img, sr, sc, newColor);

        for (int[] row : result) {
            for (int pixel : row) {
                System.out.print(pixel + " ");
            }
            System.out.println();
        }
    }
}

//Driver Code Ends
Python
#Driver Code Starts
from collections import deque
#Driver Code Ends


def floodFill(img, sr, sc, newColor):
    # If the starting pixel already has the new color
    if img[sr][sc] == newColor:
        return img

    # Direction vectors for traversing 4 directions
    dir = [(1, 0), (-1, 0), (0, 1), (0, -1)]

    q = deque()
    oldColor = img[sr][sc]
    q.append((sr, sc))

    # Change the color of the starting pixel
    img[sr][sc] = newColor

    # Perform BFS
    while q:
        x, y = q.popleft()

        # Traverse all 4 directions
        for dx, dy in dir:
            nx = x + dx
            ny = y + dy

            # Check boundary conditions and color match
            if 0 <= nx < len(img) and 0 <= ny < len(img[0]) and img[nx][ny] == oldColor:
                img[nx][ny] = newColor
                q.append((nx, ny))

    return img


#Driver Code Starts

if __name__ == "__main__":
    img = [
        [1, 1, 1, 0],
        [0, 1, 1, 1],
        [1, 0, 1, 1]
    ]
    
    sr, sc = 1, 2
    newColor = 2
    
    result = floodFill(img, sr, sc, newColor)
    
    for row in result:
        print(*row)

#Driver Code Ends
C#
//Driver Code Starts
using System;
using System.Collections.Generic;

class GFG {
//Driver Code Ends

    public static int[,] floodFill(int[,] img, int sr,
        int sc, int newColor) {

        // If the starting pixel already has the new color
        if (img[sr, sc] == newColor)
            return img;

        // Direction vectors for traversing 4 directions
        int[,] dir = {
            {1, 0}, {-1, 0}, {0, 1}, {0, -1}
        };

        Queue<(int, int)> q = new Queue<(int, int)>();
        int oldColor = img[sr, sc];
        q.Enqueue((sr, sc));

        // Change the color of the starting pixel
        img[sr, sc] = newColor;

        int n = img.GetLength(0);
        int m = img.GetLength(1);

        // Perform BFS
        while (q.Count > 0) {
            var (x, y) = q.Dequeue();

            // Traverse all 4 directions
            for (int i = 0; i < 4; i++) {
                int nx = x + dir[i, 0];
                int ny = y + dir[i, 1];

                // Check boundary conditions and color match
                if (nx >= 0 && nx < n &&
                    ny >= 0 && ny < m &&
                    img[nx, ny] == oldColor) {
                    img[nx, ny] = newColor;
                    q.Enqueue((nx, ny));
                }
            }
        }

        return img;
    }


//Driver Code Starts
    static void Main() {
        int[,] img = {
            {1, 1, 1, 0},
            {0, 1, 1, 1},
            {1, 0, 1, 1}
        };

        int sr = 1, sc = 2;
        int newColor = 2;

        int[,] result = floodFill(img, sr, sc, newColor);

        int n = result.GetLength(0);
        int m = result.GetLength(1);

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                Console.Write(result[i, j] + " ");
            }
            Console.WriteLine();
        }
    }
}

//Driver Code Ends
JavaScript
function floodFill(img, sr, sc, newColor) {
    // If the starting pixel already has the new color
    if (img[sr][sc] === newColor) return img;

    // Direction vectors for traversing 4 directions
    const dir = [[1, 0], [-1, 0], [0, 1], [0, -1]];

    const q = [];
    const oldColor = img[sr][sc];
    q.push([sr, sc]);

    // Change the color of the starting pixel
    img[sr][sc] = newColor;

    // Perform BFS
    while (q.length > 0) {
        const [x, y] = q.shift();

        // Traverse all 4 directions
        for (const it of dir) {
            const nx = x + it[0];
            const ny = y + it[1];

            // Check boundary conditions and color match
            if (nx >= 0 && nx < img.length &&
                ny >= 0 && ny < img[0].length &&
                img[nx][ny] === oldColor) {
                img[nx][ny] = newColor;
                q.push([nx, ny]);
            }
        }
    }

    return img;
}

//Driver Code
//Driver Code Starts
const img = [
    [1, 1, 1, 0],
    [0, 1, 1, 1],
    [1, 0, 1, 1]
];

const sr = 1, sc = 2, newColor = 2;
const result = floodFill(img, sr, sc, newColor);

result.forEach(row => console.log(row.join(" ")));

//Driver Code Ends

Output
2 2 2 0 
0 2 2 2 
1 0 2 2 

Flood Fill Algorithm | Computer Graphics
Article Tags :

Explore