Please bookmark this page to avoid losing your image tool!

Image Cathedral Light 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, effectStrength = 0.6, glowLevel = 0.5, tintColorStr = "255,230,200,0.15", lightSourceX = 0.5, lightSourceY = 0.2) {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    // Ensure originalImg is fully loaded, though typically it should be when passed.
    // Using naturalWidth/Height for intrinsic dimensions of the image.
    const w = originalImg.naturalWidth;
    const h = originalImg.naturalHeight;
    canvas.width = w;
    canvas.height = h;

    // 0. Parse tint color string "R,G,B,A"
    const [tintR, tintG, tintB, tintA] = tintColorStr.split(',').map(s => parseFloat(s.trim()));

    // 1. Draw original image to main canvas as the base
    ctx.drawImage(originalImg, 0, 0, w, h);

    // 2. Glow Layer for highlights
    // Only apply if glowLevel is significant
    if (glowLevel > 0.01) {
        // Create a temporary canvas to get pixel data from the original image without modifications
        const highlightSourceCanvas = document.createElement('canvas');
        highlightSourceCanvas.width = w;
        highlightSourceCanvas.height = h;
        const highlightSourceCtx = highlightSourceCanvas.getContext('2d');
        highlightSourceCtx.drawImage(originalImg, 0, 0, w, h);
        const imageData = highlightSourceCtx.getImageData(0, 0, w, h);
        const data = imageData.data;

        // Create the highlight mask: bright areas become opaque, others transparent
        // Adjust threshold: higher glowLevel means lower threshold (more areas glow)
        const thresholdLuminance = 200 - glowLevel * 120; 
        for (let i = 0; i < data.length; i += 4) {
            const r = data[i];
            const g = data[i+1];
            const b = data[i+2];
            const luminance = 0.299 * r + 0.587 * g + 0.114 * b;

            if (luminance > thresholdLuminance) {
                // Make highlights brighter and slightly warmer for the glow source
                data[i]   = Math.min(255, r + 70 * glowLevel);
                data[i+1] = Math.min(255, g + 60 * glowLevel);
                data[i+2] = Math.min(255, b + 50 * glowLevel);
                data[i+3] = 255; // Fully opaque for glow source
            } else {
                data[i+3] = 0;   // Transparent for non-highlight areas
            }
        }
        
        // Canvas to hold the sharp (unblurred) highlight mask
        const sharpGlowCanvas = document.createElement('canvas');
        sharpGlowCanvas.width = w;
        sharpGlowCanvas.height = h;
        const sharpGlowCtx = sharpGlowCanvas.getContext('2d');
        sharpGlowCtx.putImageData(imageData, 0, 0);

        // Canvas for the blurred glow effect
        const blurredGlowCanvas = document.createElement('canvas');
        blurredGlowCanvas.width = w;
        blurredGlowCanvas.height = h;
        const blurredGlowCtx = blurredGlowCanvas.getContext('2d');
        
        // Blur radius scales with glowLevel
        const blurRadius = Math.max(1, 3 + glowLevel * 22); // Min 3px blur, up to 25px
        blurredGlowCtx.filter = `blur(${blurRadius}px)`;
        blurredGlowCtx.drawImage(sharpGlowCanvas, 0, 0, w, h); // Draw sharp mask, filter applies blur
        blurredGlowCtx.filter = 'none'; // Reset filter on this context

        // Blend the blurred glow onto the main canvas
        // Glow opacity scales with glowLevel
        ctx.globalAlpha = Math.min(1, 0.3 + glowLevel * 0.7); 
        ctx.globalCompositeOperation = 'lighter'; // 'screen' or 'lighter' are good for glows
        ctx.drawImage(blurredGlowCanvas, 0, 0);
        
        // Reset global alpha and composite operation
        ctx.globalAlpha = 1.0;
        ctx.globalCompositeOperation = 'source-over';
    }

    // 3. Simulated Radial Light Source
    // Only apply if effectStrength is significant
    if (effectStrength > 0.01) {
        const focusPxX = lightSourceX * w;
        const focusPxY = lightSourceY * h;
        const maxDim = Math.max(w, h);
        // Gradient radius scales with image size and effect strength
        const gradientRadius = maxDim * (0.35 + effectStrength * 0.5); 
        
        const gradient = ctx.createRadialGradient(focusPxX, focusPxY, 0, focusPxX, focusPxY, gradientRadius);
        
        // Opacity of the light's center scales with effectStrength
        const centerAlpha = Math.min(1, 0.1 + 0.5 * effectStrength); 
        gradient.addColorStop(0,    `rgba(255, 255, 240, ${centerAlpha})`);       // Bright, slightly warm center
        gradient.addColorStop(0.25, `rgba(255, 250, 230, ${centerAlpha * 0.7})`);
        gradient.addColorStop(0.5,  `rgba(255, 245, 220, ${centerAlpha * 0.3})`);
        gradient.addColorStop(1,    `rgba(255, 255, 255, 0)`);                   // Fades to transparent

        ctx.globalCompositeOperation = 'soft-light'; // 'overlay' or 'color-dodge' could also work
        ctx.fillStyle = gradient;
        ctx.fillRect(0, 0, w, h);
        ctx.globalCompositeOperation = 'source-over'; // Reset
    }

    // 4. Global Color Tint
    // Apply if tint has alpha and effectStrength is significant
    if (tintA > 0 && effectStrength > 0.01) {
        ctx.globalCompositeOperation = 'overlay'; // 'soft-light' or 'color' could work well too
        // Tint's final alpha scales with its provided alpha and effectStrength
        const currentTintAlpha = Math.min(1, tintA * (0.2 + effectStrength * 0.8));
        ctx.fillStyle = `rgba(${tintR}, ${tintG}, ${tintB}, ${currentTintAlpha})`;
        ctx.fillRect(0, 0, w, h);
        ctx.globalCompositeOperation = 'source-over'; // Reset
    }

    // 5. Final Overall Adjustments (Brightness, Contrast, Saturation)
    // Apply if effectStrength is significant
    if (effectStrength > 0.01) {
        // Create a temporary canvas to hold the current state of the main canvas
        const finalAdjustCanvas = document.createElement('canvas');
        finalAdjustCanvas.width = w;
        finalAdjustCanvas.height = h;
        const finalAdjustCtx = finalAdjustCanvas.getContext('2d');
        finalAdjustCtx.drawImage(canvas, 0, 0); // Copy current result from main canvas

        ctx.clearRect(0, 0, w, h); // Clear main canvas before drawing the filtered version

        // Adjustments scale with effectStrength
        const brightnessValue = 1 + 0.15 * effectStrength; // Range: 1.0 to 1.15
        const contrastValue = 1 + 0.15 * effectStrength;   // Range: 1.0 to 1.15
        // Desaturation increases with effectStrength
        const saturationValue = Math.max(0, 1 - 0.4 * effectStrength); // Range: 1.0 to 0.6 
        
        ctx.filter = `brightness(${brightnessValue}) contrast(${contrastValue}) saturate(${saturationValue})`;
        ctx.drawImage(finalAdjustCanvas, 0, 0); // Draw the copied image with filter applied
        ctx.filter = 'none'; // Reset filter on the main context
    }
    
    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 Cathedral Light Filter Effect Tool allows users to apply a unique light filter effect to images, creating a soft, glowing ambiance reminiscent of cathedral light filtering through stained glass. This tool enables users to adjust the strength of the light effect, the glow intensity, and the color tint, offering customizable options for artistic enhancements. It can be useful for photographers, graphic designers, and social media enthusiasts looking to enhance the mood of their images, create stunning visual effects for storytelling, or prepare images for artistic projects.

Leave a Reply

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