Please bookmark this page to avoid losing your image tool!

Image Drip Paint 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.
async function processImage(originalImg, numDripsParam = 75, sampleColorStr = "true", fixedDripColor = "black", maxDripLengthParam = 150, minDripThicknessParam = 3, maxDripThicknessParam = 10, originYSpreadFactorParam = 0.5) {
    
    // Validate originalImg
    if (!originalImg || typeof originalImg.width === 'undefined' || originalImg.width === 0 || typeof originalImg.height === 'undefined' || originalImg.height === 0) {
        console.warn("Image Drip Paint Filter: Invalid image provided or image not loaded.");
        const fallbackCanvas = document.createElement('canvas');
        fallbackCanvas.width = (originalImg && originalImg.width > 0) ? originalImg.width : 100;
        fallbackCanvas.height = (originalImg && originalImg.height > 0) ? originalImg.height : 100;
        const fbCtx = fallbackCanvas.getContext('2d');
        if (fbCtx) {
            fbCtx.fillStyle = "#cccccc";
            fbCtx.fillRect(0,0,fallbackCanvas.width, fallbackCanvas.height);
            fbCtx.fillStyle = "black";
            fbCtx.font = "12px Arial";
            fbCtx.textAlign = "center";
            fbCtx.textBaseline = "middle";
            fbCtx.fillText("Invalid Image", fallbackCanvas.width/2, fallbackCanvas.height/2);
        }
        return fallbackCanvas;
    }

    // Parameter parsing and validation
    const sampleColor = String(sampleColorStr).toLowerCase() === "true";
    
    let numDrips = parseInt(String(numDripsParam), 10);
    if (isNaN(numDrips) || numDrips < 0) numDrips = 75;

    let maxDripLength = parseFloat(String(maxDripLengthParam));
    if (isNaN(maxDripLength) || maxDripLength <= 0) maxDripLength = 150;

    let minDripThickness = parseFloat(String(minDripThicknessParam));
    if (isNaN(minDripThickness) || minDripThickness <= 0) minDripThickness = 3;

    let maxDripThickness = parseFloat(String(maxDripThicknessParam));
    if (isNaN(maxDripThickness) || maxDripThickness <= 0) maxDripThickness = 10;
    
    if (minDripThickness > maxDripThickness) {
        maxDripThickness = minDripThickness + Math.max(1, minDripThickness * 0.2);
    }
    if (maxDripThickness < minDripThickness) { // If max was initially smaller
         maxDripThickness = minDripThickness;
    }


    let originYSpreadFactor = parseFloat(String(originYSpreadFactorParam));
    if (isNaN(originYSpreadFactor) || originYSpreadFactor < 0 || originYSpreadFactor > 1) originYSpreadFactor = 0.5;

    const canvas = document.createElement('canvas');
    canvas.width = originalImg.width;
    canvas.height = originalImg.height + maxDripLength; 
    const ctx = canvas.getContext('2d');
    if (!ctx) {
        console.error("Image Drip Paint Filter: Could not get 2D context for canvas.");
        return originalImg; // Return original image or some error indicator
    }


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

    let tempSampleCanvas = null;
    let tempSampleCtx = null;
    let canSampleColor = sampleColor; // Flag to track if sampling is possible

    if (sampleColor) {
        tempSampleCanvas = document.createElement('canvas');
        tempSampleCanvas.width = originalImg.width;
        tempSampleCanvas.height = originalImg.height;
        tempSampleCtx = tempSampleCanvas.getContext('2d', { willReadFrequently: true });
        if (!tempSampleCtx) {
             console.warn("Image Drip Paint Filter: Failed to create sampling context. Using fixed drip color.");
             canSampleColor = false; 
        } else {
            try {
                tempSampleCtx.drawImage(originalImg, 0, 0);
                // Test getImageData to see if canvas is tainted early
                tempSampleCtx.getImageData(0, 0, 1, 1); 
            } catch (e) {
                console.warn("Image Drip Paint Filter: Error drawing to or sampling from temp canvas. Canvas might be tainted. Using fixed drip color. Error:", e);
                canSampleColor = false;
            }
        }
    }

    function getPixelColor(x, y) {
        if (!canSampleColor || !tempSampleCtx ) { // Check canSampleColor flag
            return fixedDripColor; 
        }
        // Clamp coordinates to be within the image bounds
        x = Math.max(0, Math.min(Math.floor(x), originalImg.width - 1));
        y = Math.max(0, Math.min(Math.floor(y), originalImg.height - 1));
        
        try {
            const pixelData = tempSampleCtx.getImageData(x, y, 1, 1).data;
            return `rgba(${pixelData[0]}, ${pixelData[1]}, ${pixelData[2]}, ${pixelData[3] / 255})`;
        } catch (e) {
            // This catch might be redundant if initial test failed, but good for safety
            console.warn("Image Drip Paint Filter: Error sampling pixel color during getPixelColor. Using fixed color. Error:", e);
            canSampleColor = false; // Stop trying to sample for subsequent drips
            return fixedDripColor; 
        }
    }

    function drawRealisticDrip(context, startX, startY, length, dripInitialThickness, color) {
        let currentX = startX;
        let currentY = startY;
        
        context.fillStyle = color;

        const numSegments = Math.max(5, Math.ceil(length / Math.max(1, dripInitialThickness * 0.4)));
        const speedVariation = 0.4; 
        const wiggleScale = dripInitialThickness * 0.35; 

        for (let i = 0; i <= numSegments; i++) {
            const t = i / numSegments; 
            
            context.beginPath();
            context.arc(currentX, currentY, dripInitialThickness / 2, 0, Math.PI * 2);
            context.fill();

            if (i === numSegments) break; 

            const baseSegmentYMovement = length / numSegments;
            let yMovement = baseSegmentYMovement * (1 + (Math.random() - 0.5) * speedVariation);
            yMovement = Math.max(0.5, yMovement); 

            currentY += yMovement;
            if (currentY > startY + length) { 
                currentY = startY + length;
            }
            
            const G_wiggleFactor = (1 - t * t) * wiggleScale; 
            currentX += (Math.random() - 0.5) * G_wiggleFactor;
            
            currentX = Math.max(dripInitialThickness / 2, Math.min(context.canvas.width - dripInitialThickness / 2, currentX));
            
            if (currentY >= context.canvas.height - dripInitialThickness / 2) {
                currentY = context.canvas.height - dripInitialThickness / 2; 
                context.beginPath();
                context.arc(currentX, currentY, (dripInitialThickness / 2) * 1.5, 0, Math.PI * 2);
                context.fill();
                return; 
            }
        }
        
        context.beginPath();
        context.arc(currentX, currentY, (dripInitialThickness / 2) * 1.5, 0, Math.PI * 2);
        context.fill();
    }

    for (let i = 0; i < numDrips; i++) {
        const startX = Math.random() * originalImg.width;
        const startY = Math.random() * (originalImg.height * originYSpreadFactor);

        const dripColorToUse = getPixelColor(startX, startY);
        
        const currentDripLength = (Math.random() * 0.6 + 0.4) * maxDripLength; 
        let currentThickness = minDripThickness + Math.random() * (maxDripThickness - minDripThickness);
        if (maxDripThickness === minDripThickness) currentThickness = minDripThickness;

        drawRealisticDrip(ctx, startX, startY, currentDripLength, currentThickness, dripColorToUse);
    }

    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 Drip Paint Filter Effect Tool allows users to apply a realistic drip paint effect to images, creating a visually engaging transformation. This tool can be particularly useful for artists and designers looking to create unique artwork or enhance their digital images with artistic flair. Users can adjust parameters such as the number of drips, the colors used (either based on the original image or fixed), and the lengths and thicknesses of the drips, providing flexibility to tailor the effect to their desired outcome. Whether for social media posts, graphic design projects, or personal creative exploration, this tool offers an innovative way to alter and personalize images.

Leave a Reply

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