Please bookmark this page to avoid losing your image tool!

Image Wave Distortion 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, amplitude = 10, wavelength = 50, phase = 0, direction = "horizontal") {
    // Validate and sanitize parameters, falling back to defaults if necessary.
    // Parameters from the function signature already have defaults if they are 'undefined'.
    // This section further ensures they are numeric and within valid ranges if they were explicitly passed as unparseable strings.

    let numAmplitude = Number(amplitude);
    if (isNaN(numAmplitude)) {
        numAmplitude = 10; // Fallback to default if 'amplitude' was an unparseable string (e.g., "abc")
    }

    let numWavelength = Number(wavelength);
    // Wavelength must be meaningful, at least 2 pixels for a full cycle.
    if (isNaN(numWavelength) || numWavelength < 2) {
        numWavelength = 50; // Fallback to default if 'wavelength' was unparseable or too small
    }

    let numPhase = Number(phase);
    if (isNaN(numPhase)) {
        numPhase = 0; // Fallback to default if 'phase' was unparseable
    }

    let strDirection = String(direction).toLowerCase();
    if (strDirection !== "horizontal" && strDirection !== "vertical") {
        strDirection = "horizontal"; // Fallback to default direction
    }

    const canvas = document.createElement('canvas');
    // Add willReadFrequently hint for potential performance optimization when using getImageData/putImageData.
    const ctx = canvas.getContext('2d', { willReadFrequently: true });

    // Use naturalWidth/Height for intrinsic dimensions, fallback to width/height.
    const width = originalImg.naturalWidth || originalImg.width;
    const height = originalImg.naturalHeight || originalImg.height;

    // Handle cases like an image not yet loaded or a zero-size image.
    if (width === 0 || height === 0) {
        canvas.width = 0;
        canvas.height = 0;
        return canvas; // Return an empty canvas.
    }

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

    // Draw the original image onto the canvas. This allows us to access its pixel data.
    ctx.drawImage(originalImg, 0, 0, width, height);
    
    // Get the pixel data of the original image.
    const originalImageData = ctx.getImageData(0, 0, width, height);
    const originalData = originalImageData.data;

    // Create a new ImageData object to store the distorted image's pixels.
    const distortedImageData = ctx.createImageData(width, height);
    const distortedData = distortedImageData.data;

    const TWO_PI = Math.PI * 2;

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

            if (strDirection === "horizontal") {
                // Waves run horizontally across the image (oscillation depends on x-coordinate).
                // Pixels are displaced vertically.
                offset = numAmplitude * Math.sin((TWO_PI * x / numWavelength) + numPhase);
                srcX = x;
                srcY = y - offset; //  y - offset: positive amplitude pulls image data from "above", visually shifting content "down".
            } else { // strDirection === "vertical"
                // Waves run vertically down the image (oscillation depends on y-coordinate).
                // Pixels are displaced horizontally.
                offset = numAmplitude * Math.sin((TWO_PI * y / numWavelength) + numPhase);
                srcX = x - offset; // x - offset: positive amplitude pulls image data from "left", visually shifting content "right".
                srcY = y;
            }

            // Apply nearest neighbor sampling for the source pixel.
            // Round to the nearest integer coordinates for srcX and srcY.
            const iSrcX_rounded = Math.round(srcX);
            const iSrcY_rounded = Math.round(srcY);

            // Calculate the index for the destination pixel in the 1D data array.
            const destPixelIndex = (y * width + x) * 4;

            // Handle out-of-bounds source coordinates by clamping them to the image edges.
            // This means pixels at the edge are effectively repeated if the wave samples beyond the boundary.
            const clampedSrcX = Math.max(0, Math.min(width - 1, iSrcX_rounded));
            const clampedSrcY = Math.max(0, Math.min(height - 1, iSrcY_rounded));
            
            // Calculate the index for the (clamped) source pixel in the 1D data array.
            const srcPixelIndex = (clampedSrcY * width + clampedSrcX) * 4;

            // Copy RGBA components from the source pixel to the destination pixel.
            distortedData[destPixelIndex]     = originalData[srcPixelIndex];     // Red
            distortedData[destPixelIndex + 1] = originalData[srcPixelIndex + 1]; // Green
            distortedData[destPixelIndex + 2] = originalData[srcPixelIndex + 2]; // Blue
            distortedData[destPixelIndex + 3] = originalData[srcPixelIndex + 3]; // Alpha
        }
    }

    // Put the (now distorted) image data back onto the canvas.
    ctx.putImageData(distortedImageData, 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 Wave Distortion Filter allows users to apply a dynamic wave distortion effect to images. By manipulating parameters such as amplitude, wavelength, phase, and direction, this tool can create unique visual effects that add depth and movement to static images. It is useful for graphic designers, digital artists, or anyone looking to enhance their images with creative distortions for use in presentations, social media posts, or artistic projects.

Leave a Reply

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