Please bookmark this page to avoid losing your image tool!

Image Pendulum Swing 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, swingAmount = 30, pivotYRatio = 0) {
    const canvas = document.createElement('canvas');
    // Using { willReadFrequently: true } is an optimization hint for the browser.
    const ctx = canvas.getContext('2d', { willReadFrequently: true });

    const width = originalImg.naturalWidth || originalImg.width;
    const height = originalImg.naturalHeight || originalImg.height;

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

    // Draw the original image onto the canvas. 
    // This canvas will be returned if processing is skipped or fails.
    ctx.drawImage(originalImg, 0, 0, width, height);

    // If swingAmount is 0, no effect is applied.
    if (swingAmount === 0) {
        return canvas;
    }

    // If image has no dimensions, no processing can be done.
    if (width === 0 || height === 0) {
        return canvas;
    }
    
    let sourceImageData;
    try {
        sourceImageData = ctx.getImageData(0, 0, width, height);
    } catch (e) {
        // This can happen if the image is cross-origin and the canvas becomes tainted.
        console.error("Could not get image data, possibly due to cross-origin restrictions. Returning original image.", e);
        return canvas; 
    }

    const sourceData = sourceImageData.data;
    // Create a new ImageData object for the output.
    const outputImageData = ctx.createImageData(width, height);
    const outputData = outputImageData.data;
    
    // Calculate the actual Y coordinate of the pivot line.
    // The pivot calculation is based on indices from 0 to height-1 for a 0-indexed image array.
    const actualHeightForPivotCalc = height > 1 ? height - 1 : 0;
    const pivotActualY = pivotYRatio * actualHeightForPivotCalc;

    // Determine the maximum distance from the pivot line to any horizontal line in the image.
    // This is used to normalize the swing effect, ensuring the part of the image furthest
    // from the pivot swings by the full 'swingAmount'.
    let maxDistFromPivot;
    if (height <= 1) {
        // If image is 1 pixel high (or less), there's no vertical extent for the swing influence to vary.
        maxDistFromPivot = 0; 
    } else {
        // Distance from the pivot line to the top edge of the image (y=0)
        const distToTopEdge = Math.abs(0 - pivotActualY);
        // Distance from the pivot line to the bottom edge of the image (y=height-1)
        const distToBottomEdge = Math.abs((height - 1) - pivotActualY);
        maxDistFromPivot = Math.max(distToTopEdge, distToBottomEdge);
        
        // If maxDistFromPivot is 0 at this point (e.g. height=1 and pivotActualY=0),
        // no swing effect will be applied as dx will remain 0. This is correct.
        // For height > 1, maxDistFromPivot should generally be > 0.
    }

    for (let y = 0; y < height; y++) {
        let dx = 0; // Horizontal shift for this row

        if (maxDistFromPivot > 0) {
            // Calculate how far the current row 'y' is from the pivot line (signed).
            const displacementFactor = y - pivotActualY; 
            // Normalize this displacement: rows at maxDistFromPivot will have a normalizedDisplacement of 1 or -1.
            const normalizedDisplacement = displacementFactor / maxDistFromPivot;
            dx = swingAmount * normalizedDisplacement;
        }
        // If maxDistFromPivot is 0 (e.g., for a 1px high image, or if pivot setup results in no relative movement), dx remains 0.

        for (let x = 0; x < width; x++) {
            const targetPixelStartIndex = (y * width + x) * 4;

            // Determine the x-coordinate in the source image to fetch the pixel from.
            // A positive dx signifies that content at this y-level effectively moves to the right.
            // So, the pixel at the destination (x, y) should get its color from (x - dx, y) in the source.
            let sourceX = x - dx;
            
            // Round to the nearest pixel index and clamp to image boundaries.
            sourceX = Math.round(sourceX);
            sourceX = Math.max(0, Math.min(width - 1, sourceX));
            
            const sourcePixelStartIndex = (y * width + sourceX) * 4;

            // Copy pixel data (R, G, B, A)
            outputData[targetPixelStartIndex]     = sourceData[sourcePixelStartIndex];
            outputData[targetPixelStartIndex + 1] = sourceData[sourcePixelStartIndex + 1];
            outputData[targetPixelStartIndex + 2] = sourceData[sourcePixelStartIndex + 2];
            outputData[targetPixelStartIndex + 3] = sourceData[sourcePixelStartIndex + 3];
        }
    }

    // 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 Pendulum Swing Filter Effect Tool allows users to apply a unique pendulum swing effect to images. By adjusting the swing amount and pivot point, users can create visually engaging oscillating shifts in the image’s horizontal positioning, simulating a swinging motion. This tool can be used for enhancing graphics for presentations, adding dynamic visuals to social media posts, or creating artistic effects for digital artwork, providing a creative way to manipulate images for various aesthetic purposes.

Leave a Reply

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