Please bookmark this page to avoid losing your image tool!

Ice Cream Swirl Photo Filter 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.
function processImage(originalImg, centerXPercent = 50, centerYPercent = 50, radiusPercent = 100, strength = 50) {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d', { willReadFrequently: true }); // Hint for optimization if getImageData is frequent

    const width = originalImg.naturalWidth || originalImg.width;
    const height = originalImg.naturalHeight || originalImg.height;
    
    if (width === 0 || height === 0) {
        // Handle zero-size image case: return an empty (0x0) canvas
        canvas.width = 0;
        canvas.height = 0;
        return canvas;
    }

    canvas.width = width;
    canvas.height = height;

    // Draw the original image onto the canvas. This will be our source.
    ctx.drawImage(originalImg, 0, 0, width, height);
    
    // Define swirl parameters
    const maxAngle = strength / 10.0; // Max rotation angle in radians. E.g., strength 50 -> 5 radians.
    
    // Calculate radius in pixels. 100% radiusPercent means radius is min(width, height) / 2.0.
    const baseRadiusForPercent = Math.min(width, height) / 2.0;
    const maxRadius = baseRadiusForPercent * (radiusPercent / 100.0);

    // If there's no effective swirl (zero radius or zero strength),
    // the original image is already on the canvas, so return it.
    if (maxRadius <= 0 || maxAngle === 0) {
        return canvas;
    }
    
    const sourceImageData = ctx.getImageData(0, 0, width, height);
    const sourceData = sourceImageData.data;
    
    // Create a new ImageData for the output. This is crucial because we are sampling
    // from the source for each destination pixel. Modifying sourceImageData in place would lead to incorrect results.
    const outputImageData = ctx.createImageData(width, height);
    const outputData = outputImageData.data;

    const actualCenterX = width * (centerXPercent / 100.0);
    const actualCenterY = height * (centerYPercent / 100.0);

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

            let srcX = x; // Default to original pixel (identity transform)
            let srcY = y;

            if (distance < maxRadius) {
                const originalAngle = Math.atan2(dy, dx); // Angle of the pixel relative to center
                
                // Swirl factor determines how much the pixel is affected by the swirl.
                // It's 1 at the center (distance=0) and 0 at maxRadius.
                // This creates a linear falloff of the swirl effect.
                const swirlFactor = (maxRadius - distance) / maxRadius;
                
                const effectiveAngle = maxAngle * swirlFactor; // Actual rotation for this pixel
                const newAngle = originalAngle + effectiveAngle; // New angle after rotation

                // Convert polar coordinates (newAngle, distance) back to Cartesian for source pixel
                srcX = actualCenterX + distance * Math.cos(newAngle);
                srcY = actualCenterY + distance * Math.sin(newAngle);
            }

            // Bilinear interpolation to get pixel color from (srcX, srcY)
            // Clamp source coordinates to be within image bounds
            const clampedSrcX = Math.max(0, Math.min(width - 1, srcX));
            const clampedSrcY = Math.max(0, Math.min(height - 1, srcY));

            const x1 = Math.floor(clampedSrcX);
            const y1 = Math.floor(clampedSrcY);
            
            // Ensure x2 and y2 are also within bounds for interpolation
            const x2 = Math.min(width - 1, x1 + 1);
            const y2 = Math.min(height - 1, y1 + 1);

            const fx = clampedSrcX - x1; // Fractional part of x
            const fy = clampedSrcY - y1; // Fractional part of y
            const invFx = 1 - fx;
            const invFy = 1 - fy;

            const destIdx = (y * width + x) * 4; // Index for the destination pixel in outputData

            // Indices for the four neighboring pixels in sourceData
            const idx11 = (y1 * width + x1) * 4; // Top-left
            const idx21 = (y1 * width + x2) * 4; // Top-right
            const idx12 = (y2 * width + x1) * 4; // Bottom-left
            const idx22 = (y2 * width + x2) * 4; // Bottom-right

            // Interpolate R, G, B, A channels
            for (let c = 0; c < 4; c++) { 
                const p11 = sourceData[idx11 + c];
                const p21 = sourceData[idx21 + c];
                const p12 = sourceData[idx12 + c];
                const p22 = sourceData[idx22 + c];

                const interpolatedValue = 
                    p11 * invFx * invFy + 
                    p21 * fx * invFy +
                    p12 * invFx * fy +
                    p22 * fx * fy;
                
                outputData[destIdx + c] = Math.round(interpolatedValue);
            }
        }
    }

    // Put the modified pixel data back onto the canvas
    ctx.putImageData(outputImageData, 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 Ice Cream Swirl Photo Filter Effect Tool allows users to apply a swirling effect to their images, creating a visually appealing distortion that swirls around a defined center point. Users can adjust parameters such as the center of the swirl, the radius of the effect, and the strength of the swirl. This tool can be particularly useful for enhancing photographs for social media, creating unique artistic effects, or adding a fun twist to images for personal projects.

Leave a Reply

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