Please bookmark this page to avoid losing your image tool!

16mm Film Style Photo Filter

(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 = "60", addGrain = "yes", addVignette = "yes", colorTone = "warm") {
    // Parse parameters
    const intVal = Math.max(0, Math.min(100, Number(intensity))) / 100; // Normalizes 0-100 to 0.0-1.0
    const applyGrain = String(addGrain).toLowerCase() === "yes" || String(addGrain) === "true" || String(addGrain) === "1";
    const applyVignette = String(addVignette).toLowerCase() === "yes" || String(addVignette) === "true" || String(addVignette) === "1";
    
    const canvas = document.createElement('canvas');
    const w = canvas.width = originalImg.width;
    const h = canvas.height = originalImg.height;
    const ctx = canvas.getContext('2d');

    // 1. Base 16mm Softness and Image Filtering
    // 16mm film has intrinsic softness, slightly faded saturation, and warm/aged contrast
    const blurRadius = Math.min(3, Math.max(0.3, (w / 1500))) * intVal;
    const contrast = 100 + (15 * intVal); // Boost contrast slightly (100% to 115%)
    const sepia = 20 * intVal;            // Up to 20% sepia
    const saturate = 100 - (15 * intVal); // Desaturate slightly (100% to 85%)

    ctx.filter = `blur(${blurRadius}px) contrast(${contrast}%) sepia(${sepia}%) saturate(${saturate}%)`;
    ctx.drawImage(originalImg, 0, 0);
    ctx.filter = 'none'; // Reset filter for subsequent operations

    // 2. Cinematic Split Toning (Faded film emulation)
    // Screen dark teal/green to lift shadows and simulate film base
    ctx.globalCompositeOperation = 'screen';
    ctx.fillStyle = `rgba(15, 25, 20, ${0.4 * intVal})`;
    ctx.fillRect(0, 0, w, h);

    // Multiply to set the overall tone and bring down highlights smoothly
    ctx.globalCompositeOperation = 'multiply';
    let mR = 255, mG = 255, mB = 255;
    const tone = String(colorTone).toLowerCase();
    
    if (tone === "warm") {
        mG = Math.floor(255 - (15 * intVal)); // Slightly less green
        mB = Math.floor(255 - (35 * intVal)); // Much less blue => warm yellow/orange
    } else if (tone === "cool") {
        mR = Math.floor(255 - (30 * intVal)); // Less red
        mG = Math.floor(255 - (10 * intVal)); // Less green => cool teal/cyan
    } else {
        // Neutral fade
        mR = Math.floor(255 - (10 * intVal));
        mG = Math.floor(255 - (10 * intVal));
        mB = Math.floor(255 - (10 * intVal));
    }
    
    ctx.fillStyle = `rgb(${mR}, ${mG}, ${mB})`;
    ctx.fillRect(0, 0, w, h);

    // 3. High Contour Softness (Midtone pop)
    ctx.globalCompositeOperation = 'overlay';
    ctx.fillStyle = `rgba(128, 128, 128, ${0.15 * intVal})`;
    ctx.fillRect(0, 0, w, h);

    // 4. Optical Vignette (Classic lens light falloff)
    if (applyVignette) {
        ctx.globalCompositeOperation = 'multiply';
        const cx = w / 2;
        const cy = h / 2;
        const radius = Math.sqrt(cx * cx + cy * cy);
        
        const gradient = ctx.createRadialGradient(cx, cy, radius * 0.4, cx, cy, radius);
        gradient.addColorStop(0, 'rgba(0,0,0,0)');
        // Edge darkness intensifies with effect strength
        gradient.addColorStop(1, `rgba(0,0,0,${0.65 * intVal})`);
        
        ctx.fillStyle = gradient;
        ctx.fillRect(0, 0, w, h);
    }

    // 5. 16mm Film Grain Emulation
    if (applyGrain) {
        // Create an offscreen canvas for noise to avoid slow pixel-by-pixel operations on a massive image
        const tileSize = 512;
        const noiseCanvas = document.createElement('canvas');
        noiseCanvas.width = tileSize;
        noiseCanvas.height = tileSize;
        const nCtx = noiseCanvas.getContext('2d');
        const nData = nCtx.createImageData(tileSize, tileSize);
        const dataArr = nData.data;
        
        // 16mm grain is relatively coarse
        const grainIntensity = 45 * intVal; 
        
        for (let i = 0; i < dataArr.length; i += 4) {
            // Generate neutral monochromatic noise centered around 128 (Neutral Gray)
            const noise = (Math.random() - 0.5) * grainIntensity + 128;
            dataArr[i]     = noise; // R
            dataArr[i + 1] = noise; // G
            dataArr[i + 2] = noise; // B
            dataArr[i + 3] = 255;   // A
        }
        nCtx.putImageData(nData, 0, 0);

        // Overlay the generated noise seamlessly
        ctx.globalCompositeOperation = 'overlay';
        ctx.fillStyle = ctx.createPattern(noiseCanvas, 'repeat');
        
        // Slightly lower opacity of grain to keep it organic looking
        ctx.globalAlpha = 0.85; 
        ctx.fillRect(0, 0, w, h);
        
        // Reset Alpha
        ctx.globalAlpha = 1.0; 
    }

    // Reset composite mode safely before returning
    ctx.globalCompositeOperation = 'source-over';

    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

This tool applies a cinematic 16mm film aesthetic to your photos. It emulates the classic look of vintage film by adjusting softness, contrast, and saturation, and offers customizable features such as film grain, optical vignetting, and split toning. Users can choose between different color profiles, like warm or cool tones, to achieve a specific nostalgic mood. This tool is ideal for photographers and content creators looking to give their digital images a retro, analog, or cinematic feel for social media, creative projects, or artistic storytelling.

Leave a Reply

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