You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, intensity = "5", speed = "5", blockSize = "16", resetFreq = "3") {
// Parse parameters to numbers with fallback defaults
const currentIntensity = isNaN(Number(intensity)) ? 5 : Number(intensity);
const animSpeed = isNaN(Number(speed)) ? 5 : Number(speed);
const reqBlockSize = isNaN(Number(blockSize)) ? 16 : Number(blockSize);
const iFrameFreq = isNaN(Number(resetFreq)) ? 3 : Number(resetFreq);
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d', { willReadFrequently: true });
canvas.width = originalImg.width;
canvas.height = originalImg.height;
const w = canvas.width;
const h = canvas.height;
// Safety check for block sizes bounded by image dimensions
const actualBlockSize = Math.max(1, Math.min(reqBlockSize, w, h, 64));
// Create an offscreen canvas to keep pristine original image
const origCanvas = document.createElement('canvas');
origCanvas.width = w;
origCanvas.height = h;
const origCtx = origCanvas.getContext('2d');
origCtx.drawImage(originalImg, 0, 0, w, h);
// Initial draw to current frame buffer
ctx.drawImage(originalImg, 0, 0, w, h);
let hasBeenAttached = false;
let frame = 0;
let motionX = 0;
let motionY = 0;
function render() {
frame++;
// Anti-memory leak system: Stop animation if detached from DOM
if (frame % 60 === 0) {
if (document.body.contains(canvas)) {
hasBeenAttached = true;
} else if (hasBeenAttached) {
return;
} else if (frame > 600) {
return;
}
}
const dynamicSpeed = animSpeed * (Math.random() * 0.5 + 0.5);
const dynamicIntensity = currentIntensity * (Math.random() * 0.5 + 0.5);
// Generate random motion vector for datamosh smeared flows
if (Math.random() < 0.1) {
motionX = Math.floor((Math.random() * 10 - 5) * (dynamicSpeed / 3));
motionY = Math.floor((Math.random() * 10 - 5) * (dynamicSpeed / 3));
}
// --- Simulated I-frame recovery (Resetting corrupted macroblocks) ---
if (Math.random() < (iFrameFreq / 50)) {
const rw = Math.max(1, Math.floor(Math.random() * w * 0.8));
const rh = Math.max(1, Math.floor(Math.random() * h * 0.8));
const rx = Math.max(0, Math.floor(Math.random() * (w - rw)));
const ry = Math.max(0, Math.floor(Math.random() * (h - rh)));
ctx.drawImage(origCanvas, rx, ry, rw, rh, rx, ry, rw, rh);
}
// --- Major Structural Glitch (V-Sync loss / heavy corruption jump) ---
if (Math.random() < dynamicIntensity * 0.005) {
const vy = Math.floor((Math.random() * 100 - 50));
const vx = Math.floor((Math.random() * 100 - 50));
const tempC = document.createElement('canvas');
tempC.width = w; tempC.height = h;
tempC.getContext('2d').drawImage(canvas, 0, 0);
ctx.clearRect(0, 0, w, h);
ctx.drawImage(tempC, vx, vy);
ctx.globalCompositeOperation = 'destination-over';
ctx.drawImage(origCanvas, 0, 0);
ctx.globalCompositeOperation = 'source-over';
}
// --- Datamoshing (P-frame motion vector smearing) ---
if (Math.random() < 0.6) {
const numSmears = Math.floor(Math.random() * dynamicIntensity * 2);
for (let i = 0; i < numSmears; i++) {
const sw = Math.min(w, Math.floor(Math.random() * 8 + 1) * actualBlockSize);
const sh = Math.min(h, Math.floor(Math.random() * 8 + 1) * actualBlockSize);
const sx = Math.max(0, Math.floor(Math.random() * (w - sw)));
const sy = Math.max(0, Math.floor(Math.random() * (h - sh)));
ctx.drawImage(canvas, sx, sy, sw, sh, sx + motionX, sy + motionY, sw, sh);
}
}
// --- Glitch Block Tearing ---
if (Math.random() < dynamicIntensity * 0.1) {
const numTears = Math.floor(Math.random() * dynamicIntensity);
for (let i = 0; i < numTears; i++) {
const th = Math.min(h, Math.floor(Math.random() * actualBlockSize * 2) + 2);
const ty = Math.max(0, Math.floor(Math.random() * (h - th)));
const tx = Math.floor((Math.random() * 40 - 20) * (dynamicIntensity / 5));
if (tx === 0) continue;
// Slice a tear strip to wrap around horizontal offsets
const tearCanvas = document.createElement('canvas');
tearCanvas.width = w;
tearCanvas.height = th;
const tCtx = tearCanvas.getContext('2d');
tCtx.drawImage(canvas, 0, ty, w, th, 0, 0, w, th);
ctx.drawImage(tearCanvas, 0, 0, w, th, tx, ty, w, th);
if (tx > 0) {
ctx.drawImage(tearCanvas, w - tx, 0, tx, th, 0, ty, tx, th);
} else if (tx < 0) {
ctx.drawImage(tearCanvas, 0, 0, -tx, th, w + tx, ty, -tx, th);
}
}
}
// --- Chromatic Aberration / RGB Split ---
if (Math.random() < dynamicIntensity * 0.05) {
const splitH = Math.min(h, Math.max(1, Math.floor(Math.random() * (h / 2)) + 10));
const splitY = Math.max(0, Math.floor(Math.random() * (h - splitH)));
if (splitH > 0) {
const imgData = ctx.getImageData(0, splitY, w, splitH);
const data = imgData.data;
const shift = Math.floor((Math.random() * 3 + 1) * (dynamicIntensity / 2)) * 4;
for (let i = 0; i < data.length; i += 4) {
if (i + shift < data.length) {
data[i] = data[i + shift]; // Offset Red Channel
}
if (i - shift > 0) {
data[i + 2] = data[i - shift + 2]; // Offset Blue Channel
}
}
ctx.putImageData(imgData, 0, splitY);
}
}
// --- Pixelation Simulation (JPEG macro-block degradation) ---
if (Math.random() < dynamicIntensity * 0.03) {
const qw = Math.min(w, actualBlockSize * Math.ceil(Math.random() * 4));
const qh = Math.min(h, actualBlockSize * Math.ceil(Math.random() * 4));
const qx = Math.max(0, Math.floor(Math.random() * (w - qw)));
const qy = Math.max(0, Math.floor(Math.random() * (h - qh)));
const tmpW = Math.max(1, Math.floor(qw / Math.floor(Math.random() * 4 + 2)));
const tmpH = Math.max(1, Math.floor(qh / Math.floor(Math.random() * 4 + 2)));
if (qw > 0 && qh > 0) {
const tmpCanvas = document.createElement('canvas');
tmpCanvas.width = tmpW;
tmpCanvas.height = tmpH;
const tmpCtx = tmpCanvas.getContext('2d');
// Draw downsampled
tmpCtx.drawImage(canvas, qx, qy, qw, qh, 0, 0, tmpW, tmpH);
// Draw upsampled sharply
ctx.imageSmoothingEnabled = false;
ctx.drawImage(tmpCanvas, 0, 0, tmpW, tmpH, qx, qy, qw, qh);
ctx.imageSmoothingEnabled = true;
}
}
// --- Datamoshing Bloom ---
if (Math.random() < dynamicIntensity * 0.02) {
const bw = Math.min(w, actualBlockSize * Math.ceil(Math.random() * 3));
const bh = Math.min(h, actualBlockSize * Math.ceil(Math.random() * 3));
const bx = Math.max(0, Math.floor(Math.random() * (w - bw)));
const by = Math.max(0, Math.floor(Math.random() * (h - bh)));
const dirX = Math.sign(Math.random() - 0.5) * bw;
const dirY = Math.sign(Math.random() - 0.5) * bh;
// Replicate block outwards to simulate expanding corruption trails
for (let i = 1; i < 5; i++) {
ctx.drawImage(canvas, bx, by, bw, bh, bx + dirX * i, by + dirY * i, bw, bh);
}
}
// --- Video Scanlines / Artifact Noise ---
if (Math.random() < 0.2) {
ctx.fillStyle = 'rgba(0, 0, 0, ' + (Math.random() * 0.05) + ')';
for (let y = 0; y < h; y += Math.floor(Math.random() * 4 + 2)) {
ctx.fillRect(0, y, w, Math.random() * 2);
}
// Minor colored tape noise
ctx.fillStyle = `rgba(${Math.random()*255}, ${Math.random()*255}, ${Math.random()*255}, 0.02)`;
ctx.fillRect(0, 0, w, h);
}
// Scale loop frequency based on user provided speed, bounded safely
setTimeout(() => {
requestAnimationFrame(render);
}, 1000 / Math.max(10, Math.min(60, 15 + animSpeed * 3)));
}
// Begin render animation loop
render();
return canvas;
}
Apply Changes