I tried to implement a very simple color flood fill to experiment a bit with Javascript. All comments about the code are welcome but I am especially interested in performance as it seems to be a bit slow. The browser tools only tell me that there is apparently a bunch of minor garbage collecting going on.
function setPixelColor(cvs, data, row, col, color) {
const [red, green, blue] = color;
data[4 * (row * cvs.width + col)] = red;
data[4 * (row * cvs.width + col) + 1] = green;
data[4 * (row * cvs.width + col) + 2] = blue;
data[4 * (row * cvs.width + col) + 3] = 255;
}
function getPixelColor(cvs, data, row, col) {
return [data[4 * (row * cvs.width + col)],
data[4 * (row * cvs.width + col) + 1],
data[4 * (row * cvs.width + col) + 2]];
}
function arr_eq(arr1, arr2) {
if(arr1.length != arr2.length) {
return false
}
for(let i=0; i<arr1.length; i++) {
if(arr1[i] !== arr2[i]) {
return false
}
}
return true;
}
(function () {
const cvs = document.getElementById("paint");
const ctx = cvs.getContext('2d');
// black background
ctx.fillStyle='black';
ctx.fillRect(0, 0, cvs.width, cvs.height);
const imageData = ctx.getImageData(0, 0, cvs.width, cvs.height);
const data = imageData.data;
const start = [[40, 40, [255, 0, 0]],
[10, 20, [0, 255, 0]],
[23, 42, [0, 0, 255]],
[300, 333, [255, 255, 0]],
[200, 333, [255, 0, 255]]];
for(point of start) {
let [r, c, v] = point;
setPixelColor(cvs, data, r, c, v);
}
let queue = start.slice(0); // clone
while(queue.length > 0) {
p = queue.shift();
let [r,c] = p;
const vcur = getPixelColor(cvs, data, r, c);
for (const n of [[r+1,c], [r-1,c], [r,c+1], [r,c-1]]) {
const [rn, cn] = n;
if (rn >= 0 && rn < cvs.height && cn >= 0 && cn < cvs.width) {
const vn = getPixelColor(cvs, data, rn, cn);
if (arr_eq(vn, [0, 0, 0])) {
setPixelColor(cvs, data, rn, cn, vcur);
queue.push(n);
}
}
}
}
for(point of start) {
let [r, c, v] = point;
setPixelColor(cvs, data, r, c, [0, 0, 0]);
}
ctx.putImageData(imageData, 0, 0);
})();
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>test</title>
</head>
<body>
<canvas id="paint" width=500px height=500px />
<script src="test.js"></script>
</body>
</html>