Please bookmark this page to avoid losing your image tool!

Image Motion Heatmap Overlay Generator

(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, directionAngle = "45", trailLength = "60", trailDensity = "2", heatmapOpacity = "0.75", sensitivity = "60") {
    // 1. Parse and sanitize input parameters
    const angleRad = parseFloat(directionAngle) * Math.PI / 180;
    const length = Math.max(1, parseInt(trailLength, 10)); // Number of accumulation steps
    const stepSize = Math.max(0.1, parseFloat(trailDensity)); // Distance per step
    const opacity = Math.max(0.0, Math.min(1.0, parseFloat(heatmapOpacity)));
    // Sensitivity maps to difference threshold (0 to 100+). Higher sensitivity = lower threshold.
    const sensPcl = Math.max(0, Math.min(100, parseFloat(sensitivity)));
    const thresholdVal = 100 - sensPcl; 

    // Retrieve image dimensions
    const width = originalImg.naturalWidth || originalImg.width;
    const height = originalImg.naturalHeight || originalImg.height;

    // Set up the main output canvas
    const mainCanvas = document.createElement('canvas');
    mainCanvas.width = width;
    mainCanvas.height = height;
    const ctx = mainCanvas.getContext('2d');
    
    // Draw the original image as base
    ctx.drawImage(originalImg, 0, 0);

    // 2. Create an "Activity Map" based on luminance contrast to simulate prominent features
    const threshCanvas = document.createElement('canvas');
    threshCanvas.width = width;
    threshCanvas.height = height;
    const tCtx = threshCanvas.getContext('2d');
    tCtx.drawImage(originalImg, 0, 0);

    const imgData = tCtx.getImageData(0, 0, width, height);
    const data = imgData.data;

    // Calculate Average Luma to find relative prominent features
    let sumLuma = 0;
    const numPixels = width * height;
    for (let i = 0; i < data.length; i += 4) {
        sumLuma += 0.299 * data[i] + 0.587 * data[i+1] + 0.114 * data[i+2];
    }
    const avgLuma = sumLuma / numPixels;

    // Apply brightness thresholding
    const activeRange = 255.0 - thresholdVal;
    for (let i = 0; i < data.length; i += 4) {
        const luma = 0.299 * data[i] + 0.587 * data[i+1] + 0.114 * data[i+2];
        const diff = Math.abs(luma - avgLuma);

        // If a pixel stands out from the average, record it in the activity map's alpha
        if (diff > thresholdVal && activeRange > 0) {
            const intensity = Math.min(1.0, (diff - thresholdVal) / activeRange);
            data[i] = 255;
            data[i+1] = 255;
            data[i+2] = 255;
            data[i+3] = Math.floor(intensity * 255);
        } else {
            data[i+3] = 0; // Transparent
        }
    }
    tCtx.putImageData(imgData, 0, 0);

    // 3. Accumulate "Activity" in a directional smear (motion blur approach)
    const accCanvas = document.createElement('canvas');
    accCanvas.width = width;
    accCanvas.height = height;
    const accCtx = accCanvas.getContext('2d');

    const dx = Math.cos(angleRad) * stepSize;
    const dy = Math.sin(angleRad) * stepSize;

    // Additive blending for accumulation logic
    accCtx.globalCompositeOperation = 'lighter';
    // Tune alpha based on trail length so accumulation heats up properly without blowing out instantly
    accCtx.globalAlpha = Math.max(0.01, 3.5 / length);

    // Smear in the reverse direction of the angle to simulate forward motion
    for (let i = 0; i <= length; i++) {
        accCtx.drawImage(threshCanvas, -i * dx, -i * dy);
    }

    // 4. Map the accumulated directional intensities into a thermal Heatmap gradient
    const accImgData = accCtx.getImageData(0, 0, width, height);
    const aData = accImgData.data;

    const overlayData = new ImageData(width, height);
    const oData = overlayData.data;

    // Standard Thermal/Jet stops
    const stops = [
        [0,   0,   0,   0],       // 0.0 - Transparent base
        [0,   0,   255, 120],     // 0.16 - Deep Blue
        [0,   255, 255, 200],     // 0.33 - Cyan
        [0,   255, 0,   255],     // 0.50 - Green
        [255, 255, 0,   255],     // 0.66 - Yellow
        [255, 0,   0,   255],     // 0.83 - Red
        [255, 255, 255, 255]      // 1.00 - White Hot Core
    ];
    const numStops = stops.length - 1;

    for (let i = 0; i < aData.length; i += 4) {
        // Evaluate heat from the greyscale accumulation (R channel suffices)
        const t = Math.min(1.0, aData[i] / 255.0);

        if (t <= 0.01) {
            oData[i] = 0; oData[i+1] = 0; oData[i+2] = 0; oData[i+3] = 0;
            continue;
        }

        const scaledT = t * numStops;
        const idx = Math.floor(scaledT);
        
        if (idx >= numStops) {
            const endCoord = stops[numStops];
            oData[i] = endCoord[0]; oData[i+1] = endCoord[1]; oData[i+2] = endCoord[2]; oData[i+3] = endCoord[3];
        } else {
            const frac = scaledT - idx;
            const c1 = stops[idx];
            const c2 = stops[idx + 1];

            // Interpolate colors to create smooth temperature gradients
            oData[i]   = c1[0] + (c2[0] - c1[0]) * frac;
            oData[i+1] = c1[1] + (c2[1] - c1[1]) * frac;
            oData[i+2] = c1[2] + (c2[2] - c1[2]) * frac;
            oData[i+3] = c1[3] + (c2[3] - c1[3]) * frac;
        }
    }

    // 5. Apply the heatmap overlay symmetrically atop the base layer
    const overlayCanvas = document.createElement('canvas');
    overlayCanvas.width = width;
    overlayCanvas.height = height;
    const oCtx = overlayCanvas.getContext('2d');
    oCtx.putImageData(overlayData, 0, 0);

    ctx.globalAlpha = opacity;
    // Overlay logic, using 'screen' or generic over composition handles nice blending
    ctx.globalCompositeOperation = 'screen';
    ctx.drawImage(overlayCanvas, 0, 0);
    ctx.globalAlpha = 1.0;
    ctx.globalCompositeOperation = 'source-over';

    return mainCanvas;
}

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 Motion Heatmap Overlay Generator creates a visual representation of perceived movement and activity within an image. By analyzing luminance contrast and applying a directional smear effect, the tool overlays a color-coded thermal gradient (ranging from deep blue to white-hot) that simulates motion trails and high-activity zones. This can be useful for artistic photography, creating motion-blur effects, or visually emphasizing certain directions and focal points in a composition.

Leave a Reply

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