You can edit the below JavaScript code to customize the image tool.
Apply Changes
async function processImage(originalImg, intensity = "50", damageType = "all") {
let level = parseFloat(intensity);
if (isNaN(level)) level = 50;
level = Math.max(0, Math.min(100, level));
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = Math.max(1, originalImg.width);
canvas.height = Math.max(1, originalImg.height);
// Fill white background to handle transparent images
ctx.fillStyle = '#ffffff';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(originalImg, 0, 0);
const loadImage = (url) => new Promise((resolve) => {
const img = new Image();
img.onload = () => resolve(img);
img.src = url;
});
// 1. Digital Damage (Generation Loss & Glitches)
if (damageType === "all" || damageType === "digital") {
const passes = Math.floor((level / 100) * 8); // MAX 8 passes
for (let i = 0; i < passes; i++) {
const quality = Math.max(0.01, 0.3 - (level / 100) * 0.25);
const dataUrl = canvas.toDataURL('image/jpeg', quality);
const tempImg = await loadImage(dataUrl);
ctx.drawImage(tempImg, 0, 0);
}
const glitchLines = Math.floor(level / 2);
for (let i = 0; i < glitchLines; i++) {
const y = Math.random() * canvas.height;
const h = Math.random() * (canvas.height * 0.05) + 2;
const shiftX = (Math.random() - 0.5) * (level / 100) * canvas.width * 0.15;
const slice = ctx.getImageData(0, y, canvas.width, h);
const tmpCanvas = document.createElement('canvas');
tmpCanvas.width = canvas.width;
tmpCanvas.height = h;
const tCtx = tmpCanvas.getContext('2d');
tCtx.putImageData(slice, 0, 0);
ctx.fillStyle = Math.random() > 0.5 ? '#000000' : '#ffffff';
ctx.fillRect(0, y, canvas.width, h);
ctx.drawImage(tmpCanvas, shiftX, y);
if (Math.random() > 0.5) {
ctx.fillStyle = Math.random() > 0.5 ? 'rgba(255,0,0,0.3)' : 'rgba(0,255,255,0.3)';
ctx.globalCompositeOperation = 'screen';
ctx.fillRect(Math.max(0, shiftX), y, canvas.width, h);
ctx.globalCompositeOperation = 'source-over';
}
}
}
// 2. Physical Damage (Cracks, Scratches, Dirt)
if (damageType === "all" || damageType === "physical") {
const area = canvas.width * canvas.height;
// Scratches
const scratchCount = (level / 100) * (area / 10000);
for (let i = 0; i < scratchCount; i++) {
ctx.beginPath();
let x = Math.random() * canvas.width;
let y = Math.random() * canvas.height;
ctx.moveTo(x, y);
let len = Math.random() * 100 + 10;
let angle = Math.random() * Math.PI * 2;
let pX = x + Math.cos(angle) * len;
let pY = y + Math.sin(angle) * len;
let steps = Math.floor(len / 5);
for(let j = 0; j < steps; j++) {
x += (pX - x) / (steps - j) + (Math.random() - 0.5) * 5;
y += (pY - y) / (steps - j) + (Math.random() - 0.5) * 5;
ctx.lineTo(x, y);
}
ctx.strokeStyle = `rgba(0,0,0,${Math.random() * 0.4 + 0.1})`;
ctx.lineWidth = Math.random() * 2 + 1;
ctx.stroke();
ctx.strokeStyle = `rgba(255,255,255,${Math.random() * 0.5 + 0.2})`;
ctx.lineWidth = ctx.lineWidth / 2;
ctx.stroke();
}
// Cracks
const crackCount = Math.floor(level / 25);
for (let c = 0; c < crackCount; c++) {
const impactX = Math.random() * canvas.width;
const impactY = Math.random() * canvas.height;
const rays = Math.floor(Math.random() * 5) + 5;
for (let r = 0; r < rays; r++) {
let x = impactX;
let y = impactY;
let angle = (Math.PI * 2 / rays) * r + (Math.random() - 0.5);
let length = (Math.random() * 0.5 + 0.5) * Math.max(canvas.width, canvas.height);
ctx.beginPath();
ctx.moveTo(x, y);
let currentLen = 0;
while (currentLen < length) {
let step = Math.random() * 30 + 10;
currentLen += step;
angle += (Math.random() - 0.5) * 0.8;
x += Math.cos(angle) * step;
y += Math.sin(angle) * step;
ctx.lineTo(x, y);
if (Math.random() < 0.3) {
let bx = x;
let by = y;
let bangle = angle + (Math.random() > 0.5 ? 1 : -1) * (0.5 + Math.random());
let bstep = Math.random() * 60 + 20;
ctx.moveTo(x, y);
let cx = bx, cy = by;
for(let k = 0; k < 3; k++) {
cx += Math.cos(bangle) * (bstep / 3);
cy += Math.sin(bangle) * (bstep / 3);
bangle += (Math.random() - 0.5) * 0.5;
ctx.lineTo(cx, cy);
}
ctx.moveTo(x, y);
}
}
ctx.strokeStyle = 'rgba(0, 0, 0, 0.6)';
ctx.lineWidth = 1.5;
ctx.stroke();
ctx.strokeStyle = 'rgba(255, 255, 255, 0.5)';
ctx.lineWidth = 0.5;
ctx.stroke();
}
}
// Dirt Splatters
const stainCount = (level / 100) * (area / 15000);
for (let i = 0; i < stainCount; i++) {
let cx = Math.random() * canvas.width;
let cy = Math.random() * canvas.height;
let r = Math.random() * 20 + 5;
ctx.beginPath();
ctx.arc(cx, cy, r, 0, Math.PI * 2);
ctx.fillStyle = `rgba(50, 40, 30, ${Math.random() * 0.5 * (level / 100)})`;
ctx.fill();
let splatterCount = Math.random() * 5;
for(let s = 0; s < splatterCount; s++) {
ctx.beginPath();
let sx = cx + (Math.random() - 0.5) * r * 3;
let sy = cy + (Math.random() - 0.5) * r * 3;
let sr = Math.random() * r * 0.3;
ctx.arc(sx, sy, sr, 0, Math.PI * 2);
ctx.fill();
}
}
}
// 3. Time Damage (Fading, Sepia, Noise, Vignette)
if (damageType === "all" || damageType === "time") {
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;
const fadeStrength = (level / 100) * 0.8;
const noiseStrength = (level / 100) * 80;
for (let i = 0; i < data.length; i += 4) {
let r = data[i];
let g = data[i + 1];
let b = data[i + 2];
// Aging fade/sepia tint
let gray = 0.3 * r + 0.59 * g + 0.11 * b;
data[i] = r + ((gray + 40) - r) * fadeStrength;
data[i + 1] = g + ((gray + 20) - g) * fadeStrength;
data[i + 2] = b + ((gray - 10) - b) * fadeStrength;
// Add grain/noise
if (noiseStrength > 0) {
let noise = (Math.random() - 0.5) * noiseStrength;
data[i] = Math.min(255, Math.max(0, data[i] + noise));
data[i+1] = Math.min(255, Math.max(0, data[i+1] + noise));
data[i+2] = Math.min(255, Math.max(0, data[i+2] + noise));
}
}
ctx.putImageData(imageData, 0, 0);
if (level > 0) {
const cx = canvas.width / 2;
const cy = canvas.height / 2;
const maxRadius = Math.sqrt(cx * cx + cy * cy);
const gradientRadius = maxRadius * Math.max(0.1, 1 - (level / 100) * 0.6);
const gradient = ctx.createRadialGradient(cx, cy, gradientRadius, cx, cy, maxRadius);
gradient.addColorStop(0, 'rgba(0,0,0,0)');
gradient.addColorStop(1, `rgba(0,0,0,${(level / 100) * 0.9})`);
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
}
return canvas;
}
Apply Changes