Please bookmark this page to avoid losing your image tool!

Image Stadium View Filter Effect

(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) {
    const W = originalImg.width;
    const H = originalImg.height;

    const canvas = document.createElement('canvas');
    canvas.width = W;
    canvas.height = H;
    // The { willReadFrequently: true } hint can improve performance on some browsers for getImageData/putImageData operations.
    const ctx = canvas.getContext('2d', { willReadFrequently: true });

    // Draw the original image onto the canvas initially to access its pixel data.
    ctx.drawImage(originalImg, 0, 0, W, H);
    const srcImageData = ctx.getImageData(0, 0, W, H);
    const srcData = srcImageData.data;

    // Create a new ImageData object for the destination pixels.
    const destImageData = ctx.createImageData(W, H);
    const destData = destImageData.data;

    const centerX = W / 2;
    const centerY = H / 2;

    // Ensure strength is a number.
    strength = Number(strength);
    if (isNaN(strength)) {
        strength = 0.2; // Default strength if input is invalid
    }

    // Helper function to get a pixel (R,G,B,A) from image data.
    // Coordinates are floored and clamped to image boundaries.
    function getPixel(x_in, y_in, data, Dwidth, Dheight) {
        const x = Math.max(0, Math.min(Dwidth - 1, Math.floor(x_in)));
        const y = Math.max(0, Math.min(Dheight - 1, Math.floor(y_in)));
        const i = (y * Dwidth + x) * 4;
        return [data[i], data[i+1], data[i+2], data[i+3]];
    }
    
    // Helper function for bilinear interpolation.
    function getPixelBilinear(x, y, data, Dwidth, Dheight) {
        // Handle cases where x or y are exactly at the width/height boundary for correct fx, fy.
        const x_eff = (x >= Dwidth -1e-9) ? Dwidth - 1.000001 : Math.max(0,x) ; // Ensure x is within [0, Dwidth-epsilon)
        const y_eff = (y >= Dheight -1e-9) ? Dheight - 1.000001 : Math.max(0,y) ; // Ensure y is within [0, Dheight-epsilon)
        
        const x1 = Math.floor(x_eff);
        const y1 = Math.floor(y_eff);
        const x2 = x1 + 1;
        const y2 = y1 + 1;

        // Get the four neighboring pixels. getPixel handles boundary clamping.
        const P11 = getPixel(x1, y1, data, Dwidth, Dheight);
        const P21 = getPixel(x2, y1, data, Dwidth, Dheight);
        const P12 = getPixel(x1, y2, data, Dwidth, Dheight);
        const P22 = getPixel(x2, y2, data, Dwidth, Dheight);

        const fx = x_eff - x1; // Fractional part of x
        const fy = y_eff - y1; // Fractional part of y
        const fx1 = 1 - fx;
        const fy1 = 1 - fy;

        // Interpolate R, G, B, A channels
        const R = P11[0]*fx1*fy1 + P21[0]*fx*fy1 + P12[0]*fx1*fy + P22[0]*fx*fy;
        const G = P11[1]*fx1*fy1 + P21[1]*fx*fy1 + P12[1]*fx1*fy + P22[1]*fx*fy;
        const B = P11[2]*fx1*fy1 + P21[2]*fx*fy1 + P12[2]*fx1*fy + P22[2]*fx*fy;
        const A = P11[3]*fx1*fy1 + P21[3]*fx*fy1 + P12[3]*fx1*fy + P22[3]*fx*fy;
        
        return [R,G,B,A];
    }

    // Iterate over each pixel in the destination image.
    for (let j = 0; j < H; j++) { // Current row (y-coordinate)
        for (let i = 0; i < W; i++) { // Current column (x-coordinate)
            const destIdx = (j * W + i) * 4; // Index for the destination pixel array

            // Normalized coordinates relative to the center.
            // dx_norm, dy_norm range from -1 to 1.
            const dx_norm = (i - centerX) / centerX; 
            const dy_norm = (j - centerY) / centerY;
            
            // If W or H is 1, centerX or centerY would be 0.5. Division is fine.
            // No need to check for W/H=0 as Image objects have W,H >= 1.

            // 'Elliptical' squared radial distance from center.
            // r_sq_geom can be up to 2.0 at the corners (if dx_norm=1, dy_norm=1).
            const r_sq_geom = dx_norm * dx_norm + dy_norm * dy_norm;
            
            // Barrel distortion factor.
            // strength > 0: bulge out (barrel)
            // strength < 0: squeeze in (pincushion)
            // factor = 1 means no change in radius proportion.
            const factor = 1.0 - strength * r_sq_geom;

            // Calculate source normalized coordinates by scaling from the center.
            const src_dx_norm = dx_norm * factor;
            const src_dy_norm = dy_norm * factor;

            // Convert normalized source coordinates back to absolute pixel coordinates.
            // srcX = centerX + src_dx_norm * centerX = centerX * (1 + src_dx_norm)
            const srcX = centerX * (1 + src_dx_norm);
            const srcY = centerY * (1 + src_dy_norm);
            
            // Get the color from the source image using bilinear interpolation.
            // The srcX, srcY coordinates are guaranteed by the formula to be within
            // the logical bounds [0,W] and [0,H] for reasonable strength values.
            // getPixelBilinear and getPixel handle clamping for edge cases.
            const color = getPixelBilinear(srcX, srcY, srcData, W, H);
            
            destData[destIdx]     = color[0]; // R
            destData[destIdx + 1] = color[1]; // G
            destData[destIdx + 2] = color[2]; // B
            destData[destIdx + 3] = color[3]; // A
        }
    }

    // Put the modified pixel data back onto the canvas.
    ctx.putImageData(destImageData, 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 Stadium View Filter Effect tool applies a distortion effect to images, simulating a stadium view by bulging or squeezing the image based on a strength parameter. This tool can be used for enhancing photos, creating artistic effects for social media posts, or preparing images for promotional materials by giving them a dynamic, curved appearance. Adjusting the strength of the effect allows users to customize the intensity of the distortion to achieve their desired look.

Leave a Reply

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