Please bookmark this page to avoid losing your image tool!

Image Tornado 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, angleDegrees = 90, radiusRatio = 0.5, centerXRatio = 0.5, centerYRatio = 0.5) {
    const canvas = document.createElement('canvas');
    // Using { willReadFrequently: true } can be a performance hint for some browsers
    const ctx = canvas.getContext('2d', { willReadFrequently: true });

    const width = originalImg.naturalWidth || originalImg.width;
    const height = originalImg.naturalHeight || originalImg.height;

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

    // Handle cases where the image has zero dimensions
    if (width === 0 || height === 0) {
        return canvas; // Returns an empty canvas with correct (zero) dimensions
    }
    
    // Draw the original image onto the canvas. This will be the source for pixel manipulation.
    ctx.drawImage(originalImg, 0, 0, width, height);

    // If parameters effectively mean no visual change, return the canvas with the original image
    if (angleDegrees === 0 || radiusRatio <= 0) {
        return canvas; 
    }

    const imageData = ctx.getImageData(0, 0, width, height);
    const srcPixels = imageData.data;
    // Create a new pixel array for the destination image.
    // This is important to avoid modifying pixels that are later read in the same pass (read-before-write consistency).
    const destPixels = new Uint8ClampedArray(srcPixels.length);

    // Convert the twist angle from degrees to radians for Math functions
    const maxTwistAngleRad = angleDegrees * (Math.PI / 180);
    
    // Calculate the center of the tornado effect in absolute pixel coordinates
    const cx = width * centerXRatio;
    const cy = height * centerYRatio;
    
    // Calculate the actual radius of the effect in pixels.
    // Based on the smaller dimension of the image to ensure the effect can be contained.
    // Since radiusRatio > 0 and width/height > 0 (checked earlier), actualEffectRadius will be > 0.
    const actualEffectRadius = Math.min(width, height) * radiusRatio; 

    // Iterate over each pixel of the destination image
    for (let y = 0; y < height; y++) {
        for (let x = 0; x < width; x++) {
            // Calculate the x and y distances of the current pixel (x,y) from the tornado center (cx,cy)
            const dx = x - cx;
            const dy = y - cy;
            
            // Calculate the radial distance (r) of the current pixel from the tornado center
            const r = Math.sqrt(dx * dx + dy * dy);

            // Get the array index for the current destination pixel
            const currentPixelDestIndex = (y * width + x) * 4;
            
            let srcX = x; // By default, the source pixel is the current pixel itself
            let srcY = y; // This applies to pixels outside the effect radius

            // Apply the tornado (swirl) effect only to pixels within the effect radius
            if (r < actualEffectRadius) {
                // Calculate the original angle of the pixel relative to the center
                const currentAngle = Math.atan2(dy, dx);
                
                // The amount of twist decreases linearly from maxTwistAngleRad at the center (r=0)
                // to 0 at the edge of the effect radius (r = actualEffectRadius).
                const twistFactor = (actualEffectRadius - r) / actualEffectRadius;
                // This can also be written as: const twistFactor = 1.0 - (r / actualEffectRadius);
                const twistAngle = maxTwistAngleRad * twistFactor;
                
                // Calculate the new angle after applying the twist
                const newAngle = currentAngle + twistAngle;

                // Calculate the source coordinates (srcX, srcY) from where to pick the pixel color.
                // This effectively "pulls" pixels from these new coordinates to the current (x,y) position in the output.
                srcX = cx + r * Math.cos(newAngle);
                srcY = cy + r * Math.sin(newAngle);
            }
            // else: for r >= actualEffectRadius, srcX and srcY remain x and y. The pixel is not transformed.


            // Determine the actual source pixel coordinates using nearest-neighbor interpolation.
            // Rounding to the nearest integer coordinates.
            const iSrcX = Math.round(srcX);
            const iSrcY = Math.round(srcY);
            
            // Check if the calculated source coordinates are within the image boundaries
            if (iSrcX >= 0 && iSrcX < width && iSrcY >= 0 && iSrcY < height) {
                // If within bounds, copy the pixel color from the source image
                const srcPixelIndex = (iSrcY * width + iSrcX) * 4;
                destPixels[currentPixelDestIndex]     = srcPixels[srcPixelIndex];     // Red component
                destPixels[currentPixelDestIndex + 1] = srcPixels[srcPixelIndex + 1]; // Green component
                destPixels[currentPixelDestIndex + 2] = srcPixels[srcPixelIndex + 2]; // Blue component
                destPixels[currentPixelDestIndex + 3] = srcPixels[srcPixelIndex + 3]; // Alpha component
            } else {
                // If source coordinates are outside the image bounds, fill the destination pixel with transparent black.
                destPixels[currentPixelDestIndex]     = 0; // Red
                destPixels[currentPixelDestIndex + 1] = 0; // Green
                destPixels[currentPixelDestIndex + 2] = 0; // Blue
                destPixels[currentPixelDestIndex + 3] = 0; // Alpha (transparent)
            }
        }
    }

    // Create a new ImageData object from the manipulated pixel data
    const outputImageData = new ImageData(destPixels, width, height);
    // Put the new image data back onto the canvas, overwriting the original image
    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 Image Tornado Filter Effect Tool allows users to apply a swirling tornado effect to images. This tool can be used to create visually interesting and dynamic images for various applications such as enhancing personal photos, generating artwork, or making promotional graphics. Users can customize the intensity and position of the tornado effect by adjusting parameters like angle, radius, and center, thus giving flexibility in creating unique visual styles. Whether for personal projects, social media content, or digital design, this tool provides an easy way to transform standard images into engaging visuals.

Leave a Reply

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