Please bookmark this page to avoid losing your image tool!

Image Pinch And Bulge 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.
async function processImage(originalImg, strength = 0.5, centerX = 0.5, centerY = 0.5, radius = 0.5) {
    const canvas = document.createElement('canvas');
    // Using { willReadFrequently: true } can improve performance on some browsers when using getImageData
    const ctx = canvas.getContext('2d', { willReadFrequently: true });
    const width = originalImg.naturalWidth;
    const height = originalImg.naturalHeight;
    canvas.width = width;
    canvas.height = height;

    // Draw the original image to the canvas to access its pixel data
    ctx.drawImage(originalImg, 0, 0, width, height);
    const sourceData = ctx.getImageData(0, 0, width, height);
    const sourcePixels = sourceData.data;

    // Create a new ImageData object to hold the distorted image
    const destData = ctx.createImageData(width, height);
    const destPixels = destData.data;

    // Convert normalized parameters to pixel coordinates
    const pxCenterX = centerX * width;
    const pxCenterY = centerY * height;
    // Base the radius on the smaller dimension to keep the effect circular
    const pxRadius = radius * Math.min(width, height);

    // If radius is 0, there's no effect to apply
    if (pxRadius === 0) {
        ctx.putImageData(sourceData, 0, 0);
        return canvas;
    }
    
    const pxRadiusSq = pxRadius * pxRadius;

    // Map the strength parameter (-1 to 1) to a power curve for a smoother, more controllable effect.
    // A strength > 0 creates a bulge (power > 1).
    // A strength < 0 creates a pinch (0 < power < 1).
    // A strength of 0 has no effect (power = 1).
    const power = Math.pow(2, strength);

    // Iterate over each destination pixel to determine which source pixel to sample
    for (let y = 0; y < height; y++) {
        for (let x = 0; x < width; x++) {
            const destIndex = (y * width + x) * 4;

            // Calculate the vector from the current pixel to the center of the effect
            const dx = x - pxCenterX;
            const dy = y - pxCenterY;
            const distanceSq = dx * dx + dy * dy;
            
            let sourceX = x;
            let sourceY = y;

            // Apply the effect only to pixels within the specified radius
            if (distanceSq < pxRadiusSq) {
                const distance = Math.sqrt(distanceSq);
                const angle = Math.atan2(dy, dx);

                // The core of the distortion effect: we map the destination distance to a source distance.
                // This is an inverse mapping, calculating where each destination pixel comes *from*.
                const sourceDistance = Math.pow(distance / pxRadius, power) * pxRadius;

                // Convert the polar coordinates (angle, sourceDistance) back to Cartesian coordinates
                sourceX = pxCenterX + sourceDistance * Math.cos(angle);
                sourceY = pxCenterY + sourceDistance * Math.sin(angle);
            }
            
            // Use nearest-neighbor interpolation to find the source pixel color
            const isx = Math.round(sourceX);
            const isy = Math.round(sourceY);

            // Check if the calculated source coordinates are within the image bounds
            if (isx >= 0 && isx < width && isy >= 0 && isy < height) {
                const sourceIndex = (isy * width + isx) * 4;
                destPixels[destIndex]     = sourcePixels[sourceIndex];
                destPixels[destIndex + 1] = sourcePixels[sourceIndex + 1];
                destPixels[destIndex + 2] = sourcePixels[sourceIndex + 2];
                destPixels[destIndex + 3] = sourcePixels[sourceIndex + 3];
            } else {
                // Pixels from outside the source image (can happen with strong pinches) are made transparent
                destPixels[destIndex + 3] = 0;
            }
        }
    }

    // Put the modified pixel data back onto the canvas
    ctx.putImageData(destData, 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 Pinch and Bulge Effect Tool allows users to apply interactive visual distortions to images, creating either a pinch or bulge effect. This tool can manipulate image pixels based on specified parameters such as effect strength, center, and radius, enabling customized artistic adjustments. It is ideal for artists, designers, and hobbyists who wish to create unique visual effects for photos, artworks, or graphic designs. Use cases include enhancing social media content, creating eye-catching graphics, or simply experimenting with creative image presentations.

Leave a Reply

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