Please bookmark this page to avoid losing your image tool!

Distorted Face Image Effect Generator

(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, effect = "bulge", intensity = "50", radius = "50", centerX = "50", centerY = "50") {
    const W = originalImg.naturalWidth || originalImg.width;
    const H = originalImg.naturalHeight || originalImg.height;

    const canvas = document.createElement('canvas');
    if (!W || !H) return canvas;

    canvas.width = W;
    canvas.height = H;
    const ctx = canvas.getContext('2d');
    ctx.drawImage(originalImg, 0, 0);

    let srcData;
    try {
        srcData = ctx.getImageData(0, 0, W, H);
    } catch (e) {
        console.error("Failed to get image data. Ensure the image has correct cross-origin settings.", e);
        return canvas;
    }
    
    const dstData = ctx.createImageData(W, H);
    
    // Parameter parsing logic securely accommodating strings and numbers
    const parseNum = (val, def) => {
        const n = parseFloat(val);
        return isNaN(n) ? def : n;
    };
    
    const effStr = String(effect).toLowerCase();
    const intVal = Math.max(-100, Math.min(100, parseNum(intensity, 50))) / 100;
    const rPct = Math.max(0, parseNum(radius, 50)) / 100;
    const cxPct = parseNum(centerX, 50) / 100;
    const cyPct = parseNum(centerY, 50) / 100;

    const cx = W * cxPct;
    const cy = H * cyPct;
    const R = Math.min(W, H) * rPct;

    // Precalculate maximum distortion parameters based on effect type
    let S = 0;
    if (effStr === 'bulge') {
        // Sample closer to center for magnification (-0.8 represents max reasonable distortion)
        S = -0.8 * intVal;
    } else if (effStr === 'pinch') {
        // Sample further from center for shrinking
        S = 1.5 * intVal;
    }
    
    const swirlMaxObj = intVal * Math.PI * 2;
    const waveAmnt = intVal * (Math.min(W, H) * 0.05); // Max 5% of bounding area
    const wavePeriod = R / 4 || 1;

    // Apply distortion pixel calculation efficiently with bilinear interpolation
    for (let y = 0; y < H; y++) {
        for (let x = 0; x < W; x++) {
            const dx = x - cx;
            const dy = y - cy;
            const r = Math.sqrt(dx * dx + dy * dy);
            
            if (r <= R && R > 0) {
                let sx = x;
                let sy = y;
                
                // Cosine easing creates completely smooth distortion that flawlessly merges with the unaffected boundary
                const distEase = (Math.cos(Math.PI * r / R) + 1) / 2;
                
                if (effStr === 'bulge' || effStr === 'pinch') {
                    const factor = 1 + S * distEase;
                    sx = cx + dx * factor;
                    sy = cy + dy * factor;
                } else if (effStr === 'swirl') {
                    const theta = Math.atan2(dy, dx);
                    const theta_src = theta + swirlMaxObj * distEase;
                    sx = cx + r * Math.cos(theta_src);
                    sy = cy + r * Math.sin(theta_src);
                } else if (effStr === 'wavy') {
                    sx = x + waveAmnt * Math.sin(y / wavePeriod * Math.PI * 2) * distEase;
                    sy = y + waveAmnt * Math.cos(x / wavePeriod * Math.PI * 2) * distEase;
                }

                // Protect boundaries and prepare variables for bilinear interpolation
                sx = Math.max(0, Math.min(W - 1, sx));
                sy = Math.max(0, Math.min(H - 1, sy));

                const x1 = sx | 0; // bitwise floor
                const x2 = Math.min(W - 1, x1 + 1);
                const y1 = sy | 0;
                const y2 = Math.min(H - 1, y1 + 1);

                const x_frac = sx - x1;
                const y_frac = sy - y1;

                const w1 = (1 - x_frac) * (1 - y_frac);
                const w2 = x_frac * (1 - y_frac);
                const w3 = (1 - x_frac) * y_frac;
                const w4 = x_frac * y_frac;

                const dstIdx = (y * W + x) * 4;
                const i1 = (y1 * W + x1) * 4;
                const i2 = (y1 * W + x2) * 4;
                const i3 = (y2 * W + x1) * 4;
                const i4 = (y2 * W + x2) * 4;

                // Write pixel values utilizing channel weights
                dstData.data[dstIdx] = srcData.data[i1] * w1 + srcData.data[i2] * w2 + srcData.data[i3] * w3 + srcData.data[i4] * w4;
                dstData.data[dstIdx + 1] = srcData.data[i1 + 1] * w1 + srcData.data[i2 + 1] * w2 + srcData.data[i3 + 1] * w3 + srcData.data[i4 + 1] * w4;
                dstData.data[dstIdx + 2] = srcData.data[i1 + 2] * w1 + srcData.data[i2 + 2] * w2 + srcData.data[i3 + 2] * w3 + srcData.data[i4 + 2] * w4;
                dstData.data[dstIdx + 3] = srcData.data[i1 + 3] * w1 + srcData.data[i2 + 3] * w2 + srcData.data[i3 + 3] * w3 + srcData.data[i4 + 3] * w4;
            } else {
                // Speedy direct copy bypass for untouched areas to maximize generation performance
                const dstIdx = (y * W + x) * 4;
                dstData.data[dstIdx] = srcData.data[dstIdx];
                dstData.data[dstIdx + 1] = srcData.data[dstIdx + 1];
                dstData.data[dstIdx + 2] = srcData.data[dstIdx + 2];
                dstData.data[dstIdx + 3] = srcData.data[dstIdx + 3];
            }
        }
    }
    
    ctx.putImageData(dstData, 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 Distorted Face Image Effect Generator allows users to apply various fun and artistic distortion effects to their images. With customizable settings for intensity, radius, and center position, you can create effects such as bulging, pinching, swirling, or wavy distortions. This tool is ideal for creating humorous portraits, generating unique social media avatars, or adding creative artistic flourishes to digital photos.

Leave a Reply

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