Please bookmark this page to avoid losing your image tool!

Image Kirlian Photography 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, glowColorStr = "100,100,255", glowStrength = 0.8, blurAmount = 10, edgeThreshold = 30) {
    // 1. Parse glowColorStr and set up glow color components
    let r_glow = 100, g_glow = 100, b_glow = 255; // Default glow color (light bluish-purple)
    
    // Validate and parse glowColorStr
    if (typeof glowColorStr === 'string') {
        const colorParts = glowColorStr.split(',');
        if (colorParts.length === 3) {
            const parsedR = parseInt(colorParts[0].trim(), 10);
            const parsedG = parseInt(colorParts[1].trim(), 10);
            const parsedB = parseInt(colorParts[2].trim(), 10);
            if (!isNaN(parsedR) && !isNaN(parsedG) && !isNaN(parsedB)) {
                r_glow = Math.max(0, Math.min(255, parsedR));
                g_glow = Math.max(0, Math.min(255, parsedG));
                b_glow = Math.max(0, Math.min(255, parsedB));
            } else {
                console.warn(`Invalid numbers in glowColorStr: "${glowColorStr}". Using default color [${r_glow},${g_glow},${b_glow}].`);
            }
        } else {
            console.warn(`Invalid format for glowColorStr: "${glowColorStr}". Expected "R,G,B" string. Using default color [${r_glow},${g_glow},${b_glow}].`);
        }
    } else {
        console.warn(`glowColorStr is not a string: "${glowColorStr}". Using default color [${r_glow},${g_glow},${b_glow}].`);
    }


    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    const width = originalImg.naturalWidth || originalImg.width;
    const height = originalImg.naturalHeight || originalImg.height;

    if (width === 0 || height === 0) {
        // Handle invalid image dimensions by returning a minimal canvas
        console.warn("Image has zero width or height.");
        canvas.width = 1; 
        canvas.height = 1;
        return canvas;
    }
    
    canvas.width = width;
    canvas.height = height;

    // Create a temporary canvas for edge detection processing
    const tempCanvas = document.createElement('canvas');
    tempCanvas.width = width;
    tempCanvas.height = height;
    // Add { willReadFrequently: true } if frequent getImageData/putImageData operations are expected
    const tempCtx = tempCanvas.getContext('2d', { willReadFrequently: true }); 

    // Draw original image on temp canvas
    tempCtx.drawImage(originalImg, 0, 0, width, height);

    // Get image data for edge detection
    let imageData;
    try {
        imageData = tempCtx.getImageData(0, 0, width, height);
    } catch (e) {
        console.error("Could not get image data, possibly due to CORS or other security restrictions.", e);
        // Fallback: return a canvas with the original image drawn, without the effect
        ctx.drawImage(originalImg, 0, 0, width, height);
        return canvas;
    }
    const data = imageData.data;
    
    // Prepare pixel data for the edge mask. Initialized to transparent black (all zeros).
    const edgePixelData = new Uint8ClampedArray(width * height * 4);

    // Edge Detection (Simplified gradient magnitude)
    // Skip 1-pixel border to avoid boundary checks for neighbors; these pixels will remain transparent in edgePixelData.
    for (let y = 1; y < height - 1; y++) {
        for (let x = 1; x < width - 1; x++) {
            const i = (y * width + x) * 4; // Current pixel index in the data array

            // Helper to get grayscale intensity (average of R,G,B) for a pixel at a given offset
            const getGrayscale = (pixelStartIndex) => 
                (data[pixelStartIndex] + data[pixelStartIndex + 1] + data[pixelStartIndex + 2]) / 3;

            // Calculate offsets for neighboring pixels
            const W_offset = (y * width + (x - 1)) * 4;
            const E_offset = (y * width + (x + 1)) * 4;
            const N_offset = ((y - 1) * width + x) * 4;
            const S_offset = ((y + 1) * width + x) * 4;

            const valW = getGrayscale(W_offset);
            const valE = getGrayscale(E_offset);
            const valN = getGrayscale(N_offset);
            const valS = getGrayscale(S_offset);
            
            // Sobel-like gradient calculation (simplified)
            const gradX = valE - valW;
            const gradY = valS - valN; // In image coordinates, Y typically increases downwards
            const magnitude = Math.sqrt(gradX * gradX + gradY * gradY);

            if (magnitude > edgeThreshold) {
                edgePixelData[i] = r_glow;      // Red component of glow color
                edgePixelData[i + 1] = g_glow;  // Green component of glow color
                edgePixelData[i + 2] = b_glow;  // Blue component of glow color
                edgePixelData[i + 3] = 255;     // Alpha (fully opaque)
            } 
            // Pixels not meeting threshold remain transparent black due to Uint8ClampedArray initialization
        }
    }
    
    // Create an ImageData object from our manually constructed edge pixel data
    const edgeImageData = new ImageData(edgePixelData, width, height);

    // Canvas for the colored edges (pre-blur)
    const edgeColorCanvas = document.createElement('canvas');
    edgeColorCanvas.width = width;
    edgeColorCanvas.height = height;
    const edgeColorCtx = edgeColorCanvas.getContext('2d');
    edgeColorCtx.putImageData(edgeImageData, 0, 0);

    // Canvas for the blurred glow
    const glowCanvas = document.createElement('canvas');
    glowCanvas.width = width;
    glowCanvas.height = height;
    const glowCtx = glowCanvas.getContext('2d');

    // Apply blur to the colored edges to create the glow effect
    const sanitizedBlurAmount = Math.max(0, blurAmount); // Ensure blur is not negative
    if (sanitizedBlurAmount > 0) {
        glowCtx.filter = `blur(${sanitizedBlurAmount}px)`;
    }
    glowCtx.drawImage(edgeColorCanvas, 0, 0, width, height);
    if (sanitizedBlurAmount > 0) { // Reset filter only if it was applied
        glowCtx.filter = 'none'; 
    }

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

    // 2. Draw the glow layer on top using 'lighter' for an additive effect
    ctx.globalCompositeOperation = 'lighter'; 
    ctx.globalAlpha = Math.max(0, Math.min(1, glowStrength)); // Clamp strength to [0,1]
    ctx.drawImage(glowCanvas, 0, 0, width, height);

    // Reset global alpha and composite operation to defaults for subsequent drawing operations if any
    ctx.globalAlpha = 1.0;
    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 Kirlian Photography Filter Effect Tool allows users to apply a Kirlian photography-style glow effect to their images. By adjusting parameters such as glow color, glow strength, blur amount, and edge threshold, users can create visually striking images that emphasize edges with a glowing aura. This tool is ideal for artists, photographers, and graphic designers looking to enhance their visual content for creative projects, social media posts, or artistic expressions.

Leave a Reply

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