<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Cartoonify Image</title>
<style>
body { font-family: sans-serif; background: #111; color: white; text-align: center; }
canvas { max-width: 90vw; margin-top: 20px; border: 4px solid white; border-radius: 12px; }
input { margin-top: 20px; }
</style>
</head>
<body>
<h2>Upload Image → Cartoon Effect</h2>
<input type="file" id="upload" accept="image/*">
<canvas id="canvas"></canvas>
<script>
const upload = document.getElementById("upload");
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
upload.addEventListener("change", (e) => {
const file = e.target.files[0];
if (!file) return;
const img = new Image();
img.onload = () => {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
// get image data
let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
let data = imageData.data;
// cartoon effect: reduce colors (posterization)
for (let i = 0; i < data.length; i += 4) {
data[i] = Math.floor(data[i] / 64) * 64; // R
data[i+1] = Math.floor(data[i+1] / 64) * 64; // G
data[i+2] = Math.floor(data[i+2] / 64) * 64; // B
}
// simple edge detection (Sobel filter)
let gray = [];
for (let i = 0; i < data.length; i += 4) {
let avg = (data[i] + data[i+1] + data[i+2]) / 3;
gray.push(avg);
}
let edges = new Uint8ClampedArray(data.length);
for (let y = 1; y < canvas.height - 1; y++) {
for (let x = 1; x < canvas.width - 1; x++) {
let i = y * canvas.width + x;
let gx = -gray[i - canvas.width - 1] - 2*gray[i - 1] - gray[i + canvas.width - 1]
+ gray[i - canvas.width + 1] + 2*gray[i + 1] + gray[i + canvas.width + 1];
let gy = -gray[i - canvas.width - 1] - 2*gray[i - canvas.width] - gray[i - canvas.width + 1]
+ gray[i + canvas.width - 1] + 2*gray[i + canvas.width] + gray[i + canvas.width + 1];
let g = Math.sqrt(gx*gx + gy*gy);
if (g > 80) {
edges[i*4] = edges[i*4+1] = edges[i*4+2] = 0; // black edge
edges[i*4+3] = 255;
} else {
edges[i*4] = data[i*4];
edges[i*4+1] = data[i*4+1];
edges[i*4+2] = data[i*4+2];
edges[i*4+3] = 255;
}
}
}
ctx.putImageData(new ImageData(edges, canvas.width, canvas.height), 0, 0);
};
img.src = URL.createObjectURL(file);
});
</script>
</body>
</html>