Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit a769298

Browse files
Merge pull request TheAlgorithms#615 from algobytewise/add-FloodFill
add flood fill
2 parents 229cca1 + 2b2cbfe commit a769298

File tree

1 file changed

+180
-0
lines changed

1 file changed

+180
-0
lines changed

‎Recursive/FloodFill.js‎

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
/**
2+
* Flood fill, also called seed fill, is an algorithm that determines and alters the area connected
3+
* to a given node in a multi-dimensional array with some matching attribute. It is used in the
4+
* "bucket" fill tool of paint programs to fill connected, similarly-colored areas with a different
5+
* color. (description adapted from https://en.wikipedia.org/wiki/Flood_fill) (see also:
6+
* https://www.techiedelight.com/flood-fill-algorithm/).
7+
*/
8+
9+
const neighbors = [[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]]
10+
11+
const black = [0, 0, 0]
12+
const green = [0, 255, 0]
13+
const violet = [255, 0, 255]
14+
const white = [255, 255, 255]
15+
const orange = [255, 128, 0] // eslint-disable-line
16+
17+
/*
18+
Doctests
19+
> testBreadthFirst([1, 1], green, orange, [1, 1]);
20+
orange
21+
> testBreadthFirst([1, 1], green, orange, [0, 1]);
22+
violet
23+
> testBreadthFirst([1, 1], green, orange, [6, 4]);
24+
white
25+
> testDepthFirst([1, 1], green, orange, [1, 1]);
26+
orange
27+
> testDepthFirst([1, 1], green, orange, [0, 1]);
28+
violet
29+
> testDepthFirst([1, 1], green, orange, [6, 4]);
30+
white
31+
*/
32+
33+
/**
34+
* Implements the flood fill algorithm through a breadth-first approach using a queue.
35+
*
36+
* @param rgbData The image to which the algorithm is applied.
37+
* @param location The start location on the image.
38+
* @param targetColor The old color to be replaced.
39+
* @param replacementColor The new color to replace the old one.
40+
*/
41+
function breadthFirstSearch (rgbData, location, targetColor, replacementColor) {
42+
if (location[0] < 0 ||
43+
location[0] >= rgbData.length ||
44+
location[1] < 0 ||
45+
location[1] >= rgbData[0].length) {
46+
throw new Error('location should point to a pixel within the rgbData')
47+
}
48+
49+
const queue = []
50+
queue.push(location)
51+
52+
while (queue.length > 0) {
53+
breadthFirstFill(rgbData, location, targetColor, replacementColor, queue)
54+
}
55+
}
56+
57+
/**
58+
* Implements the flood fill algorithm through a depth-first approach using recursion.
59+
*
60+
* @param rgbData The image to which the algorithm is applied.
61+
* @param location The start location on the image.
62+
* @param targetColor The old color to be replaced.
63+
* @param replacementColor The new color to replace the old one.
64+
*/
65+
function depthFirstSearch (rgbData, location, targetColor, replacementColor) {
66+
if (location[0] < 0 ||
67+
location[0] >= rgbData.length ||
68+
location[1] < 0 ||
69+
location[1] >= rgbData[0].length) {
70+
throw new Error('location should point to a pixel within the rgbData')
71+
}
72+
73+
depthFirstFill(rgbData, location, targetColor, replacementColor)
74+
}
75+
76+
/**
77+
* Utility-function to implement the breadth-first loop
78+
*
79+
* @param rgbData The image to which the algorithm is applied.
80+
* @param location The start location on the image.
81+
* @param targetColor The old color to be replaced.
82+
* @param replacementColor The new color to replace the old one.
83+
* @param queue The locations that still need to be visited.
84+
*/
85+
function breadthFirstFill (rgbData, location, targetColor, replacementColor, queue) {
86+
const currentLocation = queue[0]
87+
queue.shift()
88+
89+
if (rgbData[currentLocation[0]][currentLocation[1]] === targetColor) {
90+
rgbData[currentLocation[0]][currentLocation[1]] = replacementColor
91+
92+
for (let i = 0; i < neighbors.length; i++) {
93+
const x = currentLocation[0] + neighbors[i][0]
94+
const y = currentLocation[1] + neighbors[i][1]
95+
if (x >= 0 && x < rgbData.length && y >= 0 && y < rgbData[0].length) {
96+
queue.push([x, y])
97+
}
98+
}
99+
}
100+
}
101+
102+
/**
103+
* Utility-function to implement the depth-first loop
104+
*
105+
* @param rgbData The image to which the algorithm is applied.
106+
* @param location The start location on the image.
107+
* @param targetColor The old color to be replaced.
108+
* @param replacementColor The new color to replace the old one.
109+
*/
110+
function depthFirstFill (rgbData, location, targetColor, replacementColor) {
111+
if (rgbData[location[0]][location[1]] === targetColor) {
112+
rgbData[location[0]][location[1]] = replacementColor
113+
114+
for (let i = 0; i < neighbors.length; i++) {
115+
const x = location[0] + neighbors[i][0]
116+
const y = location[1] + neighbors[i][1]
117+
if (x >= 0 && x < rgbData.length && y >= 0 && y < rgbData[0].length) {
118+
depthFirstFill(rgbData, [x, y], targetColor, replacementColor)
119+
}
120+
}
121+
}
122+
}
123+
124+
/**
125+
* Generates the rgbData-matrix for the tests
126+
*
127+
* @return example rgbData-matrix
128+
*/
129+
function generateTestRgbData () {
130+
const layout = [
131+
[violet, violet, green, green, black, green, green],
132+
[violet, green, green, black, green, green, green],
133+
[green, green, green, black, green, green, green],
134+
[black, black, green, black, white, white, green],
135+
[violet, violet, black, violet, violet, white, white],
136+
[green, green, green, violet, violet, violet, violet],
137+
[violet, violet, violet, violet, violet, violet, violet]
138+
]
139+
140+
// transpose layout-matrix so the x-index comes before the y-index
141+
const transposed = []
142+
for (let x = 0; x < layout[0].length; x++) {
143+
transposed[x] = []
144+
for (let y = 0; y < layout.length; y++) {
145+
transposed[x][y] = layout[y][x]
146+
}
147+
}
148+
149+
return transposed
150+
}
151+
152+
/**
153+
* Utility-function to test the function "breadthFirstSearch"
154+
*
155+
* @param fillLocation The start location on the image where the flood fill is applied.
156+
* @param targetColor The old color to be replaced.
157+
* @param replacementColor The new color to replace the old one.
158+
* @param testLocation The location of the color to be checked.
159+
* @return The color at testLocation
160+
*/
161+
function testBreadthFirst (fillLocation, targetColor, replacementColor, testLocation) {// eslint-disable-line
162+
const rgbData = generateTestRgbData()
163+
breadthFirstSearch(rgbData, fillLocation, targetColor, replacementColor)
164+
return rgbData[testLocation[0]][testLocation[1]]
165+
}
166+
167+
/**
168+
* Utility-function to test the function "depthFirstSearch"
169+
*
170+
* @param fillLocation The start location on the image where the flood fill is applied.
171+
* @param targetColor The old color to be replaced.
172+
* @param replacementColor The new color to replace the old one.
173+
* @param testLocation The location of the color to be checked.
174+
* @return The color at testLocation
175+
*/
176+
function testDepthFirst (fillLocation, targetColor, replacementColor, testLocation) {// eslint-disable-line
177+
const rgbData = generateTestRgbData()
178+
depthFirstSearch(rgbData, fillLocation, targetColor, replacementColor)
179+
return rgbData[testLocation[0]][testLocation[1]]
180+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /