Please bookmark this page to avoid losing your image tool!

Image Lens Distortion Filter 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, strength = 0.2, centerX = 0.5, centerY = 0.5) {
    const width = originalImg.width;
    const height = originalImg.height;

    // If image is empty, return a blank canvas
    if (width === 0 || height === 0) {
        const emptyCanvas = document.createElement('canvas');
        emptyCanvas.width = width;
        emptyCanvas.height = height;
        console.warn("Image Lens Distortion: Input image has zero width or height.");
        return emptyCanvas;
    }

    // Create source canvas to get imageData
    const srcCanvas = document.createElement('canvas');
    srcCanvas.width = width;
    srcCanvas.height = height;
    const srcCtx = srcCanvas.getContext('2d', { willReadFrequently: true });
    srcCtx.drawImage(originalImg, 0, 0);
    const srcImageData = srcCtx.getImageData(0, 0, width, height);

    // Create output canvas
    const dstCanvas = document.createElement('canvas');
    dstCanvas.width = width;
    dstCanvas.height = height;
    const dstCtx = dstCanvas.getContext('2d');
    const dstImageData = dstCtx.createImageData(width, height);
    const dstData = dstImageData.data;

    const absCenterX = centerX * width;
    const absCenterY = centerY * height;

    // Define a sensible radius for normalization. Typically, distance from image center to a corner.
    // This ensures that rNormSq is roughly 1.0 at corners if the lens center is the image center.
    const normRadius = Math.sqrt(Math.pow(width / 2, 2) + Math.pow(height / 2, 2));
    
    // K_DIVISOR is normRadius squared. If normRadius is 0, set to 1 to avoid DivByZero.
    const K_DIVISOR = (normRadius === 0) ? 1.0 : normRadius * normRadius;
    const invKDivisor = (K_DIVISOR === 0) ? 1.0 : 1.0 / K_DIVISOR; // Precompute for performance

    // Helper function to get a single pixel's color array [R,G,B,A] from imageData
    // Clamps coordinates to be within image bounds. x, y are expected to be integers.
    function getPixel(imgDataObj, x, y, w, h) {
        const clampedX = Math.max(0, Math.min(x, w - 1));
        const clampedY = Math.max(0, Math.min(y, h - 1));
        const i = (clampedY * w + clampedX) * 4;
        return [
            imgDataObj.data[i],
            imgDataObj.data[i + 1],
            imgDataObj.data[i + 2],
            imgDataObj.data[i + 3],
        ];
    }
    
    // Helper function for bilinear interpolation. x, y are float coordinates.
    function getPixelBilinear(imgDataObj, x, y, w, h) {
        const x1 = Math.floor(x);
        const y1 = Math.floor(y);
        
        const fx = x - x1; // fractional part of x
        const fy = y - y1; // fractional part of y
        const invFx = 1 - fx;
        const invFy = 1 - fy;

        // Coordinates for the four surrounding pixels
        const p11 = getPixel(imgDataObj, x1, y1, w, h);         // top-left
        const p21 = getPixel(imgDataObj, x1 + 1, y1, w, h);     // top-right
        const p12 = getPixel(imgDataObj, x1, y1 + 1, w, h);     // bottom-left
        const p22 = getPixel(imgDataObj, x1 + 1, y1 + 1, w, h); // bottom-right

        // Interpolate R, G, B, A channels
        const R = (p11[0] * invFx + p21[0] * fx) * invFy + (p12[0] * invFx + p22[0] * fx) * fy;
        const G = (p11[1] * invFx + p21[1] * fx) * invFy + (p12[1] * invFx + p22[1] * fx) * fy;
        const B = (p11[2] * invFx + p21[2] * fx) * invFy + (p12[2] * invFx + p22[2] * fx) * fy;
        const A = (p11[3] * invFx + p21[3] * fx) * invFy + (p12[3] * invFx + p22[3] * fx) * fy;
        
        return [R, G, B, A];
    }

    // If strength is effectively zero, copy image directly for performance
    if (Math.abs(strength) < 1e-5) { 
        dstCtx.putImageData(srcImageData, 0, 0);
        return dstCanvas;
    }

    for (let j = 0; j < height; j++) { // y-coordinate / row
        for (let i = 0; i < width; i++) { // x-coordinate / col
            const dx = i - absCenterX; // distance from distortion center X
            const dy = j - absCenterY; // distance from distortion center Y
            const distSq = dx * dx + dy * dy; // squared distance

            const rNormSq = distSq * invKDivisor; // normalized squared radius from center
            const distortionFactor = 1.0 + strength * rNormSq;

            let R = 0, G = 0, B = 0, A = 0; // Default to transparent black for problematic cases

            // If distortionFactor is near zero, it creates a singularity.
            // Pixels at this radius would be mapped to/from infinity.
            if (Math.abs(distortionFactor) < 1e-5) {
                // Set to transparent black (already default) or another indicator color.
            } else {
                const srcX = absCenterX + dx / distortionFactor;
                const srcY = absCenterY + dy / distortionFactor;
                
                // Check if computed source coordinates are finite.
                // If distortionFactor was extremely small (but not zero), srcX/Y could be Infinity.
                if (isFinite(srcX) && isFinite(srcY)) {
                    // Perform bilinear interpolation to get source pixel color
                    [R, G, B, A] = getPixelBilinear(srcImageData, srcX, srcY, width, height);
                } 
                // else: R,G,B,A remain transparent black if srcX/Y are Inf/NaN
            }
            
            const dstIndex = (j * width + i) * 4;
            dstData[dstIndex]     = R;
            dstData[dstIndex + 1] = G;
            dstData[dstIndex + 2] = B;
            dstData[dstIndex + 3] = A;
        }
    }

    dstCtx.putImageData(dstImageData, 0, 0);
    return dstCanvas;
}

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 Lens Distortion Filter Tool allows users to apply a lens distortion effect to images. By adjusting parameters such as distortion strength and focal point, users can creatively manipulate their images to achieve various visual effects. This tool is useful for graphic designers and photographers looking to add unique distortions for artistic purposes, enhance visual storytelling, or create eye-catching images for social media and online content.

Leave a Reply

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