Show code
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Floyd-Steinberg Dithering</title>
<style>
body {margin: 0; overflow: hidden;}
canvas {display: block;}
div {position: absolute; top: 10px; left: 10px; color: white; font-size: 20px;}
</style>
</head>
<body>
<canvas id="canvas"></canvas><div id="info"></div>
<script>
function createImageData(canvas) {
const width = canvas.width;
const height = canvas.height;
return new ImageData(width, height);
}
function setPixel(data, x, y, value) {
data.data[(y * data.width + x) * 4] = value;
data.data[(y * data.width + x) * 4 + 1] = value;
data.data[(y * data.width + x) * 4 + 2] = value;
data.data[(y * data.width + x) * 4 + 3] = 255;
}
function getPixel(data, x, y) {
return data.data[(y * data.width + x) * 4];
}
function dither(imgData, paletteSize) {
const width = imgData.width;
const height = imgData.height;
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const oldPixel = getPixel(imgData, x, y);
const newPixel = Math.round(oldPixel / paletteSize) * paletteSize;
setPixel(imgData, x, y, newPixel);
const error = oldPixel - newPixel;
if (x + 1 < width) setPixel(imgData, x + 1, y, getPixel(imgData, x + 1, y) + (error * 7 / 16));
if (x - 1 >= 0 && y + 1 < height) setPixel(imgData, x - 1, y + 1, getPixel(imgData, x - 1, y + 1) + (error * 3 / 16));
if (y + 1 < height) setPixel(imgData, x, y + 1, getPixel(imgData, x, y + 1) + (error * 5 / 16));
if (x + 1 < width && y + 1 < height) setPixel(imgData, x + 1, y + 1, getPixel(imgData, x + 1, y + 1) + (error * 1 / 16));
}
}
return imgData;
}
function drawCanvas(ctx, imgData, paletteSize, frame) {
ctx.putImageData(dither(imgData, paletteSize), 0, 0);
document.getElementById("info").textContent = `Palette Size: ${paletteSize} Frame: ${frame}`;
}
function animate(canvas, ctx, paletteSize, frame) {
const imgData = createImageData(canvas);
for (let y = 0; y < canvas.height; y++) {
for (let x = 0; x < canvas.width; x++) {
const value = Math.sin(x / 20 + frame / 10) * 127 + 128;
setPixel(imgData, x, y, value);
}
}
drawCanvas(ctx, imgData, paletteSize, frame);
frame++;
if (frame < 360) requestAnimationFrame(() => animate(canvas, ctx, Math.floor(Math.random() * 5) + 1, frame));
else canvas.width = 800; // Restart
}
const canvas = document.getElementById("canvas");
canvas.width = 800;
canvas.height = 600;
animate(canvas, canvas.getContext('2d'), Math.floor(Math.random() * 5) + 1, 0);
</script>
</body>
</html>
```