Please bookmark this page to avoid losing your image tool!

Image Mirage Filter Application

(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.
/**
 * Applies a mirage (heat haze/ripple) filter to an image.
 * This filter creates a wave-like distortion with optional noise to simulate
 * the visual effect of a mirage or heat shimmering.
 *
 * @param {HTMLImageElement} originalImg The original JavaScript Image object.
 *                                     It's assumed this image is already loaded.
 * @param {number} [amplitude=20] The maximum pixel displacement for the wave effect.
 *                                Larger values create more pronounced waves.
 * @param {number} [frequency=0.04] The frequency of the waves. Lower values create
 *                                 wider waves; higher values create more, tighter waves.
 *                                 The wave function is `sin(frequency * coordinate + phase)`.
 * @param {number} [phase=0] The starting phase of the wave, in radians. Changing this
 *                           value can be used to animate the wave effect if the function
 *                           is called repeatedly with updated phase values.
 * @param {string} [direction="horizontal"] Determines the axis of pixel displacement and
 *                                         the axis along which the wave pattern propagates.
 *                                         - "horizontal": Pixels are displaced horizontally (left/right).
 *                                                         The wave pattern is based on the y-coordinate.
 *                                                         (i.e., displacement_x = f(y))
 *                                         - "vertical":   Pixels are displaced vertically (up/down).
 *                                                         The wave pattern is based on the x-coordinate.
 *                                                         (i.e., displacement_y = f(x))
 * @param {number} [noise=3] The intensity of random noise added to the wave displacement.
 *                           This adds a turbulent or shimmering quality to the effect.
 *                           Values typically range from 0 (no noise, smooth waves) to 5-10 for
 *                           noticeable turbulence.
 * @returns {HTMLCanvasElement} A new canvas element displaying the image with the mirage filter applied.
 */
async function processImage(originalImg, amplitude = 20, frequency = 0.04, phase = 0, direction = "horizontal", noise = 3) {
    const canvas = document.createElement('canvas');
    // Using { willReadFrequently: true } can be an optimization hint for some browsers
    const ctx = canvas.getContext('2d', { willReadFrequently: true });

    // Use naturalWidth/Height for intrinsic image dimensions for raster images
    // Fallback to width/height if naturalWidth/Height are not available (e.g. for SVG or not yet loaded)
    const width = originalImg.naturalWidth || originalImg.width;
    const height = originalImg.naturalHeight || originalImg.height;

    if (width === 0 || height === 0) {
        // Handle cases where image dimensions are not available
        console.error("Image dimensions are zero. Ensure the image is loaded and valid.");
        // Return an empty or minimal canvas to avoid further errors
        canvas.width = 1;
        canvas.height = 1;
        return canvas;
    }

    canvas.width = width;
    canvas.height = height;

    // Draw the original image onto the canvas. This is our source for 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 originalPixels = originalImageData.data;

    // Create a new ImageData object for the output.
    // This is where we'll write the transformed pixels.
    const outputImageData = ctx.createImageData(width, height);
    const outputPixels = outputImageData.data;

    // Iterate over each pixel of the destination image
    for (let y = 0; y < height; y++) {
        for (let x = 0; x < width; x++) {
            let srcX = x;
            let srcY = y;
            let displacementValue;

            if (direction === "horizontal") {
                // Pixels are displaced horizontally.
                // The amount of displacement depends on the y-coordinate (forms horizontal waves).
                displacementValue = amplitude * Math.sin(frequency * y + phase);
                if (noise > 0) {
                    // Add random jitter for a more turbulent/shimmering effect
                    displacementValue += noise * (Math.random() - 0.5);
                }
                srcX = x + Math.round(displacementValue);
            } else { // direction === "vertical"
                // Pixels are displaced vertically.
                // The amount of displacement depends on the x-coordinate (forms vertical waves).
                displacementValue = amplitude * Math.sin(frequency * x + phase);
                if (noise > 0) {
                    // Add random jitter
                    displacementValue += noise * (Math.random() - 0.5);
                }
                srcY = y + Math.round(displacementValue);
            }

            // Clamp source coordinates to be within the image bounds to avoid errors
            srcX = Math.max(0, Math.min(width - 1, srcX));
            srcY = Math.max(0, Math.min(height - 1, srcY));

            // Calculate array indices for the pixel data (source and destination)
            // Each pixel is 4 bytes (R, G, B, A)
            const destIndex = (y * width + x) * 4;
            const srcIndex = (srcY * width + srcX) * 4;

            // Copy pixel data (RGBA) from the source location in originalPixels
            // to the destination location in outputPixels.
            outputPixels[destIndex]     = originalPixels[srcIndex];     // Red
            outputPixels[destIndex + 1] = originalPixels[srcIndex + 1]; // Green
            outputPixels[destIndex + 2] = originalPixels[srcIndex + 2]; // Blue
            outputPixels[destIndex + 3] = originalPixels[srcIndex + 3]; // Alpha
        }
    }

    // Put the modified pixel data back onto the canvas
    ctx.putImageData(outputImageData, 0, 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 Mirage Filter Application allows users to apply a mirage effect to images, simulating the heat haziness or shimmering distortion often seen in hot environments. You can customize various parameters, such as the amplitude and frequency of the waves, the direction of displacement (horizontal or vertical), and the intensity of noise for a more turbulent appearance. This tool can be useful for artistic image editing, enhancing photography, or creating visual effects for digital art. It is ideal for users looking to achieve a unique, wavy distortion that mimics real-world mirage phenomena.

Leave a Reply

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