Please bookmark this page to avoid losing your image tool!

Image Wind Turbine Filter Effect Enhancer

(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,
    numBlades = 3,
    bladeColor = "rgba(220, 220, 220, 0.35)",
    bladeLengthFactor = 0.45,     // Proportion of the smaller image dimension
    bladeBaseWidthFactor = 0.12,  // Proportion of blade length
    bladeTipWidthFactor = 0.03,   // Proportion of blade length
    hubRadiusFactor = 0.06,       // Proportion of blade length
    spinOffsetAngle = 0,          // Initial rotation in degrees
    motionBlurSteps = 7,          // Number of steps for blur effect (0 for no blur)
    motionBlurAngleSpread = 20,   // Angular spread of blur in degrees
    centerOffsetXRatio = 0,       // Horizontal offset of turbine center (-0.5 to 0.5 of image width)
    centerOffsetYRatio = 0        // Vertical offset of turbine center (-0.5 to 0.5 of image height)
) {
    // Ensure numeric parameters are properly typed as numbers
    numBlades = Number(numBlades);
    bladeLengthFactor = Number(bladeLengthFactor);
    bladeBaseWidthFactor = Number(bladeBaseWidthFactor);
    bladeTipWidthFactor = Number(bladeTipWidthFactor);
    hubRadiusFactor = Number(hubRadiusFactor);
    spinOffsetAngle = Number(spinOffsetAngle);
    motionBlurSteps = Number(motionBlurSteps);
    motionBlurAngleSpread = Number(motionBlurAngleSpread);
    centerOffsetXRatio = Number(centerOffsetXRatio);
    centerOffsetYRatio = Number(centerOffsetYRatio);

    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    // Ensure originalImg has valid dimensions
    const imgWidth = originalImg.naturalWidth || originalImg.width;
    const imgHeight = originalImg.naturalHeight || originalImg.height;
    
    canvas.width = imgWidth;
    canvas.height = imgHeight;

    // Draw the original image onto the canvas
    ctx.drawImage(originalImg, 0, 0, imgWidth, imgHeight);

    // If image dimensions are zero, or no blades, return early
    if (imgWidth === 0 || imgHeight === 0) {
        return canvas;
    }
    
    // Calculate turbine properties
    const centerX = canvas.width / 2 + centerOffsetXRatio * canvas.width;
    const centerY = canvas.height / 2 + centerOffsetYRatio * canvas.height;
    
    const minImageDimension = Math.min(canvas.width, canvas.height);
    const bladeL = bladeLengthFactor * minImageDimension; // Blade length

    // If blade length or number of blades is zero or negative, no blades to draw
    if (bladeL <= 0 || numBlades <= 0) {
        return canvas;
    }

    const hubActualRadius = hubRadiusFactor * bladeL;      // Radius of the central hub
    const bladeWBase = bladeBaseWidthFactor * bladeL;    // Width of the blade at its base (near hub)
    const bladeWTip = bladeTipWidthFactor * bladeL;      // Width of the blade at its tip

    // Store original globalAlpha and set fillStyle for blades
    const originalGlobalAlpha = ctx.globalAlpha;
    ctx.fillStyle = bladeColor;

    const effectiveBlurSteps = Math.max(0, Math.floor(motionBlurSteps));

    // Loop for motion blur steps. Step 0 is the "main" blade position.
    for (let step = 0; step <= effectiveBlurSteps; step++) {
        const currentSpinOffsetRad = spinOffsetAngle * (Math.PI / 180);
        let stepAngleShiftRad = 0;
        let stepOpacityFactor = 1.0;

        if (effectiveBlurSteps > 0 && step > 0) { // Apply blur only for steps after the main blade image
            // Trails spread "behind" the main blade position
            stepAngleShiftRad = (step / effectiveBlurSteps) * (motionBlurAngleSpread * Math.PI / 180);
            // Opacity diminishes for trails further back in the motion
            stepOpacityFactor = 1.0 - (step / (effectiveBlurSteps + 1));
        } else if (effectiveBlurSteps === 0 && step === 0) {
            // No blur, full opacity for the single drawing pass
        }


        ctx.globalAlpha = originalGlobalAlpha * stepOpacityFactor; // Apply step-specific opacity

        for (let i = 0; i < numBlades; i++) {
            const baseAngleRad = (i / numBlades) * (2 * Math.PI) + currentSpinOffsetRad;
            // Current angle for this specific blade in this blur step
            const bladeAngleForStepRad = baseAngleRad - stepAngleShiftRad; 

            // Vector along the blade's direction and its perpendicular
            const vecX = Math.cos(bladeAngleForStepRad);
            const vecY = Math.sin(bladeAngleForStepRad);
            const perpX = -vecY; // Perpendicular vector component X
            const perpY = vecX;  // Perpendicular vector component Y

            // Define the four corner points of the blade (a quadrilateral)
            // Points are ordered for ctx.lineTo: inner-left, inner-right, outer-right, outer-left
            const p_inner_left_x = centerX + hubActualRadius * vecX + (bladeWBase / 2) * perpX;
            const p_inner_left_y = centerY + hubActualRadius * vecY + (bladeWBase / 2) * perpY;

            const p_inner_right_x = centerX + hubActualRadius * vecX - (bladeWBase / 2) * perpX;
            const p_inner_right_y = centerY + hubActualRadius * vecY - (bladeWBase / 2) * perpY;

            const p_outer_right_x = centerX + (hubActualRadius + bladeL) * vecX - (bladeWTip / 2) * perpX;
            const p_outer_right_y = centerY + (hubActualRadius + bladeL) * vecY - (bladeWTip / 2) * perpY;

            const p_outer_left_x = centerX + (hubActualRadius + bladeL) * vecX + (bladeWTip / 2) * perpX;
            const p_outer_left_y = centerY + (hubActualRadius + bladeL) * vecY + (bladeWTip / 2) * perpY;

            // Draw the blade path
            ctx.beginPath();
            ctx.moveTo(p_inner_left_x, p_inner_left_y);
            ctx.lineTo(p_inner_right_x, p_inner_right_y);
            ctx.lineTo(p_outer_right_x, p_outer_right_y);
            ctx.lineTo(p_outer_left_x, p_outer_left_y);
            ctx.closePath();
            ctx.fill();
        }
    }

    // Restore globalAlpha to its original value
    ctx.globalAlpha = originalGlobalAlpha;

    // Draw the central hub cap (nacelle) on top of the blade roots
    if (hubActualRadius > 0) {
        // The hub is drawn with the same bladeColor.
        // If bladeColor is highly transparent, the hub will also be transparent.
        // For a more solid hub, ensure bladeColor's alpha is high, or use a dedicated hub color parameter.
        ctx.fillStyle = bladeColor; // Re-set fill style in case it was changed
        ctx.beginPath();
        ctx.arc(centerX, centerY, hubActualRadius, 0, 2 * Math.PI);
        ctx.fill();
    }

    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 Wind Turbine Filter Effect Enhancer’ is an online tool that allows users to add a wind turbine effect to their images. With adjustable parameters, users can define the number of turbine blades, their colors, lengths, and various visual effects such as motion blur. This tool is useful for creating artistic representations of renewable energy themes, enhancing graphics for environmental projects, or simply adding a creative touch to photo editing. Whether for personal use or visual design in presentations, the tool enables versatile image transformations related to wind power imagery.

Leave a Reply

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