Please bookmark this page to avoid losing your image tool!

Image Coffee Stain Filter Effect

(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, sepiaIntensity = 0.8, stainOpacity = 0.6, splotchCount = 3, noiseAmount = 20) {
    const canvas = document.createElement('canvas');
    const width = originalImg.naturalWidth;
    const height = originalImg.naturalHeight;

    if (width === 0 || height === 0) {
        // Handle cases where image might not be loaded or is invalid
        console.error("Original image has zero width or height. Is it loaded properly?");
        canvas.width = 1; // Return a 1x1 canvas to avoid errors downstream
        canvas.height = 1;
        return canvas;
    }

    canvas.width = width;
    canvas.height = height;
    const ctx = canvas.getContext('2d');

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

    // 2. Apply Sepia Tone (if intensity > 0)
    if (sepiaIntensity > 0 && sepiaIntensity <= 1.0) {
        const imageData = ctx.getImageData(0, 0, width, height);
        const data = imageData.data;
        for (let i = 0; i < data.length; i += 4) {
            const r = data[i];
            const g = data[i + 1];
            const b = data[i + 2];

            // Standard sepia calculation
            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;

            // Blend original with sepia based on intensity
            data[i] = (1 - sepiaIntensity) * r + sepiaIntensity * Math.min(255, tr);
            data[i + 1] = (1 - sepiaIntensity) * g + sepiaIntensity * Math.min(255, tg);
            data[i + 2] = (1 - sepiaIntensity) * b + sepiaIntensity * Math.min(255, tb);
        }
        ctx.putImageData(imageData, 0, 0);
    }

    // 3. Add Coffee Stain Splotches
    if (splotchCount > 0 && stainOpacity > 0 && stainOpacity <= 1.0) {
        // 'multiply' blending mode darkens the image where the stain is applied,
        // simulating absorption of coffee into paper.
        ctx.globalCompositeOperation = 'multiply';

        const baseStainColorR = 101; // A typical coffee brown (RGB: 101, 67, 33)
        const baseStainColorG = 67;
        const baseStainColorB = 33;

        for (let i = 0; i < splotchCount; i++) {
            const maxDim = Math.max(width, height);
            // Stain radius: 10% to 30% of the larger image dimension
            const radius = (Math.random() * 0.2 + 0.1) * maxDim; 
            const x = Math.random() * width;
            const y = Math.random() * height;

            // Create a radial gradient for the stain.
            // Coffee stains often have a darker ring and a lighter center.
            const gradient = ctx.createRadialGradient(x, y, radius * 0.2, x, y, radius);
            
            // Alpha values are scaled by stainOpacity.
            // Center of the stain (more transparent)
            gradient.addColorStop(0, `rgba(${baseStainColorR}, ${baseStainColorG}, ${baseStainColorB}, ${0.15 * stainOpacity})`);
            // Main body/ring of the stain (darker, more opaque)
            gradient.addColorStop(0.6 + Math.random() * 0.2, `rgba(${baseStainColorR}, ${baseStainColorG}, ${baseStainColorB}, ${0.4 * stainOpacity})`);
            // Outer edge of the stain (fades out)
            gradient.addColorStop(1, `rgba(${baseStainColorR}, ${baseStainColorG}, ${baseStainColorB}, ${0.05 * stainOpacity})`);

            ctx.beginPath();
            // Draw a slightly irregular circle for the stain shape using lineTo
            const numJaggedPoints = 15 + Math.floor(Math.random() * 10); // 15-24 points
            const angleStepJagged = (Math.PI * 2) / numJaggedPoints;
            // How much radius can vary for jaggedness (e.g., up to 40% of base radius)
            const radiusJaggedVariance = 0.4; 

            for (let k = 0; k < numJaggedPoints; k++) {
                // Add random offset to angle for more irregularity
                const currentAngle = angleStepJagged * k + (Math.random() - 0.5) * angleStepJagged * 0.4;
                // Vary radius for each point
                const currentRadius = radius * (1 - Math.random() * radiusJaggedVariance);
                
                const pointX = x + Math.cos(currentAngle) * currentRadius;
                const pointY = y + Math.sin(currentAngle) * currentRadius;

                if (k === 0) {
                    ctx.moveTo(pointX, pointY);
                } else {
                    ctx.lineTo(pointX, pointY);
                }
            }
            ctx.closePath(); 
            ctx.fillStyle = gradient;
            ctx.fill();
        }
        // Reset composite operation to default for subsequent drawing operations (like noise)
        ctx.globalCompositeOperation = 'source-over';
    }

    // 4. Add Noise
    if (noiseAmount > 0) {
        const imageData = ctx.getImageData(0, 0, width, height);
        const pixels = imageData.data;
        const noiseStrength = Math.max(0, Math.min(noiseAmount, 100)); // Clamp noise amount

        for (let i = 0; i < pixels.length; i += 4) {
            // Add random noise to R, G, B channels. Alpha (pixels[i+3]) is unchanged.
            const randomFactor = (Math.random() - 0.5) * noiseStrength;
            pixels[i]   = Math.max(0, Math.min(255, pixels[i]   + randomFactor));
            pixels[i+1] = Math.max(0, Math.min(255, pixels[i+1] + randomFactor));
            pixels[i+2] = Math.max(0, Math.min(255, pixels[i+2] + randomFactor));
        }
        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 Coffee Stain Filter Effect tool allows users to apply a vintage coffee stain effect to their images. By adjusting parameters such as sepia intensity, stain opacity, splotch count, and noise amount, users can create customized effects that add a warm, aged appearance to their photos. This tool is ideal for artists, designers, and anyone looking to enhance their images with a nostalgic, textured look, suitable for personal projects, social media posts, or creative presentations.

Leave a Reply

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