Please bookmark this page to avoid losing your image tool!

Image Sound Wave 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, amplitude = 20, numWaves = 5, phase = 0, direction = "horizontal", waveType = "sine") {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    // Use naturalWidth and naturalHeight for actual image dimensions
    // Fallback to width/height if natural dimensions are not available (e.g., for SVG or non-loaded images)
    const width = originalImg.naturalWidth || originalImg.width;
    const height = originalImg.naturalHeight || originalImg.height;

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

    // If image has no dimensions (e.g., not loaded or broken), return an empty canvas.
    if (width === 0 || height === 0) {
        return canvas;
    }

    // Draw original image to a temporary canvas to get its pixel data.
    // This is necessary because Image objects don't directly expose pixel data.
    const tempCanvas = document.createElement('canvas');
    tempCanvas.width = width;
    tempCanvas.height = height;
    // Add willReadFrequently hint for potential performance optimization by the browser.
    const tempCtx = tempCanvas.getContext('2d', { willReadFrequently: true }); 
    tempCtx.drawImage(originalImg, 0, 0, width, height);
    
    let originalImageData;
    try {
        originalImageData = tempCtx.getImageData(0, 0, width, height);
    } catch (e) {
        // This can happen if the image is cross-origin and the canvas becomes "tainted",
        // preventing pixel data extraction due to security restrictions.
        console.error("Error getting image data for Sound Wave Filter:", e);
        // As a fallback, draw the original image to the output canvas without the effect.
        ctx.drawImage(originalImg, 0, 0, width, height);
        return canvas;
    }
    
    const originalPixels = originalImageData.data;
    const outputImageData = ctx.createImageData(width, height);
    const outputPixels = outputImageData.data;

    const PI2 = Math.PI * 2;

    for (let y = 0; y < height; y++) {
        for (let x = 0; x < width; x++) {
            let displacementX = 0; // Displacement for the current pixel's source X
            let displacementY = 0; // Displacement for the current pixel's source Y
            let waveFunctionValue;

            if (direction === "horizontal") {
                // Waves run horizontally (along the x-axis).
                // Pixel displacement is vertical (affects the y-coordinate of the source pixel).
                const normalizedPosition = x / width; // Position along the wave, normalized (0 to 1)
                const angle = normalizedPosition * numWaves * PI2 + phase;

                if (waveType === "cosine") {
                    waveFunctionValue = Math.cos(angle);
                } else { // Default to "sine" if waveType is misspelled or not "cosine"
                    waveFunctionValue = Math.sin(angle);
                }
                displacementY = amplitude * waveFunctionValue;
            } else if (direction === "vertical") {
                // Waves run vertically (along the y-axis).
                // Pixel displacement is horizontal (affects the x-coordinate of the source pixel).
                const normalizedPosition = y / height; // Position along the wave, normalized (0 to 1)
                const angle = normalizedPosition * numWaves * PI2 + phase;

                if (waveType === "cosine") {
                    waveFunctionValue = Math.cos(angle);
                } else { // Default to "sine"
                    waveFunctionValue = Math.sin(angle);
                }
                displacementX = amplitude * waveFunctionValue;
            }
            // If direction is neither "horizontal" nor "vertical", there's no displacement.

            // Calculate the source pixel coordinates based on displacement.
            // Math.round is used for nearest-neighbor sampling.
            const sourceX = Math.round(x + displacementX);
            const sourceY = Math.round(y + displacementY);

            // Clamp source coordinates to be within the image boundaries.
            // This handles pixels displaced off-image by sampling the edge pixels.
            const clampedSourceX = Math.max(0, Math.min(width - 1, sourceX));
            const clampedSourceY = Math.max(0, Math.min(height - 1, sourceY));

            // Calculate array indices for source and destination pixels.
            // Each pixel occupies 4 array elements (R, G, B, A).
            const sourceIndex = (clampedSourceY * width + clampedSourceX) * 4;
            const destIndex = (y * width + x) * 4;

            // Copy pixel data from source to destination.
            outputPixels[destIndex]     = originalPixels[sourceIndex];     // Red
            outputPixels[destIndex + 1] = originalPixels[sourceIndex + 1]; // Green
            outputPixels[destIndex + 2] = originalPixels[sourceIndex + 2]; // Blue
            outputPixels[destIndex + 3] = originalPixels[sourceIndex + 3]; // Alpha
        }
    }

    // Draw the modified pixel data onto the output 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 Sound Wave Filter Effect Tool allows users to apply a unique sound wave effect to images, creating visually appealing distortions based on amplitude and wave parameters. Users can customize the effect by adjusting the wave’s amplitude, the number of waves, the phase shift, and the direction (horizontal or vertical) of the wave. This tool is ideal for graphic designers, artists, and content creators looking to add dynamic wave effects to their images for artistic presentations, social media posts, or digital art projects.

Leave a Reply

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