Please bookmark this page to avoid losing your image tool!

Image Ski Trail 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, 
    trailAngle = 0,      // Degrees: 0 is right, 90 is down
    numStreaks = 8,      // Number of streak copies to create the trail effect
    streakSpread = 1.5,  // Pixel distance between each streak copy
    streakOpacity = 0.1, // Opacity of each individual streak copy (0 to 1)
    highlightThreshold = 0.7 // Luminance threshold (0 to 1) for pixels to contribute to streaks. 
                             // 0 uses the full image, 1 uses only pure white.
) {
    const canvas = document.createElement('canvas');
    // The main context will do drawing. If highlightThreshold is used, it will involve reading pixels.
    const ctxOptions = {};
    if (highlightThreshold > 0 && highlightThreshold <= 1) {
        // Hint that the main canvas might have its contents read if we were to do more complex blends later,
        // but for this specific implementation, only highlightCanvas is read.
        // However, setting it on the main canvas doesn't hurt.
        // ctxOptions.willReadFrequently = true; 
    }
    const ctx = canvas.getContext('2d', ctxOptions);

    const w = originalImg.width || originalImg.naturalWidth;
    const h = originalImg.height || originalImg.naturalHeight;
    canvas.width = w;
    canvas.height = h;

    if (w === 0 || h === 0) {
        console.error("Image has zero width or height.");
        return canvas; // Return empty canvas
    }

    let imageForStreaks = originalImg;

    // If highlightThreshold is between 0 (exclusive) and 1 (inclusive),
    // create a version of the image containing only pixels brighter than the threshold.
    if (highlightThreshold > 0 && highlightThreshold <= 1) {
        const highlightCanvas = document.createElement('canvas');
        highlightCanvas.width = w;
        highlightCanvas.height = h;
        const highlightCtx = highlightCanvas.getContext('2d', { willReadFrequently: true }); 
        
        highlightCtx.drawImage(originalImg, 0, 0, w, h);

        try {
            const imageData = highlightCtx.getImageData(0, 0, w, h);
            const data = imageData.data;
            const thresholdValue = highlightThreshold * 255;

            for (let i = 0; i < data.length; i += 4) {
                const r = data[i];
                const g = data[i + 1];
                const b = data[i + 2];
                
                // Luminance calculation (Rec. 709 formula)
                const luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b;
                
                if (luminance < thresholdValue) {
                    data[i + 3] = 0; // Make pixels below threshold transparent
                }
                // Pixels at or above threshold retain their original color and alpha.
            }
            highlightCtx.putImageData(imageData, 0, 0);
            imageForStreaks = highlightCanvas; // This canvas (with transparent parts) will be used for streaks
        } catch (e) {
            console.error("Error processing image data for highlights (possibly due to tainted canvas):", e);
            // Fallback to using original image if getImageData fails
            imageForStreaks = originalImg;
        }
    }

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

    // 2. Draw the streak layers
    // 'lighter' composite operation adds color values, making streaks appear bright.
    ctx.globalCompositeOperation = 'lighter'; 
    
    const angleRad = trailAngle * (Math.PI / 180); // Convert degrees to radians

    for (let i = 1; i <= numStreaks; i++) {
        // Calculate the offset for the current streak copy
        const currentSpread = streakSpread * i;
        const offsetX = currentSpread * Math.cos(angleRad);
        const offsetY = currentSpread * Math.sin(angleRad);
        
        ctx.globalAlpha = streakOpacity; // Set opacity for this streak copy
        
        // Draw the (potentially highlight-filtered) image at the calculated offset
        if (imageForStreaks.width > 0 && imageForStreaks.height > 0) {
             ctx.drawImage(imageForStreaks, offsetX, offsetY, w, h);
        }
    }

    // Reset canvas context properties to defaults
    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 Ski Trail Filter Effect Tool applies a dynamic trail effect to images, allowing users to create artistic streaks that simulate motion. By adjusting the angle, number of streaks, their spread, and opacity, users can customize the visibility and intensity of the trails. This tool is perfect for enhancing photos of outdoor activities, adding an artistic flair to sports imagery, or creating visually engaging graphics for social media and marketing materials.

Leave a Reply

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