Please bookmark this page to avoid losing your image tool!

Image Airplane Contrail 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, 
    numContrails = 3, 
    contrailColorRGB = "255,255,255", 
    contrailOpacity = 0.7, 
    maxThickness = 8, 
    minThickness = 2, 
    blurStrength = 15
) {
    // Helper function to generate random points on the perimeter of an "extended" version of the image canvas.
    // The "extended" canvas is larger than the actual image by a margin on all sides.
    // This ensures that contrails appear to originate and terminate off-screen, crossing the entire image.
    function getRandomPointOnExtendedEdge(W, H, margin) {
        const side = Math.floor(Math.random() * 4); // 0: top, 1: right, 2: bottom, 3: left
        let x, y;
        
        // Calculate dimensions of the effectively larger area from which points are chosen.
        // Points can be on segments from (-margin, -margin) to (W+margin, H+margin).
        const extendedW = W + 2 * margin; // Full width of the extended area for random selection along an edge
        const extendedH = H + 2 * margin; // Full height of the extended area

        switch (side) {
            case 0: // Point on the top extended edge
                x = Math.random() * extendedW - margin; // x coordinate from -margin to W+margin
                y = -margin;                           // y coordinate fixed at -margin (top edge of extended box)
                break;
            case 1: // Point on the right extended edge
                x = W + margin;                        // x coordinate fixed at W+margin (right edge of extended box)
                y = Math.random() * extendedH - margin; // y coordinate from -margin to H+margin
                break;
            case 2: // Point on the bottom extended edge
                x = Math.random() * extendedW - margin;
                y = H + margin;                        // y coordinate fixed at H+margin (bottom edge of extended box)
                break;
            case 3: // Point on the left extended edge
                x = -margin;                           // x coordinate fixed at -margin (left edge of extended box)
                y = Math.random() * extendedH - margin;
                break;
        }
        return { x, y, side }; // Return coordinates and the side chosen
    }

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

    const W = originalImg.naturalWidth || originalImg.width;
    const H = originalImg.naturalHeight || originalImg.height;
    canvas.width = W;
    canvas.height = H;

    // Draw the original image onto the canvas
    ctx.drawImage(originalImg, 0, 0, W, H);

    // --- Parameter Validation and Sanitization ---

    // Validate and parse contrailColorRGB parameter (e.g., "255,0,0" for red)
    let r = 255, g = 255, b = 255; // Default to white color
    if (typeof contrailColorRGB === 'string') {
        const parts = contrailColorRGB.split(',').map(c => parseInt(c.trim(), 10));
        if (parts.length === 3 && parts.every(val => !isNaN(val) && val >= 0 && val <= 255)) {
            [r, g, b] = parts;
        } else {
            console.warn(`Invalid contrailColorRGB string: "${contrailColorRGB}". Using default white (255,255,255).`);
        }
    } else {
        console.warn(`contrailColorRGB is not a string: ${contrailColorRGB}. Using default white (255,255,255).`);
    }
    
    // Validate contrailOpacity parameter (0.0 to 1.0)
    let finalOpacity = parseFloat(contrailOpacity);
    if (isNaN(finalOpacity) || finalOpacity < 0 || finalOpacity > 1) {
        console.warn(`Invalid contrailOpacity: ${contrailOpacity}. Must be a number between 0 and 1. Using default 0.7.`);
        finalOpacity = 0.7;
    }

    const finalContrailColor = `rgba(${r}, ${g}, ${b}, ${finalOpacity})`;
    
    // Ensure blurStrength is a non-negative number
    const actualBlurStrength = Math.max(0, parseFloat(blurStrength) || 0);

    // Validate and order thickness parameters, ensuring they are non-negative numbers
    // parseFloat will handle string inputs like "5" or "5px" (becomes 5 for "5px")
    // Default to 0 if parsing fails (e.g. "abc" string)
    let parsedMinThickness = parseFloat(minThickness) || 0;
    let parsedMaxThickness = parseFloat(maxThickness) || 0;

    let mThick = Math.min(parsedMinThickness, parsedMaxThickness);
    let MThick = Math.max(parsedMinThickness, parsedMaxThickness);
    if (mThick < 0) mThick = 0;
    if (MThick < 0) MThick = 0; // MThick is guaranteed >= mThick, so this checks if both were negative.

    // Validate number of contrails (must be a non-negative integer)
    const numContrailsToDraw = Math.max(0, parseInt(numContrails, 10) || 0);

    // --- Contrail Drawing Loop ---
    for (let i = 0; i < numContrailsToDraw; i++) {
        // Determine random thickness for the current contrail's core line, within the mThick-MThick range
        const currentThickness = (MThick === mThick) ? mThick : (Math.random() * (MThick - mThick) + mThick);
        
        // Define a margin around the canvas. Contrail start/end points will be on the edge of this margin.
        // This ensures the blur and line caps of contrails don't abruptly start/end visibly on the canvas.
        // The margin size depends on blur strength and maximum possible line thickness.
        const margin = actualBlurStrength + MThick; 

        // Get a random starting point (P1) on one of the extended edges
        const P1_info = getRandomPointOnExtendedEdge(W, H, margin);
        let P2_info;
        
        // Get a random ending point (P2) on an extended edge.
        // The do-while loop ensures P2 is on a different "axis group" (horizontal vs. vertical edges) than P1.
        // This strategy promotes contrails that generally cross the image diagonally, rather than short lines
        // or lines that might run parallel and close to an edge.
        // (side % 2 === 0 for top/bottom edges, side % 2 === 1 for left/right edges)
        do {
            P2_info = getRandomPointOnExtendedEdge(W, H, margin);
        } while (P2_info.side % 2 === P1_info.side % 2); 
                                                                              
        const x1 = P1_info.x;
        const y1 = P1_info.y;
        const x2 = P2_info.x;
        const y2 = P2_info.y;

        // Apply shadow for the blurred part of the contrail (the main visual effect)
        ctx.shadowColor = finalContrailColor; // The color of the glow/blur (includes opacity)
        ctx.shadowBlur = actualBlurStrength;  // How much blur (diffusion)
        
        // Draw the core line of the contrail
        // This line itself will be blurred due to the shadow effect.
        // Its color can be the same as the shadow to reinforce the center of the blurred area.
        ctx.strokeStyle = finalContrailColor; 
        ctx.lineWidth = currentThickness;     // Thickness of the core line segment
        ctx.lineCap = 'round';                // Creates soft, rounded ends for the line segment itself

        ctx.beginPath();
        ctx.moveTo(x1, y1);
        ctx.lineTo(x2, y2);
        ctx.stroke();

        // Reset shadow properties after drawing each contrail.
        // This prevents the shadow settings from affecting subsequent drawing operations
        // (e.g., other contrails in this loop, or any drawing done on the canvas afterwards).
        ctx.shadowColor = 'transparent'; // Effectively 'rgba(0,0,0,0)'
        ctx.shadowBlur = 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 Airplane Contrail Filter Effect Tool allows users to apply a visually striking airplane contrail effect to their images. Users can customize various parameters such as the number of contrails, their color, opacity, thickness, and blur strength, resulting in unique artistic renditions of their photos. This tool is ideal for graphic designers, digital artists, or anyone looking to enhance images for creative projects, social media posts, or personalized gifts. The contrails add a dynamic, sky-like flair, making images stand out.

Leave a Reply

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