Please bookmark this page to avoid losing your image tool!

Video Glitch And Datamosh Effect Generator

(Free & Supports Bulk Upload)

Drag & drop your images here or

The result will appear here...
You can edit the below JavaScript code to customize the image tool.
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;
}

Free Image Tool Creator

Can't find the image tool you're looking for?
Create one based on your own needs now!

Description

The Video Glitch and Datamosh Effect Generator is a tool designed to apply dynamic, psychedelic visual distortions to images, simulating the aesthetic of corrupted video files. It generates various digital artifacts, including datamoshing (pixel smearing), chromatic aberration (RGB splitting), block tearing, pixelation, and scanline noise. Users can customize the visual output by adjusting parameters such as effect intensity, animation speed, block size, and the frequency of image resets. This tool is ideal for digital artists, content creators, and designers looking to add a lo-fi, glitch-art, or vaporwave aesthetic to their visual projects.

Leave a Reply

Your email address will not be published. Required fields are marked *