Please bookmark this page to avoid losing your image tool!

Image Lens Flare Effect Applicator

(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, flareXPercent = 50, flareYPercent = 50, mainColorStr = "255,255,220", overallSize = 300, starburstRays = 16, starburstRayLengthScale = 0.8, haloElements = 5, coreBrightness = 0.7, haloBaseOpacity = 0.15) {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    canvas.width = originalImg.naturalWidth;
    canvas.height = originalImg.naturalHeight;

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

    // Parse main color string
    let r = 255, g = 255, b = 220; // Default main color
    const colorParts = mainColorStr.split(',');
    if (colorParts.length === 3) {
        r = parseInt(colorParts[0].trim(), 10) || 255;
        g = parseInt(colorParts[1].trim(), 10) || 255;
        b = parseInt(colorParts[2].trim(), 10) || 220;
    }
    
    // Ensure brightness/opacity values are within [0,1]
    coreBrightness = Math.max(0, Math.min(1, coreBrightness));
    haloBaseOpacity = Math.max(0, Math.min(1, haloBaseOpacity));

    const flareX = (flareXPercent / 100) * canvas.width;
    const flareY = (flareYPercent / 100) * canvas.height;

    // Set composite mode for additive blending (light effects)
    ctx.globalCompositeOperation = 'lighter';

    // 1. Main Glare: A large, soft, circular glow
    const glareRadius = Math.max(1, overallSize * 0.6);
    const glareGradient = ctx.createRadialGradient(flareX, flareY, 0, flareX, flareY, glareRadius);
    glareGradient.addColorStop(0, `rgba(${r},${g},${b}, ${coreBrightness * 0.2})`);
    glareGradient.addColorStop(0.5, `rgba(${r},${g},${b}, ${coreBrightness * 0.1})`);
    glareGradient.addColorStop(1, `rgba(${r},${g},${b}, 0)`);
    ctx.fillStyle = glareGradient;
    ctx.beginPath();
    ctx.arc(flareX, flareY, glareRadius, 0, Math.PI * 2);
    ctx.fill();

    // 2. Central Core: Smaller, brighter, more focused glow
    const coreRadius = Math.max(1, overallSize * 0.1);
    const coreGradient = ctx.createRadialGradient(flareX, flareY, 0, flareX, flareY, coreRadius);
    coreGradient.addColorStop(0, `rgba(${r},${g},${b}, ${coreBrightness})`); // Brightest part
    coreGradient.addColorStop(0.6, `rgba(${r},${g},${b}, ${coreBrightness * 0.5})`);
    coreGradient.addColorStop(1, `rgba(${r},${g},${b}, 0)`);
    ctx.fillStyle = coreGradient;
    ctx.beginPath();
    ctx.arc(flareX, flareY, coreRadius, 0, Math.PI * 2);
    ctx.fill();

    // 3. Starburst Rays originating from the core
    const rayBaseLength = overallSize * starburstRayLengthScale;
    const raySharpnessFactor = 0.03; 

    for (let i = 0; i < starburstRays; i++) {
        const angle = (i / starburstRays) * Math.PI * 2 + (Math.random() - 0.5) * (Math.PI / starburstRays) * 0.3;
        const currentRayLength = rayBaseLength * (0.7 + Math.random() * 0.6); // Vary length

        const startRadiusN = Math.max(1, coreRadius * 0.5); // Rays start slightly out from exact center
        const endRadiusN = startRadiusN + currentRayLength;

        const tipX = flareX + Math.cos(angle) * endRadiusN;
        const tipY = flareY + Math.sin(angle) * endRadiusN;

        const perpAngle = angle + Math.PI / 2;
        const baseHalfWidth = currentRayLength * raySharpnessFactor * (Math.random() * 0.5 + 0.75);

        const x1 = flareX + Math.cos(angle) * startRadiusN + Math.cos(perpAngle) * baseHalfWidth;
        const y1 = flareY + Math.sin(angle) * startRadiusN + Math.sin(perpAngle) * baseHalfWidth;
        const x2 = flareX + Math.cos(angle) * startRadiusN - Math.cos(perpAngle) * baseHalfWidth;
        const y2 = flareY + Math.sin(angle) * startRadiusN - Math.sin(perpAngle) * baseHalfWidth;
        
        ctx.beginPath();
        ctx.moveTo(tipX, tipY);
        ctx.lineTo(x1, y1);
        ctx.lineTo(x2, y2);
        ctx.closePath();

        const rayGradient = ctx.createLinearGradient(flareX, flareY, tipX, tipY);
        const rayAlpha = coreBrightness * (0.25 + Math.random() * 0.25);
        rayGradient.addColorStop(0, `rgba(${r},${g},${b}, ${rayAlpha})`);
        rayGradient.addColorStop(0.6, `rgba(${r},${g},${b}, ${rayAlpha * 0.7})`);
        rayGradient.addColorStop(1, `rgba(${r},${g},${b}, 0)`);
        ctx.fillStyle = rayGradient;
        ctx.fill();
    }

    // 4. Halo Elements (Ghosts/Secondary Flares)
    const baseGhostColors = [
        `rgba(220, 50, 50, ${haloBaseOpacity})`, // Reddish
        `rgba(50, 200, 50, ${haloBaseOpacity})`, // Greenish
        `rgba(80, 80, 230, ${haloBaseOpacity})`, // Bluish
        `rgba(${r}, ${g}, ${b}, ${haloBaseOpacity * 1.1})`, // Main flare color
        `rgba(${Math.min(255, r+30)}, ${Math.min(255,g+10)}, ${Math.max(0,b-30)}, ${haloBaseOpacity * 0.9})` // Warmer tone
    ];

    const centerX = canvas.width / 2;
    const centerY = canvas.height / 2;
    const vecFlareToCenterX = centerX - flareX; // Vector from flare to center
    const vecFlareToCenterY = centerY - flareY;

    for (let i = 0; i < haloElements; i++) {
        // k determines position along the line connecting flare and image center.
        // k=0: at flare. k=1: at image center. k=2: at reflection of flare through center.
        // Distribute ghosts along this line including random variations.
        const kBase = (i / Math.max(1, haloElements - 1)) * 1.8; // Spread up to nearly reflection point
        const k = kBase + (Math.random() * 0.8 - 0.4); // Add jitter and spread. Range around -0.4 to 2.2

        let ghostX, ghostY;
        // If flare is at image center, distribute ghosts radially
        if (Math.abs(vecFlareToCenterX) < 1 && Math.abs(vecFlareToCenterY) < 1) {
            const randomAngle = Math.random() * Math.PI * 2;
            const randomDist = (i + 1) * overallSize * 0.12 * (Math.random() * 0.4 + 0.8);
            ghostX = flareX + Math.cos(randomAngle) * randomDist;
            ghostY = flareY + Math.sin(randomAngle) * randomDist;
        } else {
            ghostX = flareX + vecFlareToCenterX * k;
            ghostY = flareY + vecFlareToCenterY * k;
        }
        
        const ghostRadius = Math.max(1, overallSize * (0.02 + Math.random() * 0.10));
        const selectedColorStr = baseGhostColors[i % baseGhostColors.length];
        
        const colorMatch = selectedColorStr.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);
        if (!colorMatch) continue;

        const rC = colorMatch[1];
        const gC = colorMatch[2];
        const bC = colorMatch[3];
        const aC = parseFloat(colorMatch[4] !== undefined ? colorMatch[4] : '1.0');

        const ghostGradient = ctx.createRadialGradient(ghostX, ghostY, 0, ghostX, ghostY, ghostRadius);
        ghostGradient.addColorStop(0, `rgba(${rC},${gC},${bC}, ${aC * 0.7})`);
        ghostGradient.addColorStop(0.5, `rgba(${rC},${gC},${bC}, ${aC * 0.4})`);
        ghostGradient.addColorStop(1, `rgba(${rC},${gC},${bC}, 0)`);
        ctx.fillStyle = ghostGradient;

        ctx.beginPath();
        ctx.arc(ghostX, ghostY, ghostRadius, 0, Math.PI * 2);
        ctx.fill();

        // Optional: add a thin, brighter ring to some ghosts
        if (Math.random() < 0.35) {
            ctx.beginPath();
            ctx.arc(ghostX, ghostY, ghostRadius * (0.7 + Math.random() * 0.2), 0, Math.PI * 2);
            ctx.strokeStyle = `rgba(${rC},${gC},${bC}, ${aC * 0.9 * (Math.random() * 0.4 + 0.6)})`;
            ctx.lineWidth = Math.max(1, ghostRadius * 0.08 * (Math.random() * 0.6 + 0.7));
            ctx.stroke();
        }
    }

    // Reset composite mode to default
    ctx.globalCompositeOperation = 'source-over';

    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 Lens Flare Effect Applicator is a versatile online tool designed to add stunning lens flare effects to your images. By allowing users to customize various parameters such as the position of the flare, its size, color, and intensity, this tool enhances the visual appeal of photos with realistic light effects, including glare, starburst rays, and soft halos. It can be particularly useful for graphic designers, photographers, and content creators looking to elevate their images for artistic or promotional purposes. Whether enhancing a landscape photograph, creating dramatic lighting for portraits, or designing engaging graphics for social media, this tool provides an easy and effective way to apply dynamic lens flare effects.

Leave a Reply

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