Please bookmark this page to avoid losing your image tool!

Image Warp 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, angle = 90, radiusFactor = 0.5, centerX = 0.5, centerY = 0.5) {
    const width = originalImg.width;
    const height = originalImg.height;

    if (width === 0 || height === 0) {
        // Handle empty or not-yet-loaded image by returning an empty canvas
        const canvas = document.createElement('canvas');
        canvas.width = 0;
        canvas.height = 0;
        return canvas;
    }

    // Create a source canvas to get ImageData from the original image
    const sourceCanvas = document.createElement('canvas');
    sourceCanvas.width = width;
    sourceCanvas.height = height;
    const sourceCtx = sourceCanvas.getContext('2d', { willReadFrequently: true });
    sourceCtx.drawImage(originalImg, 0, 0, width, height);
    let sourceImageData;
    try {
        sourceImageData = sourceCtx.getImageData(0, 0, width, height);
    } catch (e) {
        // Handle potential security errors if image is cross-origin and canvas becomes tainted
        console.error("Error getting ImageData: ", e);
        // Fallback: return a copy of the original image drawn on a new canvas
        const fallbackCanvas = document.createElement('canvas');
        fallbackCanvas.width = width;
        fallbackCanvas.height = height;
        const fallbackCtx = fallbackCanvas.getContext('2d');
        fallbackCtx.drawImage(originalImg, 0, 0, width, height);
        return fallbackCanvas;
    }
    const sourceData = sourceImageData.data;

    // Create an output canvas for the warped image
    const outputCanvas = document.createElement('canvas');
    outputCanvas.width = width;
    outputCanvas.height = height;
    const outputCtx = outputCanvas.getContext('2d', { willReadFrequently: true });
    const outputImageData = outputCtx.createImageData(width, height);
    const outputData = outputImageData.data;

    const actualCenterX = width * centerX;
    const actualCenterY = height * centerY;
    
    // Calculate the actual radius in pixels.
    // Uses Math.min(width, height) so the factor scales consistently regardless of aspect ratio.
    const actualRadius = Math.min(width, height) * radiusFactor;
    
    const angleRad = angle * Math.PI / 180;

    // If radius is effectively zero, no warp occurs.
    // Draw the original image to the output canvas and return.
    if (actualRadius <= 0) {
        outputCtx.drawImage(originalImg, 0, 0, width, height);
        return outputCanvas;
    }

    for (let y = 0; y < height; y++) {
        for (let x = 0; x < width; x++) {
            const dx = x - actualCenterX; // Distance from current pixel to center X
            const dy = y - actualCenterY; // Distance from current pixel to center Y
            const distance = Math.sqrt(dx * dx + dy * dy);

            let srcX = x;
            let srcY = y;

            if (distance < actualRadius) {
                // Current angle of the pixel relative to the center
                const currentPixelAngle = Math.atan2(dy, dx);
                
                // Twirl strength fades linearly from center to radius edge
                // Strength = 1 at center (distance = 0), 0 at edge (distance = actualRadius)
                const twirlEffectStrength = 1 - (distance / actualRadius);
                
                // Apply the twirl: add scaled angle to the current pixel's angle
                const rotatedAngle = currentPixelAngle + angleRad * twirlEffectStrength;

                // Convert polar coordinates (rotatedAngle, distance) back to Cartesian for source pixel
                srcX = actualCenterX + distance * Math.cos(rotatedAngle);
                srcY = actualCenterY + distance * Math.sin(rotatedAngle);
            }
            // If distance >= actualRadius, srcX and srcY remain x and y (no twirl)

            // Round source coordinates to nearest integer
            const iSrcX = Math.round(srcX);
            const iSrcY = Math.round(srcY);

            // Clamp source coordinates to be within image bounds
            const clampedSrcX = Math.max(0, Math.min(width - 1, iSrcX));
            const clampedSrcY = Math.max(0, Math.min(height - 1, iSrcY));

            const srcIndex = (clampedSrcY * width + clampedSrcX) * 4;
            const destIndex = (y * width + x) * 4;

            // Copy RGBA components from source pixel to destination pixel
            outputData[destIndex    ] = sourceData[srcIndex    ]; // R
            outputData[destIndex + 1] = sourceData[srcIndex + 1]; // G
            outputData[destIndex + 2] = sourceData[srcIndex + 2]; // B
            outputData[destIndex + 3] = sourceData[srcIndex + 3]; // A
        }
    }

    outputCtx.putImageData(outputImageData, 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 Warp Filter tool allows users to apply a twirl effect to images, creating a warped appearance based on a specified rotation angle and radius factor. Users can adjust the center point of the warp as well, providing flexibility in how the distortion is applied. This tool can be used for creative graphic design, enhancing images for artistic purposes, or adding visual interest to photographs by generating unique styles or effects.

Leave a Reply

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