Please bookmark this page to avoid losing your image tool!

Image Double Exposure 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, 
    secondImageUrl = "", 
    blendMode = "lighten", 
    opacity1 = 1.0, 
    opacity2 = 0.7, 
    desaturateSecondLayer = 0
) {
    // Ensure numerical parameters are indeed numbers
    const numOpacity1 = Number(opacity1);
    const numOpacity2 = Number(opacity2);
    const numDesaturateSecondLayer = Number(desaturateSecondLayer);

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

    // Determine dimensions for the main canvas from originalImg
    // Uses naturalWidth/Height for HTMLImageElement, or width/height for HTMLCanvasElement
    const mainCanvasWidth = originalImg.naturalWidth || originalImg.width;
    const mainCanvasHeight = originalImg.naturalHeight || originalImg.height;

    // Validate dimensions of originalImg
    if (!mainCanvasWidth || !mainCanvasHeight || mainCanvasWidth === 0 || mainCanvasHeight === 0) {
        console.error("Original image is invalid, not loaded, or has zero dimensions. Cannot process.");
        // Create and return a small canvas with an error message
        const errorCanvas = document.createElement('canvas');
        errorCanvas.width = 300;
        errorCanvas.height = 100;
        const errCtx = errorCanvas.getContext('2d');
        
        errCtx.fillStyle = '#EFEFEF'; // Light gray background
        errCtx.fillRect(0, 0, errorCanvas.width, errorCanvas.height);
        errCtx.fillStyle = '#D32F2F'; // Red text for error
        errCtx.font = 'bold 15px Arial';
        errCtx.textAlign = 'center';
        errCtx.textBaseline = 'middle';
        errCtx.fillText('Error: Original image is not valid.', errorCanvas.width / 2, errorCanvas.height / 2);
        return errorCanvas;
    }
    
    canvas.width = mainCanvasWidth;
    canvas.height = mainCanvasHeight;

    // 1. Prepare the second image source
    // This will eventually hold an HTMLImageElement or HTMLCanvasElement to be used as the second layer
    let secondImageSourceToProcess; 

    const loadImage = (src) => {
        return new Promise((resolve, reject) => {
            const img = new Image();
            // Important for loading images from other domains to avoid tainting the canvas
            img.crossOrigin = "Anonymous"; 
            img.onload = () => resolve(img);
            img.onerror = (errEvent) => {
                // The error event itself doesn't give much info directly, the message is more for logging
                reject(new Error(`Failed to load image from URL: ${src}`));
            };
            img.src = src;
        });
    };

    if (typeof secondImageUrl === 'string' && secondImageUrl.trim() !== "") {
        try {
            secondImageSourceToProcess = await loadImage(secondImageUrl);
        } catch (error) {
            console.warn(`${error.message}. Using the original image as the second layer instead.`);
            // Fallback: if the external image fails to load, use the originalImg as the second source
            secondImageSourceToProcess = originalImg;
        }
    } else {
        // If no secondImageUrl is provided (or it's an empty string), use originalImg as the second source
        secondImageSourceToProcess = originalImg;
    }

    // 2. Optionally desaturate the second image source
    let finalSecondLayerImage = secondImageSourceToProcess; // This is what will be drawn

    if (numDesaturateSecondLayer === 1) {
        const tempDesaturationCanvas = document.createElement('canvas');
        const tempDesaturationCtx = tempDesaturationCanvas.getContext('2d');
        
        // Get dimensions of the image to be desaturated
        const sWidth = secondImageSourceToProcess.naturalWidth || secondImageSourceToProcess.width;
        const sHeight = secondImageSourceToProcess.naturalHeight || secondImageSourceToProcess.height;

        // Proceed with desaturation only if dimensions are valid
        if (sWidth && sHeight && sWidth > 0 && sHeight > 0) {
            tempDesaturationCanvas.width = sWidth;
            tempDesaturationCanvas.height = sHeight;
    
            tempDesaturationCtx.filter = 'grayscale(100%)';
            tempDesaturationCtx.drawImage(secondImageSourceToProcess, 0, 0, sWidth, sHeight);
            tempDesaturationCtx.filter = 'none'; // Reset filter for good practice
    
            finalSecondLayerImage = tempDesaturationCanvas; // Use the desaturated canvas content
        } else {
            console.warn("Second image source chosen for desaturation has zero dimensions. Skipping desaturation step.");
            // finalSecondLayerImage remains as secondImageSourceToProcess (which might be an invalid/unloaded image)
        }
    }

    // 3. Draw the layers onto the main canvas

    // Draw the first layer (originalImg)
    // Clamp opacity values to the valid [0, 1] range
    ctx.globalAlpha = Math.max(0, Math.min(1, numOpacity1)); 
    ctx.drawImage(originalImg, 0, 0, mainCanvasWidth, mainCanvasHeight);

    // Prepare to draw the second layer
    // Ensure finalSecondLayerImage is valid and has dimensions before drawing
    const finalSecondWidth = finalSecondLayerImage.naturalWidth || finalSecondLayerImage.width;
    const finalSecondHeight = finalSecondLayerImage.naturalHeight || finalSecondLayerImage.height;

    if (finalSecondLayerImage && finalSecondWidth > 0 && finalSecondHeight > 0) {
        ctx.globalCompositeOperation = blendMode; // Set the blend mode
        ctx.globalAlpha = Math.max(0, Math.min(1, numOpacity2)); // Set opacity for the second layer

        // Draw the second image, scaled to fit the main canvas dimensions
        ctx.drawImage(finalSecondLayerImage, 0, 0, mainCanvasWidth, mainCanvasHeight);
    } else {
        console.warn("Final second layer image is invalid or has zero dimensions. Skipping drawing of the second layer.");
    }
    
    // Reset canvas context properties to their defaults for good hygiene
    ctx.globalAlpha = 1.0;
    ctx.globalCompositeOperation = 'source-over'; // Default blend mode

    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 Double Exposure Filter Effect Tool allows users to create double exposure images by blending two images together using various blend modes and adjustable opacities. This tool can be useful for enhancing photographs, creating artistic effects for social media posts, or designing unique visuals for marketing materials. Users can specify a primary image and an optional second image, control the blending effect, and apply desaturation to the second image for creative output.

Leave a Reply

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

Other Image Tools:

Image Fujichrome Velvia 50 Filter Effect Application

Image Revolog Texture Film Filter Effect Tool

Image Lomography Metropolis Filter Effect Application

Image Variable ND Filter Effect Tool

Image 8mm Movie Film Filter Effect Application

Image TMax 100 Filter Effect Application

Image Fog Filter Effect Tool

Image Ektachrome E100 Filter Effect Application

Image RED Cinema Camera Filter Effect Tool

Image Reverse Graduated ND Filter Effect Tool

Image Kaleidoscope Filter Effect Tool

Image Platinum Palladium Print Filter Effect

Image Light Leak Filter Effect Tool

Image Moire Pattern Filter Effect Tool

Image Pull Processing Filter Effect Tool

Photo Ambrotype Filter Effect Tool

Image Cross-Screen Star Filter Effect Tool

Image Tiffen Ultra Contrast Filter Effect Application

Photo Telephoto Lens Compression Filter Effect Tool

Image Leica M6 Camera Render Filter Effect

Image Cokin Sunset Filter Effect Application

Image CineScope Aspect Ratio Filter Effect Tool

Image Ilford FP4 Plus Filter Effect Tool

Image Infrared 850nm Filter Effect Tool

Image Pentax 67 Medium Format Filter Effect Tool

Image ARRI Alexa Cinema Camera Filter Effect Enhancer

Image Cinestill 50D Filter Effect Application

Image Kodachrome 64 Filter Effect Tool

Photo Lomography Berlin Kino Filter Effect Tool

Image Fujifilm Neopan Filter Effect Tool

Image Polaroid Instant Film Filter Effect Tool

Image Holga Camera Filter Effect Tool

Image Fisheye Lens Distortion Filter Effect Tool

Image Kodak Gold 200 Film Filter Effect Tool

Photo Macro Filter Effect Tool

Image Neutral Density Filter Effect Tool

See All →