Introduction
Flood Fill is an algorithm that is used to color a connected area of pixels in an image. The algorithm starts at a given point and “floods” the area with a specific color. It is used in the “bucket fill” tool of paint programs to fill connected, similarly-colored areas with a different color.
In this study, we will discuss how to implement the Flood Fill algorithm in C, but not in the context of an image. Instead, we will use a 2D array to represent the image.
Subject
Write a function that takes a char **
as a 2-dimensional array of char, a
t_point
as the dimensions of this array and a t_point
as the starting point.
Starting from the given ‘begin’ t_point
, this function fills an entire zone
by replacing characters inside with the character ‘F’. A zone is an group of
the same character delimitated horizontally and vertically by other characters
or the array boundry.
The flood_fill function won’t fill diagonally.
The flood_fill function will be prototyped like this:
void flood_fill(char **tab, t_point size, t_point begin);
The t_point structure is prototyped like this: (put it in flood_fill.c)
typedef struct s_point
{
int x;
int y;
} t_point;
Example:
// test.c
#include <stdlib.h>
#include <stdio.h>
char** make_area(char** zone, t_point size)
{
char** new;
new = malloc(sizeof(char*) * size.y);
for (int i = 0; i < size.y; ++i)
{
new[i] = malloc(size.x + 1);
for (int j = 0; j < size.x; ++j)
new[i][j] = zone[i][j];
new[i][size.x] = '\0';
}
return new;
}
int main(void)
{
t_point size = {8, 5};
char *zone[] = {
"11111111",
"10001001",
"10010001",
"10110001",
"11100001",
};
char** area = make_area(zone, size);
for (int i = 0; i < size.y; ++i)
printf("%s\n", area[i]);
printf("\n");
t_point begin = {7, 4};
flood_fill(area, size, begin);
for (int i = 0; i < size.y; ++i)
printf("%s\n", area[i]);
return (0);
}
$> gcc flood_fill.c test.c -o test; ./test
11111111
10001001
10010001
10110001
11100001
FFFFFFFF
F000F00F
F00F000F
F0FF000F
FFF0000F
$>
Solution
They were kind enough to provide us with a t_point
structure that we can use to represent the dimensions of the 2D array and test.c
to test our implementation.
Looking at 2D array zone
in test.c
, I think we all already can see that the flood_fill
function should fill the area recursively.
Let’s do it!
typedef struct s_point
{
int x;
int y;
} t_point;
char get_val(char **area, t_point node){
return(area[node.y][node.x]);
}
void check_val(char **area, t_point node){
area[node.y][node.x] = 'F';
}
int is_valid(char **area, t_point size, t_point node, char c){
if (node.x < 0 || node.x >= size.x || node.y < 0 || node.y >= size.y)
return(-1);
char next_node_val = get_val(area, node);
if(next_node_val != c)
return(-1);
return(1);
}
void traverse(char **area, t_point size, t_point node, char c){
if(is_valid(area, size, node, c) == 1){
check_val(area, node);
t_point arr[] = {
{node.x, node.y+1}, //top
{node.x, node.y-1}, //bottom
{node.x+1, node.y}, // right
{node.x-1, node.y} // left
};
int i = 3;
while(i >= 0){
t_point next_node = arr[i];
traverse(area, size, next_node, c);
i--;
}
}
}
void flood_fill(char **area, t_point size, t_point begin){
char c = get_val(area, begin); // starting character
traverse(area, size, begin, c);
}
Output with size = {8, 5}
and begin = {7, 4}
:
11111111
10001001
10010001
10110001
11100001
FFFFFFFF
F000F00F
F00F000F
F0FF000F
FFF0000F
Looks good!
Info
Keep in mind that the size is 1-indexed, while the begin point is 0-indexed. This distinction might be confusing at first, especially since
size_t
is commonly used for size representations in C.