Please bookmark this page to avoid losing your image tool!

Waterpark Image Creator

(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, waveAmplitude = 12, waveFrequency = 0.05, tintLevel = 0.35) {
    const width = originalImg.width;
    const height = originalImg.height;

    // Create a canvas to draw and manipulate the image
    const canvas = document.createElement('canvas');
    canvas.width = width;
    canvas.height = height;
    const ctx = canvas.getContext('2d');

    // Draw the initial image on the canvas
    ctx.drawImage(originalImg, 0, 0);

    // Fetch pixel data
    const imgData = ctx.getImageData(0, 0, width, height);
    const data = imgData.data;
    
    // Create a copy of the original data to read from, so we don't read modified data when translating pixels
    const srcData = new Uint8ClampedArray(data);

    // 1. Apply underwater wave distortion and pool tint to pixels
    for (let y = 0; y < height; y++) {
        for (let x = 0; x < width; x++) {
            // Calculate displaced coordinates for a water ripple effect
            let offsetX = Math.sin(y * waveFrequency) * waveAmplitude;
            let offsetY = Math.cos(x * waveFrequency) * waveAmplitude;

            let srcX = Math.floor(x + offsetX);
            let srcY = Math.floor(y + offsetY);

            // Clamp coordinates to image boundaries
            srcX = Math.max(0, Math.min(width - 1, srcX));
            srcY = Math.max(0, Math.min(height - 1, srcY));

            const destIdx = (y * width + x) * 4;
            const srcIdx = (srcY * width + srcX) * 4;

            let r = srcData[srcIdx];
            let g = srcData[srcIdx + 1];
            let b = srcData[srcIdx + 2];
            let a = srcData[srcIdx + 3];

            // Apply aqua waterpark tint (pool blue/cyan: roughly R=0, G=150, B=230)
            r = r * (1 - tintLevel) + 0 * tintLevel;
            g = g * (1 - tintLevel) + 150 * tintLevel;
            b = b * (1 - tintLevel) + 230 * tintLevel;

            // Uint8ClampedArray will automatically clamp values between 0 and 255
            data[destIdx] = r;
            data[destIdx + 1] = g;
            data[destIdx + 2] = b;
            data[destIdx + 3] = a;
        }
    }
    ctx.putImageData(imgData, 0, 0);

    // 2. Draw overlapping water caustics (sunlight pool reflections)
    ctx.save();
    ctx.globalCompositeOperation = 'screen';
    ctx.lineWidth = 2;
    ctx.strokeStyle = 'rgba(255, 255, 255, 0.15)';
    
    let causticFrequency = waveFrequency * 0.5;
    
    // Horizontal-ish wave lines
    for (let i = 0; i < height; i += 20) {
        ctx.beginPath();
        for (let j = 0; j <= width; j += 10) {
            let offset = Math.sin(j * causticFrequency + i * 0.1) * 15;
            if (j === 0) ctx.moveTo(j, i + offset);
            else ctx.lineTo(j, i + offset);
        }
        ctx.stroke();
    }
    
    // Vertical-ish wave lines
    for (let j = 0; j < width; j += 20) {
        ctx.beginPath();
        for (let i = 0; i <= height; i += 10) {
            let offset = Math.sin(i * causticFrequency + j * 0.1) * 15;
            if (i === 0) ctx.moveTo(j + offset, i);
            else ctx.lineTo(j + offset, i);
        }
        ctx.stroke();
    }
    ctx.restore();

    // Setup a simple pseudo-random number generator for deterministic rendering
    let seed = 12345;
    function random() {
        seed = (seed * 9301 + 49297) % 233280;
        return seed / 233280;
    }

    // 3. Draw stylistic underwater air bubbles
    const numBubbles = Math.floor((width * height) / 8000); // Scale bubbles based on resolution

    for (let k = 0; k < numBubbles; k++) {
        let cx = random() * width;
        let cy = random() * height;
        let r = random() * 15 + 3;

        // Bubble fill and outline
        ctx.beginPath();
        ctx.arc(cx, cy, r, 0, Math.PI * 2);
        ctx.fillStyle = 'rgba(255, 255, 255,' + (random() * 0.2 + 0.1) + ')';
        ctx.fill();
        ctx.lineWidth = 1.5;
        ctx.strokeStyle = 'rgba(255, 255, 255,' + (random() * 0.4 + 0.4) + ')';
        ctx.stroke();

        // Bright bubble highlight
        ctx.beginPath();
        ctx.arc(cx - r * 0.3, cy - r * 0.3, r * 0.2, 0, Math.PI * 2);
        ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
        ctx.fill();
    }

    // 4. Add a vibrant sunny vignette (water parks are bright and colorful)
    const gradient = ctx.createRadialGradient(width/2, height/2, 0, width/2, height/2, Math.max(width, height) * 0.7);
    gradient.addColorStop(0, 'rgba(255, 255, 255, 0.1)'); // Bright center
    gradient.addColorStop(1, 'rgba(0, 80, 160, 0.4)');     // Deep blue edges
    
    ctx.save();
    ctx.globalCompositeOperation = 'overlay';
    ctx.fillStyle = gradient;
    ctx.fillRect(0, 0, width, height);
    ctx.restore();

    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 Waterpark Image Creator applies an underwater aesthetic to your photos by introducing wave distortions, a blue-toned pool tint, and light caustics to simulate sunlight reflecting through water. It also adds stylistic air bubbles and a vibrant sunny vignette to enhance the aquatic feel. This tool is ideal for creating themed content for summer promotions, social media posts, or adding playful water-themed effects to various images.

Leave a Reply

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