Please bookmark this page to avoid losing your image tool!

Image Aged Photograph Filter Effect 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, sepiaIntensityArg = 1.0, noiseAmountArg = 25, vignetteStrengthArg = 0.7, desaturationLevelArg = 0.2) {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    // Ensure originalImg is a valid Image object with positive dimensions
    if (!originalImg || 
        typeof originalImg.width !== 'number' || 
        typeof originalImg.height !== 'number' || 
        originalImg.width <= 0 || 
        originalImg.height <= 0) {
        // If image is invalid or has no dimensions, return an empty (0x0) canvas.
        // The caller can decide how to handle this (e.g., display an error message).
        canvas.width = 0;
        canvas.height = 0;
        return canvas;
    }
    
    canvas.width = originalImg.naturalWidth || originalImg.width; // Prefer naturalWidth for full res
    canvas.height = originalImg.naturalHeight || originalImg.height; // Prefer naturalHeight for full res


    // Parameter parsing and validation with fallbacks to default values from signature
    // The default values are set in the function signature.
    // This section handles cases where non-numeric strings might be passed.
    const defaultSepiaIntensity = 1.0;
    const defaultNoiseAmount = 25;
    const defaultVignetteStrength = 0.7;
    const defaultDesaturationLevel = 0.2;

    let sepiaIntensity = parseFloat(sepiaIntensityArg);
    if (isNaN(sepiaIntensity)) sepiaIntensity = defaultSepiaIntensity;
    sepiaIntensity = Math.max(0.0, Math.min(1.0, sepiaIntensity));

    let noiseAmount = parseFloat(noiseAmountArg);
    if (isNaN(noiseAmount)) noiseAmount = defaultNoiseAmount;
    noiseAmount = Math.max(0, noiseAmount); // No specific upper bound, but practically > 100 is extreme

    let vignetteStrength = parseFloat(vignetteStrengthArg);
    if (isNaN(vignetteStrength)) vignetteStrength = defaultVignetteStrength;
    vignetteStrength = Math.max(0.0, Math.min(1.0, vignetteStrength));

    let desaturationLevel = parseFloat(desaturationLevelArg);
    if (isNaN(desaturationLevel)) desaturationLevel = defaultDesaturationLevel;
    desaturationLevel = Math.max(0.0, Math.min(1.0, desaturationLevel));

    // Draw the original image onto the canvas
    ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);

    // Get the pixel data from the canvas
    const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    const data = imageData.data;
    const width = canvas.width;
    const height = canvas.height;
    
    // Pre-calculate for vignette
    const centerX = width / 2;
    const centerY = height / 2;
    // maxDist will be > 0 because width & height are validated to be > 0.
    const maxDist = Math.sqrt(centerX * centerX + centerY * centerY); 

    // Iterate over each pixel (RGBA)
    for (let i = 0; i < data.length; i += 4) {
        let r = data[i];
        let g = data[i+1];
        let b = data[i+2];

        // 1. Apply Desaturation
        if (desaturationLevel > 0) {
            // Standard luminance-based grayscale conversion
            const gray = r * 0.299 + g * 0.587 + b * 0.114; 
            // Interpolate between original color and gray
            r = r * (1 - desaturationLevel) + gray * desaturationLevel;
            g = g * (1 - desaturationLevel) + gray * desaturationLevel;
            b = b * (1 - desaturationLevel) + gray * desaturationLevel;
        }

        // 2. Apply Sepia Tone
        if (sepiaIntensity > 0) {
            // Standard sepia formula coefficients
            // tr, tg, tb are the target sepia values for the current r, g, b
            const tr = 0.393 * r + 0.769 * g + 0.189 * b;
            const tg = 0.349 * r + 0.686 * g + 0.168 * b;
            const tb = 0.272 * r + 0.534 * g + 0.131 * b;
            
            // Interpolate between current color and full sepia color
            r = r * (1 - sepiaIntensity) + tr * sepiaIntensity;
            g = g * (1 - sepiaIntensity) + tg * sepiaIntensity;
            b = b * (1 - sepiaIntensity) + tb * sepiaIntensity;
        }

        // 3. Add Noise/Grain
        if (noiseAmount > 0) {
            // Generate random noise value (centered around 0)
            const noise = (Math.random() - 0.5) * noiseAmount;
            r += noise;
            g += noise;
            b += noise;
        }

        // 4. Apply Vignette Effect
        if (vignetteStrength > 0) {
            const pixelX = (i / 4) % width; // Current pixel's X coordinate
            const pixelY = Math.floor((i / 4) / width); // Current pixel's Y coordinate
            
            // Distance of the pixel from the center
            const distX = pixelX - centerX;
            const distY = pixelY - centerY;
            const distance = Math.sqrt(distX * distX + distY * distY);
            
            // Normalized distance (0 at center, 1 at corners/farthest points)
            // maxDist cannot be 0 here due to prior width/height checks
            const normalizedDistance = distance / maxDist; 
            
            // Calculate darkening factor based on distance and strength
            // Using a quadratic falloff for a smooth vignette
            const reduction = (normalizedDistance * normalizedDistance) * vignetteStrength;
            const darkenFactor = Math.max(0, 1.0 - reduction); 
            
            r *= darkenFactor;
            g *= darkenFactor;
            b *= darkenFactor;
        }

        // Clamp final Red, Green, Blue values to the 0-255 range
        data[i]   = Math.min(255, Math.max(0, r));
        data[i+1] = Math.min(255, Math.max(0, g));
        data[i+2] = Math.min(255, Math.max(0, b));
        // Alpha channel (data[i+3]) is preserved
    }

    // Put the modified pixel data back onto the canvas
    ctx.putImageData(imageData, 0, 0);
    
    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 Aged Photograph Filter Effect Tool allows users to apply a vintage or aged look to their images. This includes effects such as sepia toning, noise addition for a grainy texture, vignette darkening around the edges, and color desaturation. It’s perfect for users looking to enhance their photos with a nostalgic aesthetic, ideal for creating artistic images for social media, personal projects, or enhancing old family photos.

Leave a Reply

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