Please bookmark this page to avoid losing your image tool!

Image Kinetic Art 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 = 10, period = 50, direction = 'vertical') {
    let w = originalImg.naturalWidth || originalImg.width;
    let h = originalImg.naturalHeight || originalImg.height;

    // Ensure w and h are valid numbers, defaulting to a small canvas size if not.
    // This helps prevent errors if the image object is faulty or not fully loaded.
    w = Number(w) || 100; // Default width if w is NaN, undefined, or 0
    h = Number(h) || 100; // Default height if h is NaN, undefined, or 0

    const outputCanvas = document.createElement('canvas');
    outputCanvas.width = w;
    outputCanvas.height = h;
    const outputCtx = outputCanvas.getContext('2d');

    // Create a temporary canvas to get image data
    const tempCanvas = document.createElement('canvas');
    tempCanvas.width = w;
    tempCanvas.height = h;
    // Use { willReadFrequently: true } for potential performance optimization when using getImageData repeatedly.
    const tempCtx = tempCanvas.getContext('2d', { willReadFrequently: true });
    
    try {
        tempCtx.drawImage(originalImg, 0, 0, w, h);
    } catch (e) {
        console.error("Error drawing original image to temporary canvas:", e);
        // Display an error message on the canvas
        outputCtx.fillStyle = 'rgba(200,200,200,1)'; // Light gray background
        outputCtx.fillRect(0,0,w,h);
        outputCtx.fillStyle = 'red';
        outputCtx.font = '14px Arial';
        outputCtx.textAlign = 'center';
        outputCtx.textBaseline = 'middle';
        outputCtx.fillText('Error: Could not load image.', w/2, h/2);
        return outputCanvas; // Return canvas with error message
    }

    let originalImgData;
    try {
        originalImgData = tempCtx.getImageData(0, 0, w, h);
    } catch (e) {
        console.error("Error getting image data (possibly cross-origin):", e);
        // If getImageData fails (e.g. cross-origin), draw the original image as a fallback
        // and display a warning message on top.
        outputCtx.drawImage(originalImg, 0, 0, w, h); 
        
        outputCtx.fillStyle = 'rgba(255, 0, 0, 0.6)'; // Semi-transparent red overlay
        outputCtx.fillRect(0, 0, w, h);
        
        outputCtx.fillStyle = 'white';
        outputCtx.font = 'bold 16px Arial';
        outputCtx.textAlign = 'center';
        outputCtx.textBaseline = 'middle';
        
        const messages = ['Kinetic effect cannot be applied.', '(Cross-origin restrictions or image error)'];
        const lineHeight = 20;
        const startY = h/2 - (messages.length - 1) * lineHeight / 2;

        for(let i = 0; i < messages.length; i++) {
            outputCtx.fillText(messages[i], w/2, startY + i * lineHeight);
        }
        return outputCanvas;
    }
    
    const outputImgData = outputCtx.createImageData(w, h);

    const origPixels = originalImgData.data;
    const outPixels = outputImgData.data;

    const numAmplitude = Number(amplitude);
    const numPeriod = Number(period);

    if (w === 0 || h === 0) {
        // If image has zero dimension, there's nothing to process.
        // The output canvas will be blank and correctly sized.
        console.warn("Image has zero width or height. Returning blank canvas.");
        return outputCanvas;
    }

    if (direction === 'vertical') {
        for (let x = 0; x < w; x++) { // Iterate through destination columns
            const angle = (numPeriod === 0) ? 0 : (x * 2 * Math.PI / numPeriod);
            const yShift = (numPeriod === 0) ? 0 : Math.sin(angle) * numAmplitude;

            for (let y = 0; y < h; y++) { // Iterate through destination rows
                // For canvas pixel (x,y), find source pixel (x, srcY)
                const srcY = Math.round(y - yShift);

                // Clamp srcY to be within image boundaries
                let clampedSrcY = srcY;
                if (clampedSrcY < 0) clampedSrcY = 0;
                if (clampedSrcY >= h) clampedSrcY = h - 1;
                
                const destIdx = (y * w + x) * 4;
                const srcIdx = (clampedSrcY * w + x) * 4;

                outPixels[destIdx]     = origPixels[srcIdx];     // R
                outPixels[destIdx + 1] = origPixels[srcIdx + 1]; // G
                outPixels[destIdx + 2] = origPixels[srcIdx + 2]; // B
                outPixels[destIdx + 3] = origPixels[srcIdx + 3]; // A
            }
        }
    } else if (direction === 'horizontal') {
        for (let y = 0; y < h; y++) { // Iterate through destination rows
            const angle = (numPeriod === 0) ? 0 : (y * 2 * Math.PI / numPeriod);
            const xShift = (numPeriod === 0) ? 0 : Math.sin(angle) * numAmplitude;

            for (let x = 0; x < w; x++) { // Iterate through destination columns
                // For canvas pixel (x,y), find source pixel (srcX, y)
                const srcX = Math.round(x - xShift);

                // Clamp srcX to be within image boundaries
                let clampedSrcX = srcX;
                if (clampedSrcX < 0) clampedSrcX = 0;
                if (clampedSrcX >= w) clampedSrcX = w - 1;

                const destIdx = (y * w + x) * 4;
                const srcIdx = (y * w + clampedSrcX) * 4;

                outPixels[destIdx]     = origPixels[srcIdx];     // R
                outPixels[destIdx + 1] = origPixels[srcIdx + 1]; // G
                outPixels[destIdx + 2] = origPixels[srcIdx + 2]; // B
                outPixels[destIdx + 3] = origPixels[srcIdx + 3]; // A
            }
        }
    } else {
        // Invalid direction, just copy image to output canvas
        console.warn(`Invalid direction: "${direction}". Copying original image.`);
        outputCtx.drawImage(originalImg, 0, 0, w, h);
        return outputCanvas;
    }

    outputCtx.putImageData(outputImgData, 0, 0);
    return outputCanvas;
}

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 Kinetic Art Filter Effect Tool allows users to apply a dynamic wave effect to images, creating a visually engaging kinetic art style. By manipulating the amplitude and period of the wave, users can customize the direction of the effect, whether vertical or horizontal. This tool is ideal for artists, graphic designers, and social media enthusiasts who want to add a unique artistic flair to their images for digital art projects, social media posts, or marketing materials.

Leave a Reply

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