I have a flood fill I’m using from another post on here.
I removed all the alpha channels but the colors are off.
I’v racked my brain for days changing things around and using different fill methods but this one has gotten me closest. I’ll be having users draw and fill as they please. Sorry if this is something simple.
<canvas id="myCanvas" width="300" height="150" style="border:1px solid grey"></canvas>
<script>
const c = document.getElementById("myCanvas");
const ctx = c.getContext("2d");
ctx.strokeStyle = "rgb(252, 53, 3)";
ctx.strokeRect(10, 10, 50, 50);
var red = [3, 252, 3];
floodFill(ctx, 15, 15, red);
ctx.strokeStyle = "rgb(3, 252, 3)";
ctx.strokeRect(75, 10, 50, 50);
var green = [3, 252, 3];
floodFill(ctx, 80, 15, green);
ctx.strokeStyle = "rgb(3, 119, 252)";
ctx.strokeRect(150, 10, 50, 50);
var blue = [3, 119, 252];
floodFill(ctx, 155, 15, blue);
ctx.strokeStyle = "rgb(0, 0, 0)";
ctx.strokeRect(225, 10, 50, 50);
var black = [0, 0, 0];
//floodFill(ctx, 230, 15, black);
//black get's stackoverflow and crashes page
function getPixel(imageData, x, y) {
if (x < 0 || y < 0 || x >= imageData.width || y >= imageData.height) {
return [-1, -1, -1, -1]; // impossible color
} else {
const offset = (y * imageData.width + x) * 4;
var pixel = imageData.data.slice(offset, offset + 4);
pixel[3] = 1; // ignore alpha
return pixel;
}
}
function setPixel(imageData, x, y, color) {
const offset = (y * imageData.width + x) * 4;
imageData.data[offset + 0] = color[0];
imageData.data[offset + 1] = color[1];
imageData.data[offset + 2] = color[2];
imageData.data[offset + 3] = color[0];
}
function colorsMatch(a, b, rSq) {
if (a === b) return true;
if (a == null || b == null) return false;
if (a.length !== b.length) return false;
for (var i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) return false;
}
return true;
}
function floodFill(ctx, x, y, fillColor, range = 1) {
// read the pixels in the canvas
const imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height);
// flags for if we visited a pixel already
const visited = new Uint8Array(imageData.width, imageData.height);
// get the color we're filling
const targetColor = getPixel(imageData, x, y);
console.log("target: " + targetColor + "Fill: " + fillColor);
// check we are actually filling a different color
if (!colorsMatch(targetColor, fillColor)) {
const rangeSq = range * range;
const pixelsToCheck = [x, y];
while (pixelsToCheck.length > 0) {
const y = pixelsToCheck.pop();
const x = pixelsToCheck.pop();
const currentColor = getPixel(imageData, x, y);
if (!visited[y * imageData.width + x] && colorsMatch(currentColor, targetColor, rangeSq)) {
setPixel(imageData, x, y, fillColor);
visited[y * imageData.width + x] = 1; // mark we were here already
pixelsToCheck.push(x + 1, y);
pixelsToCheck.push(x - 1, y);
pixelsToCheck.push(x, y + 1);
pixelsToCheck.push(x, y - 1);
}
}
// put the data back
ctx.putImageData(imageData, 0, 0);
}
}
</script>
I don’t know what is causing the issue, if I try to pass in rgb value black (0,0,0) it crashes.