Please bookmark this page to avoid losing your image tool!

Image Heat Haze Filter

(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, strength = 10, waveFrequencyY = 0.05, waveFrequencyX = 0.01, phaseOffset = 0) {
    // Get image dimensions
    const width = originalImg.naturalWidth;
    const height = originalImg.naturalHeight;

    // Handle cases of invalid image dimensions (e.g., image not loaded properly)
    if (width === 0 || height === 0) {
        const emptyCanvas = document.createElement('canvas');
        emptyCanvas.width = width;
        emptyCanvas.height = height;
        // Optionally draw the (empty) original image if it makes sense,
        // though on a 0-dimension canvas, it won't be visible.
        // const ctx = emptyCanvas.getContext('2d');
        // if (ctx) { // Should always get a context
        //     ctx.drawImage(originalImg, 0, 0);
        // }
        return emptyCanvas; // Returns a 0-width or 0-height canvas
    }

    // Create a canvas to draw the processed image
    const canvas = document.createElement('canvas');
    canvas.width = width;
    canvas.height = height;
    const ctx = canvas.getContext('2d');

    // Draw the original image onto the canvas. This is necessary to access its pixel data.
    ctx.drawImage(originalImg, 0, 0, width, height);

    // Get the pixel data from the original image drawn on the canvas
    const originalImageData = ctx.getImageData(0, 0, width, height);
    const originalData = originalImageData.data;

    // Create a new ImageData object to store the processed pixels
    // This avoids modifying the originalImageData directly while iterating
    const newImageData = ctx.createImageData(width, height);
    const newData = newImageData.data;

    // Apply the heat haze effect pixel by pixel
    for (let y = 0; y < height; y++) {
        for (let x = 0; x < width; x++) {
            // Calculate the dynamic phase for the sine wave.
            // This phase depends on both y (for vertical waves) and x (for horizontal turbulence),
            // creating a more complex wave pattern.
            // - y * waveFrequencyY: Primary vertical wave.
            // - x * waveFrequencyX: Adds horizontal variation/turbulence to the waves.
            // - phaseOffset: Shifts the entire wave pattern.
            const dynamicPhase = (y * waveFrequencyY) + (x * waveFrequencyX) + phaseOffset;
            
            // Calculate horizontal displacement using a sine wave.
            // 'strength' controls the amplitude (max displacement) of the wave.
            const displacementX = strength * Math.sin(dynamicPhase);

            // Determine the source x-coordinate from which to pick the pixel.
            // Add the calculated displacement to the current x-coordinate.
            // Math.round is used to get an integer pixel coordinate.
            let srcX = Math.round(x + displacementX);
            
            // For this heat haze effect, the source y-coordinate remains the same as the destination y.
            // This creates a predominantly horizontal shimmering/distortion.
            const srcY = y;

            // Clamp the source x-coordinate to be within the image boundaries.
            // This prevents trying to read pixels from outside the image.
            srcX = Math.max(0, Math.min(width - 1, srcX));
            // srcY is inherently within bounds [0, height - 1] because it's `y` from the loop.

            // Calculate the array indices for the destination pixel (in newData)
            // and the source pixel (in originalData).
            // Each pixel consists of 4 bytes (R, G, B, A).
            const dstIndex = (y * width + x) * 4;
            const srcIndex = (srcY * width + srcX) * 4;

            // Copy the pixel data (RGBA) from the source location in the original image
            // to the destination location in the new image data.
            newData[dstIndex]     = originalData[srcIndex];     // Red component
            newData[dstIndex + 1] = originalData[srcIndex + 1]; // Green component
            newData[dstIndex + 2] = originalData[srcIndex + 2]; // Blue component
            newData[dstIndex + 3] = originalData[srcIndex + 3]; // Alpha component
        }
    }

    // Put the modified pixel data (newImageData) back onto the canvas
    ctx.putImageData(newImageData, 0, 0);

    // Return the canvas element with the heat haze effect applied
    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 Heat Haze Filter is a tool designed to apply a heat haze effect to images, creating a shimmering, distorted appearance that mimics the visual effects of heat waves. This effect can be particularly useful for enhancing landscape photos, artistic projects, or any imagery where you want to simulate atmospheric distortions. Users can adjust the strength of the effect, as well as the wave frequencies, allowing for customized results tailored to their specific visual preferences.

Leave a Reply

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