Please bookmark this page to avoid losing your image tool!

Image VHS Filter Video And Audio Converter

(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.
async function processImage(originalImg, noiseAmount = 0.15, scanlineIntensity = 0.2, channelShift = 4, glitchIntensity = 0.3, osdText = "REC ● 01:23:45") {
    // This function applies a VHS-style filter to an image.
    // The "Video and Audio" parts of the tool name are interpreted as providing
    // the aesthetic of a VHS recording, as processing actual video/audio is
    // beyond the scope of a function that takes a single image object.

    // Step 1: Dynamically load a retro-looking font for the OSD text.
    // We use the FontFace API to load 'VT323' from Google Fonts.
    // The function is async to wait for the font to be available.
    try {
        const font = new FontFace('VT323', 'url(https://fonts.gstatic.com/s/vt323/v17/loBsmMgpcv_OC_2gfC_am0QN.woff2)');
        await font.load();
        document.fonts.add(font);
    } catch (e) {
        console.error("VHS filter font could not be loaded. Using a fallback font.", e);
    }

    // Step 2: Set up the canvas.
    const canvas = document.createElement('canvas');
    // Using { willReadFrequently: true } can improve performance for repeated getImageData calls.
    const ctx = canvas.getContext('2d', {
        willReadFrequently: true
    });
    const w = originalImg.naturalWidth;
    const h = originalImg.naturalHeight;
    canvas.width = w;
    canvas.height = h;

    // Step 3: Draw the original image with a slight blur to mimic lower resolution.
    ctx.filter = 'blur(0.6px)';
    ctx.drawImage(originalImg, 0, 0, w, h);
    ctx.filter = 'none';

    // Step 4: Apply Chromatic Aberration & Color Bleeding effect.
    // This is done by shifting the Red and Blue color channels horizontally.
    const imageData = ctx.getImageData(0, 0, w, h);
    const data = imageData.data;
    const originalData = new Uint8ClampedArray(data); // Work on a copy

    for (let i = 0; i < data.length; i += 4) {
        // Red channel: read from a pixel 'channelShift' to the left
        const rIndex = i - (channelShift * 4);
        if (rIndex >= 0) {
            data[i] = originalData[rIndex];
        }
        // Green channel: remains in place (no change)
        // Blue channel: read from a pixel 'channelShift' to the right
        const bIndex = i + 2 + (channelShift * 4);
        if (bIndex < originalData.length) {
            data[i + 2] = originalData[bIndex];
        }
    }
    ctx.putImageData(imageData, 0, 0);

    // Step 5: Add analog noise.
    const noiseData = ctx.getImageData(0, 0, w, h);
    const pixels = noiseData.data;
    for (let i = 0; i < pixels.length; i += 4) {
        // Add a random value to R, G, and B channels
        for (let j = 0; j < 3; j++) {
            const noise = (Math.random() - 0.5) * 255 * noiseAmount;
            pixels[i + j] = Math.max(0, Math.min(255, pixels[i + j] + noise));
        }
    }
    ctx.putImageData(noiseData, 0, 0);

    // Step 6: Emulate CRT scanlines.
    ctx.fillStyle = `rgba(0, 0, 0, ${scanlineIntensity})`;
    for (let i = 0; i < h; i += 4) { // Draw 2px dark lines with 2px gap
        ctx.fillRect(0, i, w, 2);
    }

    // Step 7: Simulate tape tracking errors (horizontal glitches).
    if (glitchIntensity > 0) {
        const numGlitches = Math.floor(glitchIntensity * (h / 30));
        for (let i = 0; i < numGlitches; i++) {
            const y = Math.random() * h;
            const glitchHeight = Math.random() * 30 + 1;
            const xOffset = (Math.random() - 0.5) * w * 0.1;

            if (y + glitchHeight > h) continue;

            // Grab a slice of the canvas and draw it back on with a horizontal offset
            ctx.drawImage(canvas,
                0, y, w, glitchHeight,
                xOffset, y, w, glitchHeight
            );
        }
    }

    // Step 8: Apply a vignette effect to darken the edges.
    const grd = ctx.createRadialGradient(w / 2, h / 2, Math.min(w, h) / 3, w / 2, h / 2, Math.max(w, h));
    grd.addColorStop(0, 'rgba(0,0,0,0)');
    grd.addColorStop(1, 'rgba(0,0,0,0.4)');
    ctx.fillStyle = grd;
    ctx.fillRect(0, 0, w, h);

    // Step 9: Add the On-Screen Display (OSD) text if provided.
    if (osdText && osdText.trim() !== "") {
        const fontSize = Math.min(w, h) * 0.04;
        ctx.font = `${fontSize}px VT323, 'Courier New', monospace`;
        ctx.fillStyle = 'rgba(255, 255, 220, 0.7)';
        ctx.textBaseline = 'top';
        ctx.textAlign = 'left';

        // Add a shadow for better contrast against the busy background
        ctx.shadowColor = 'black';
        ctx.shadowBlur = 6;
        ctx.shadowOffsetX = 2;
        ctx.shadowOffsetY = 2;

        const padding = w * 0.025;
        ctx.fillText(osdText, padding, padding);
    }

    // Step 10: Return the final canvas element.
    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 Image VHS Filter Video And Audio Converter is a tool designed to transform images into a retro VHS-style aesthetic, reminiscent of old analog video recordings. It applies a variety of effects such as chromatic aberration, analog noise, scanlines, and tape tracking glitches to create a distinctive vintage look. Users can also add custom on-screen display (OSD) text to their images. This tool is useful for adding nostalgic vibes to photos, enhancing social media posts, creating unique digital artwork, or simply exploring retro visuals.

Leave a Reply

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