Please bookmark this page to avoid losing your image tool!

Photo Old Filter Application

(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, sepiaStrength = 0.7, noiseStrength = 0.05, desaturation = 0.2, vignetteIntensity = 0.3) {
    const canvas = document.createElement('canvas');
    // Using { willReadFrequently: true } can be a performance hint for browsers
    const ctx = canvas.getContext('2d', { willReadFrequently: true });

    const w = originalImg.naturalWidth || originalImg.width;
    const h = originalImg.naturalHeight || originalImg.height;
    canvas.width = w;
    canvas.height = h;

    if (w === 0 || h === 0) {
        // If image dimensions are zero (e.g., not loaded or invalid image),
        // return an empty canvas to prevent errors.
        console.warn("Image has zero width or height. Returning an empty canvas.");
        return canvas;
    }

    ctx.drawImage(originalImg, 0, 0, w, h);

    const imageData = ctx.getImageData(0, 0, w, h);
    const data = imageData.data;
    const len = data.length;

    // Max noise deviation: e.g. if noiseStrength is 1, noise can shift a channel by +/-32
    // Default (0.05) means +/- 1.6, a very subtle noise.
    const noisePixelShift = noiseStrength * 32; 

    for (let i = 0; i < len; i += 4) {
        let r = data[i];
        let g = data[i + 1];
        let b = data[i + 2];
        // Alpha channel data[i+3] is preserved by default

        // 1. Desaturation
        // Desaturation = 0 means original color, Desaturation = 1 means grayscale.
        if (desaturation > 0) {
            const gray = 0.299 * r + 0.587 * g + 0.114 * b; // Standard luminance calculation
            r = r * (1 - desaturation) + gray * desaturation;
            g = g * (1 - desaturation) + gray * desaturation;
            b = b * (1 - desaturation) + gray * desaturation;
        }

        // 2. Sepia Tone
        // sepiaStrength = 0 means no sepia, sepiaStrength = 1 means full sepia.
        if (sepiaStrength > 0) {
            // Standard sepia matrix values
            const sr = (r * 0.393) + (g * 0.769) + (b * 0.189);
            const sg = (r * 0.349) + (g * 0.686) + (b * 0.168);
            const sb = (r * 0.272) + (g * 0.534) + (b * 0.131);

            r = r * (1 - sepiaStrength) + sr * sepiaStrength;
            g = g * (1 - sepiaStrength) + sg * sepiaStrength;
            b = b * (1 - sepiaStrength) + sb * sepiaStrength;
        }
        
        // 3. Noise
        // Adds monochromatic noise.
        if (noisePixelShift > 0) {
            const randomNoise = (Math.random() - 0.5) * noisePixelShift;
            r += randomNoise;
            g += randomNoise;
            b += randomNoise;
        }

        // Clamp values to the 0-255 range for each channel
        data[i] = Math.max(0, Math.min(255, r));
        data[i + 1] = Math.max(0, Math.min(255, g));
        data[i + 2] = Math.max(0, Math.min(255, b));
    }

    ctx.putImageData(imageData, 0, 0);

    // 4. Vignette Effect
    // Clamp vignetteIntensity to a practical [0, 1] range.
    const effectiveVignetteIntensity = Math.max(0, Math.min(1, vignetteIntensity));

    if (effectiveVignetteIntensity > 0) {
        ctx.save(); // Save current canvas state
        const centerX = w / 2;
        const centerY = h / 2;
        
        // Spread Factor: Controls how far the transparent center of the vignette extends.
        // Ranges from ~0.1 (for intensity 1, small center) to ~0.9 (for intensity 0, large center).
        const spreadFactor = 0.1 + (1 - effectiveVignetteIntensity) * 0.8; 

        // Define the inner and outer radii for the radial gradient.
        // Inner radius is based on the smaller dimension of the image and the spread factor.
        const innerRadius = (Math.min(w, h) / 2) * spreadFactor;
        // Outer radius extends to the corners of the image.
        const outerRadius = Math.sqrt(centerX * centerX + centerY * centerY);

        const gradient = ctx.createRadialGradient(
            centerX, centerY, innerRadius,
            centerX, centerY, outerRadius
        );

        // Edge Opacity: Controls darkness of the vignette at the edges.
        // Max opacity of ~0.8 for black at full intensity to avoid pure black.
        const edgeOpacity = effectiveVignetteIntensity * 0.8; 

        gradient.addColorStop(0, "rgba(0,0,0,0)");       // Transparent black at the inner radius
        gradient.addColorStop(1, `rgba(0,0,0,${edgeOpacity})`); // Semi-transparent black at the outer radius

        ctx.globalCompositeOperation = 'source-over'; // Draw new shapes on top of existing content
        ctx.fillStyle = gradient;
        ctx.fillRect(0, 0, w, h); // Apply the gradient over the entire canvas
        ctx.restore(); // Restore canvas state
    }
    
    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

Photo Old Filter Application is a web-based tool that allows users to apply vintage photo effects to their images. Users can adjust the strength of sepia toning, add noise for a grainy texture, desaturate colors for a faded look, and create vignette effects to enhance the nostalgic feel of photographs. This tool is ideal for anyone looking to give their photos an artistic, retro aesthetic, whether for personal projects, social media sharing, or creative design.

Leave a Reply

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