Please bookmark this page to avoid losing your image tool!

HIFI Stereo Mono VHSRip 16mm Photo Filter Tool

(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,
    stereoOffset = 4,         // Spread of the red/blue channel split (chromatic aberration)
    contrastLevel = 45,       // High contrast 16mm look (0 - 100)
    noiseAmount = 40,         // Overall film grain intensity (0 - 100)
    glitchAmount = 25,        // VHS horizontal tracking shift intensity (0 - 100)
    scanlineOpacity = 0.15    // Opacity of the VHS scanlines (0.0 - 1.0)
) {
    // 1. Core Canvas Setup
    const canvas = document.createElement('canvas');
    const w = originalImg.width;
    const h = originalImg.height;
    canvas.width = w;
    canvas.height = h;
    const ctx = canvas.getContext('2d');

    // Draw base image slightly blurred to simulate degraded VHS/16mm focus
    ctx.filter = 'blur(0.5px)';
    ctx.drawImage(originalImg, 0, 0);

    // 2. Glitch Shifts (VHS Tracking Glitches)
    if (glitchAmount > 0) {
        // Draw horizontal shifted slices from original image
        const numGlitches = Math.floor(glitchAmount * 0.5);
        for (let i = 0; i < numGlitches; i++) {
            let sy = Math.floor(Math.random() * h);
            let sh = Math.floor(Math.random() * (h * 0.05)) + 2; 
            let dx = (Math.random() - 0.5) * glitchAmount * (w / 200); 
            ctx.drawImage(originalImg, 0, sy, w, sh, dx, sy, w, sh);
        }
    }
    
    ctx.filter = 'none';

    // 3. Pixel Manipulation (Mono Grayscale, Contrast, Grain, Stereo Channel Shift)
    const imgData = ctx.getImageData(0, 0, w, h);
    const data = imgData.data;
    const monoData = new Uint8ClampedArray(data.length);
    
    // Calculate contrast factor
    const factor = (259 * (contrastLevel + 255)) / (255 * (259 - contrastLevel));

    // First pass: Generate Mono, Contrast, and Grain data
    for (let i = 0; i < data.length; i += 4) {
        let r = data[i];
        let g = data[i + 1];
        let b = data[i + 2];

        // Mono/Grayscale
        let lum = 0.299 * r + 0.587 * g + 0.114 * b;

        // Apply Contrast
        lum = factor * (lum - 128) + 128;

        // Apply 16mm Noise / Grain
        let noise = (Math.random() - 0.5) * noiseAmount * 2;
        lum += noise;

        // Clamp values
        lum = Math.min(255, Math.max(0, lum));

        monoData[i] = lum;
        monoData[i + 1] = lum;
        monoData[i + 2] = lum;
        monoData[i + 3] = data[i + 3];
    }

    // Second pass: Apply "HIFI Stereo" chromatic split
    let offsetBytes = Math.floor(stereoOffset * Math.max(1, w / 800)) * 4;

    for (let y = 0; y < h; y++) {
        let rowStart = y * w * 4;
        let rowEnd = (y + 1) * w * 4 - 4;

        for (let x = 0; x < w; x++) {
            let i = (y * w + x) * 4;
            let rIdx = i - offsetBytes;
            let bIdx = i + offsetBytes;

            // Constrain red/blue shift inside the horizontal limits of the current row
            let rVal = (rIdx >= rowStart) ? monoData[rIdx] : monoData[i];
            let bVal = (bIdx <= rowEnd) ? monoData[bIdx] : monoData[i];
            let gVal = monoData[i + 1]; // Green stays center

            data[i] = rVal;
            data[i + 1] = gVal;
            data[i + 2] = bVal;
            // alpha remains exactly the same
        }
    }
    
    // Commit modified pixels
    ctx.putImageData(imgData, 0, 0);

    // 4. VHS Bottom Tracking Static
    if (glitchAmount > 0) {
        const trackH = Math.max(5, Math.floor(h * 0.04));
        const trackY = h - trackH - Math.floor(Math.random() * (h * 0.02));
        if(trackY > 0) {
            const trackData = ctx.getImageData(0, trackY, w, trackH);
            for (let i = 0; i < trackData.data.length; i += 4) {
                if (Math.random() < 0.6) { // Snow effect
                    let gray = Math.random() * 255;
                    trackData.data[i] = gray;
                    trackData.data[i + 1] = gray;
                    trackData.data[i + 2] = gray;
                }
            }
            ctx.putImageData(trackData, 0, trackY);
            // Draw tracking distortion line
            ctx.fillStyle = 'rgba(255,255,255,0.7)';
            ctx.fillRect(0, trackY + trackH / 2, w, Math.max(1, Math.floor(h / 400)));
        }
    }

    // 5. Classic Overlay Aesthetics (Text Play Timestamp & 16mm Scratches)
    // Draw "PLAY" UI
    ctx.fillStyle = 'rgba(230, 230, 230, 0.9)';
    ctx.font = 'bold ' + Math.max(16, Math.floor(h * 0.04)) + 'px "Courier New", Courier, monospace';
    ctx.shadowColor = 'black';
    ctx.shadowBlur = 4;
    ctx.textAlign = 'left';
    ctx.textBaseline = 'top';
    ctx.fillText("PLAY \u25BA", w * 0.05, h * 0.05);

    ctx.textAlign = 'right';
    ctx.fillText("SP 0:00:00", w * 0.95, h * 0.05);
    ctx.shadowBlur = 0; // Reset Shadow

    // 16mm Dust and Scratches
    const numScratches = Math.floor(Math.random() * 5) + 1;
    ctx.strokeStyle = 'rgba(255, 255, 255, 0.25)';
    for (let i = 0; i < numScratches; i++) {
        ctx.beginPath();
        let px = Math.random() * w;
        ctx.moveTo(px, 0);
        ctx.lineWidth = Math.random() * 1.5 + 0.5;
        // Jagged vertical line down the frame
        for (let py = 0; py <= h; py += Math.random() * 50 + 20) {
            px += (Math.random() - 0.5) * 3;
            ctx.lineTo(px, py);
        }
        ctx.stroke();
    }

    // 6. VHS Scanlines
    if (scanlineOpacity > 0) {
        ctx.fillStyle = `rgba(0, 0, 0, ${scanlineOpacity})`;
        let lineThickness = Math.max(1, Math.floor(h / 600));
        let lineSpacing = lineThickness * 3;
        for (let y = 0; y < h; y += lineSpacing) {
            ctx.fillRect(0, y, w, lineThickness);
        }
    }

    // 7. Dark Edge Vignette
    const grad = ctx.createRadialGradient(
        w / 2, h / 2, Math.max(w, h) * 0.35,
        w / 2, h / 2, Math.max(w, h) * 0.75
    );
    grad.addColorStop(0, 'rgba(0,0,0,0)');
    grad.addColorStop(1, 'rgba(0,0,0,0.65)');
    ctx.fillStyle = grad;
    ctx.fillRect(0, 0, w, h);

    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 HIFI Stereo Mono VHSRip 16mm Photo Filter Tool applies vintage analog aesthetics to your images. It simulates the unique look of 16mm film and VHS tapes by incorporating effects such as film grain, high contrast, chromatic aberration (stereo channel splitting), and horizontal tracking glitches. The tool also adds classic retro overlays, including scanlines, VHS ‘PLAY’ timestamps, dust scratches, and a vignette effect. This tool is ideal for digital artists, social media creators, or anyone looking to give modern photos a nostalgic, lo-fi, or cinematic retro feel.

Leave a Reply

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