Please bookmark this page to avoid losing your image tool!

Image Acid Pool 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, distortionAmount = 0.03, waveFrequency = 8, colorIntensity = 1.0) {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d', { willReadFrequently: true }); // Optimization hint for frequent getImageData/putImageData

    // Determine image dimensions, ensuring they are positive
    const imgWidth = originalImg.naturalWidth || originalImg.width;
    const imgHeight = originalImg.naturalHeight || originalImg.height;

    if (imgWidth <= 0 || imgHeight <= 0) {
        // console.error("Image dimensions must be valid and positive for processing.");
        // Create a small canvas with an error message
        const errCanvas = document.createElement('canvas');
        errCanvas.width = Math.max(1, imgWidth || 100); // Use a default if dimensions are truly zero
        errCanvas.height = Math.max(1, imgHeight || 100);
        const errCtx = errCanvas.getContext('2d');
        errCtx.fillStyle = 'lightgray';
        errCtx.fillRect(0, 0, errCanvas.width, errCanvas.height);
        if (typeof errCtx.fillText === 'function') { // Check if fillText is available (browser env)
            errCtx.fillStyle = 'red';
            errCtx.textAlign = 'center';
            errCtx.font = '12px Arial';
            errCtx.fillText('Invalid Image Dimensions', errCanvas.width / 2, errCanvas.height / 2);
        }
        return errCanvas;
    }

    canvas.width = imgWidth;
    canvas.height = imgHeight;

    // Draw the original image onto the canvas
    try {
        ctx.drawImage(originalImg, 0, 0, imgWidth, imgHeight);
    } catch (e) {
        // console.error("Error drawing image to canvas: ", e);
        // Fallback: render error message on canvas
        ctx.fillStyle = 'lightgray';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        if (typeof ctx.fillText === 'function') {
            ctx.fillStyle = 'red';
            ctx.textAlign = 'center';
            ctx.font = '16px Arial';
            ctx.fillText('Error loading image', canvas.width / 2, canvas.height / 2);
        }
        return canvas; // Return the canvas with the error message
    }
    
    let imageData;
    try {
        imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    } catch (e) {
        // This can happen due to tainted canvas if image is cross-origin and server doesn't allow.
        // console.error("Error getting ImageData (possibly tainted canvas): ", e);
        ctx.fillStyle = 'lightgray';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        if (typeof ctx.fillText === 'function') {
            ctx.font = '14px Arial'; // Adjusted font size
            ctx.fillStyle = 'darkred';
            ctx.textAlign = 'center';
            const msg = 'Cannot process: Image from another domain?';
            // Basic text fitting
            const textMetrics = ctx.measureText(msg);
            if (textMetrics.width > canvas.width - 20) { // If text is too wide, use smaller font
                 ctx.font = '10px Arial';
            }
            ctx.fillText(msg, canvas.width / 2, canvas.height / 2);
             if (canvas.height > 40) { // Add note if space allows
                ctx.font = '10px Arial';
                ctx.fillText('(Enable CORS or use same-domain image)', canvas.width / 2, canvas.height / 2 + 15);
            }
        }
        return canvas;
    }
    
    const data = imageData.data;
    const width = canvas.width;
    const height = canvas.height;

    // Create a copy of the original pixel data to read from.
    // This is crucial because we're modifying `data` while needing original values for distortion.
    const originalPixelData = new Uint8ClampedArray(imageData.data);

    // Normalize parameters to prevent extreme values if necessary
    distortionAmount = Math.max(0, Math.min(0.2, distortionAmount)); // Cap distortion
    waveFrequency = Math.max(1, Math.min(50, waveFrequency));     // Cap frequency
    colorIntensity = Math.max(0, Math.min(1, colorIntensity));   // Clamp intensity

    for (let y = 0; y < height; y++) {
        for (let x = 0; x < width; x++) {
            // Normalize coordinates for consistent wave calculation regardless of image size
            const normalizedY = y / height; // Ranges from 0 to 1
            const normalizedX = x / width;  // Ranges from 0 to 1

            // Calculate distortion offsets for the "pool" effect
            // X-offset ripple based on Y-position, Y-offset ripple based on X-position
            const angleYWave = normalizedY * waveFrequency * Math.PI * 2; // waveFrequency full waves across Y
            const angleXWave = normalizedX * waveFrequency * Math.PI * 2; // waveFrequency full waves across X

            const offsetX = Math.sin(angleYWave) * width * distortionAmount;
            const offsetY = Math.cos(angleXWave) * height * distortionAmount; // Using cos for Y for varied pattern

            // Calculate the source pixel coordinates after applying distortion
            let srcX = Math.round(x + offsetX);
            let srcY = Math.round(y + offsetY);

            // Clamp source coordinates to be within the image bounds
            srcX = Math.max(0, Math.min(width - 1, srcX));
            srcY = Math.max(0, Math.min(height - 1, srcY));

            const srcIndex = (srcY * width + srcX) * 4;

            // Get original pixel color from the (distorted) source location
            let r_src = originalPixelData[srcIndex];
            let g_src = originalPixelData[srcIndex + 1];
            let b_src = originalPixelData[srcIndex + 2];
            const a_src = originalPixelData[srcIndex + 3]; // Alpha channel

            // Apply "Acid" color transformation: R -> G, G -> B, B -> R (GBR cyclcic shift)
            // This creates a psychedelic color effect.
            let r_acid = g_src;
            let g_acid = b_src;
            let b_acid = r_src;

            // Blend the "acid" color with the original source color based on colorIntensity parameter
            const destIndex = (y * width + x) * 4;
            data[destIndex]     = (1 - colorIntensity) * r_src + colorIntensity * r_acid;
            data[destIndex + 1] = (1 - colorIntensity) * g_src + colorIntensity * g_acid;
            data[destIndex + 2] = (1 - colorIntensity) * b_src + colorIntensity * b_acid;
            data[destIndex + 3] = a_src; // Preserve the original alpha
        }
    }

    // Write the modified pixel data back to the canvas
    ctx.putImageData(imageData, 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 Acid Pool Filter Effect Tool allows users to apply a psychedelic distortion effect to their images. By adjusting parameters such as distortion amount, wave frequency, and color intensity, users can create vibrant, swirling visuals that mimic an ‘acid pool’ aesthetic. This tool is ideal for artists, graphic designers, and anyone looking to enhance their images with dynamic visual effects. Use cases include creating unique social media graphics, enhancing digital art projects, or simply experimenting with image transformations.

Leave a Reply

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