Please bookmark this page to avoid losing your image tool!

Image Time Worn 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.
async function processImage(
    originalImg,
    sepiaStrength = "0.7",      // String "0.0" to "1.0" for sepia intensity
    contrastReduction = "0.1",  // String "0.0" to "0.5" for how much to reduce contrast
    noiseIntensity = "20",      // String "0" to "100" for noise amplitude
    scratchCount = "10",        // String "0" to "50" for number of scratches
    dustParticleCount = "50",   // String "0" to "200" for number of dust particles
    vignetteStrength = "0.6"    // String "0.0" to "1.0" for vignette opacity
) {
    // Parameter parsing and validation
    let pSepiaStrength = parseFloat(sepiaStrength);
    if (isNaN(pSepiaStrength) || pSepiaStrength < 0 || pSepiaStrength > 1) pSepiaStrength = 0.7;

    let pContrastReduction = parseFloat(contrastReduction);
    if (isNaN(pContrastReduction) || pContrastReduction < 0 || pContrastReduction > 0.5) pContrastReduction = 0.1;
    const contrastFactor = 1.0 - pContrastReduction;

    let pNoiseIntensity = parseInt(noiseIntensity); // Integer for +/- pixel value change
    if (isNaN(pNoiseIntensity) || pNoiseIntensity < 0 || pNoiseIntensity > 100) pNoiseIntensity = 20;

    let pScratchCount = parseInt(scratchCount);
    if (isNaN(pScratchCount) || pScratchCount < 0 || pScratchCount > 50) pScratchCount = 10;

    let pDustParticleCount = parseInt(dustParticleCount);
    if (isNaN(pDustParticleCount) || pDustParticleCount < 0 || pDustParticleCount > 200) pDustParticleCount = 50;

    let pVignetteStrength = parseFloat(vignetteStrength);
    if (isNaN(pVignetteStrength) || pVignetteStrength < 0 || pVignetteStrength > 1) pVignetteStrength = 0.6;

    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

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

    // If image is not loaded or has no dimensions, return an empty canvas
    if (w === 0 || h === 0) {
        // console.warn("Original image has zero width or height.");
        return canvas;
    }

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

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

    // 1. Apply Sepia, Contrast Reduction, and Noise (Pixel manipulation)
    for (let i = 0; i < data.length; i += 4) {
        let r = data[i];
        let g = data[i + 1];
        let b = data[i + 2];

        let finalR = r, finalG = g, finalB = b;

        // Apply Sepia
        if (pSepiaStrength > 0) {
            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;

            finalR = r * (1 - pSepiaStrength) + tr * pSepiaStrength;
            finalG = g * (1 - pSepiaStrength) + tg * pSepiaStrength;
            finalB = b * (1 - pSepiaStrength) + tb * pSepiaStrength;
        }
        
        // Apply Contrast Reduction
        if (pContrastReduction > 0 && contrastFactor !== 1.0) {
            finalR = (finalR - 127.5) * contrastFactor + 127.5;
            finalG = (finalG - 127.5) * contrastFactor + 127.5;
            finalB = (finalB - 127.5) * contrastFactor + 127.5;
        }

        // Apply Noise
        if (pNoiseIntensity > 0) {
            const noise = (Math.random() - 0.5) * pNoiseIntensity;
            finalR += noise;
            finalG += noise;
            finalB += noise;
        }

        // Clamp values to 0-255 range
        data[i] = Math.max(0, Math.min(255, finalR));
        data[i + 1] = Math.max(0, Math.min(255, finalG));
        data[i + 2] = Math.max(0, Math.min(255, finalB));
    }
    ctx.putImageData(imageData, 0, 0);

    // 2. Draw Scratches
    if (pScratchCount > 0) {
        for (let i = 0; i < pScratchCount; i++) {
            ctx.beginPath();
            const isVertical = Math.random() > 0.5;
            const scratchAlpha = Math.random() * 0.25 + 0.05; // Subtle alpha
            const grayScale = Math.random() > 0.5 ? (30 + Math.random() * 50) : (180 + Math.random() * 50); // Dark or light gray
            
            ctx.strokeStyle = `rgba(${grayScale}, ${grayScale}, ${grayScale}, ${scratchAlpha})`;
            ctx.lineWidth = Math.random() * 1.5 + 0.3; // Thin lines

            const jitterBase = Math.min(w,h) * 0.05; // Max deviation of scratch line relative to image size

            if (isVertical) {
                const x = Math.random() * w;
                const y1 = (Math.random() * 0.5 - 0.25) * h; // Start near/off top edge
                const y2 = (1 + (Math.random() * 0.5 - 0.25)) * h; // End near/off bottom edge
                const jitter1 = (Math.random() - 0.5) * jitterBase;
                const jitter2 = (Math.random() - 0.5) * jitterBase;
                ctx.moveTo(x + jitter1, y1);
                ctx.lineTo(x + jitter2, y2);
            } else { // Horizontal
                const y = Math.random() * h;
                const x1 = (Math.random() * 0.5 - 0.25) * w; // Start near/off left edge
                const x2 = (1 + (Math.random() * 0.5 - 0.25)) * w; // End near/off right edge
                const jitter1 = (Math.random() - 0.5) * jitterBase;
                const jitter2 = (Math.random() - 0.5) * jitterBase;
                ctx.moveTo(x1, y + jitter1);
                ctx.lineTo(x2, y + jitter2);
            }
            ctx.stroke();
        }
    }

    // 3. Draw Dust Particles
    if (pDustParticleCount > 0) {
        for (let i = 0; i < pDustParticleCount; i++) {
            const x = Math.random() * w;
            const y = Math.random() * h;
            const radius = Math.random() * 1.3 + 0.2; // Small specks (0.2px to 1.5px radius)
            const alpha = Math.random() * 0.5 + 0.1; // Dust opacity

            // Dust can be dark or light specks
            const speckColorVal = Math.random() > 0.4 ? Math.floor(Math.random() * 70) : Math.floor(190 + Math.random() * 65); // Dark (0-69) or light (190-254)
            ctx.fillStyle = `rgba(${speckColorVal}, ${speckColorVal}, ${speckColorVal}, ${alpha})`;
            
            ctx.beginPath();
            ctx.arc(x, y, radius, 0, Math.PI * 2);
            ctx.fill();
        }
    }

    // 4. Draw Vignette
    if (pVignetteStrength > 0) {
        const centerX = w / 2;
        const centerY = h / 2;
        const cornerDist = Math.sqrt(Math.pow(centerX, 2) + Math.pow(centerY, 2));
        
        // Inner radius of vignette clear area (stronger vignette means smaller clear area)
        // The 0.7 and 0.5 factors control how quickly the vignette starts and its minimum size
        const innerRadiusFactor = 0.7 - pVignetteStrength * 0.5;
        const innerRadius = cornerDist * Math.max(0, innerRadiusFactor); // Ensure innerRadius is not negative

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

        // Vignette color (typically black, could be dark brown for aged effect)
        const R_VIGNETTE = 20; // Dark brownish tint
        const G_VIGNETTE = 10;
        const B_VIGNETTE = 0;
        
        gradient.addColorStop(0, `rgba(${R_VIGNETTE},${G_VIGNETTE},${B_VIGNETTE},0)`);
        gradient.addColorStop(1, `rgba(${R_VIGNETTE},${G_VIGNETTE},${B_VIGNETTE},${pVignetteStrength})`);
        
        ctx.fillStyle = gradient;
        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 Image Time Worn Filter Effect Tool allows users to apply a vintage, aged look to their images. This tool can add sepia tones, reduce contrast, and introduce noise to create an effect reminiscent of old photographs. Additionally, users can simulate scratches and dust particles, contributing to the worn appearance. A vignette effect can also be applied to draw attention to the center of the image while darkening the edges. This tool is ideal for anyone looking to enhance photographs with a nostalgic feel, create unique artistic images, or add character to digital media for personal projects, presentations, or social media.

Leave a Reply

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