Я использую алгоритм floodFill, но он очень медленно. Например, у меня есть холст (512px x 512px), и для заполнения всего холста мне нужно 6 секунд. Можете ли вы помочь мне улучшить мою реализацию? Я использую алгоритм из http://www.williammalone.com/articles/html5-canvas-javascript-paint-bucket-tool/
И вот ссылка, где я пытался улучшить свой алгоритм: https://labs.eleks.com/2012/11/html5-canvas-performance-and.html
function flood(context, canvas, color, target) {
function floodFill(startX, startY, color) {
function isStartColor(position, startColor, imageData) {
if ((imageData[position + 0]) != ((startColor >> 24) & 0xFF)
|| (imageData[position + 1]) != ((startColor >> 16) & 0xFF)
|| (imageData[position + 2]) != ((startColor >> 8) & 0xFF)) {
return false;
}
return true;
}
function drawPixel(position, imageData) {
imageData[position] = color.r;
imageData[position + 1] = color.g;
imageData[position + 2] = color.b;
imageData[position + 3] = 255;
}
let stack = [[startX, startY]];
while (stack.length) {
const image = context.getImageData(0, 0, canvas.width, canvas.height);
const imageData = image.data;
const newPosition = stack.pop();
const x = Math.round(newPosition[0]);
const y = Math.round(newPosition[1]);
const pixelPosition = (y * canvas.width + x) * 4;
const startColor = {
r: imageData[pixelPosition + 0] << 24,
g: imageData[pixelPosition + 1] << 16,
b: imageData[pixelPosition + 2] << 8
}
while (y-- >= 0 && isStartColor(pixelPosition, startColor, imageData)) {
pixelPosition = pixelPosition - canvas.width * 4;
}
y++;
pixelPosition = pixelPosition + canvas.width * 4;
let reachLeft = false;
let reachRight = false;
while (y++ < canvas.height - 1 && isStartColor(pixelPosition, startColor, imageData)) {
drawPixel(pixelPosition, imageData);
if (x > 0) {
if (isStartColor(pixelPosition - 4, startColor, imageData)) {
if (!reachLeft) {
stack.push([x - 1, y]);
reachLeft = true;
}
} else {
if (reachLeft) {
reachLeft = false;
}
}
}
if (x < canvas.width - 1) {
if (isStartColor(pixelPosition + 4, startColor, imageData)) {
if (!reachRight) {
stack.push([x + 1, y]);
reachRight = true;
}
} else {
if (reachRight) {
reachRight = false;
}
}
}
pixelPosition = pixelPosition + canvas.width * 4;
}
context.putImageData(image, 0, 0);
}
}
const canvasHTMLWidth = document.querySelector('.main-canvas').offsetWidth;
const canvasHTMLHeight = document.querySelector('.main-canvas').offsetHeight;
let xCoordinateScale;
let yCoordinateScale;
function getCoodinateScale() {
xCoordinateScale = (canvasHTMLWidth / canvas.width);
yCoordinateScale = (canvasHTMLHeight / canvas.height);
}
function hexToRgb(hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16),
a: 255
} : null;
}
getCoodinateScale();
const floodColor = hexToRgb(color.value);
canvas.addEventListener('mousedown', (event) => {
if (!target.classList.contains('active-tool')) {
return
}
floodFill(event.offsetX / xCoordinateScale, event.offsetY / yCoordinateScale, floodColor);
});
}