Please bookmark this page to avoid losing your image tool!

Image Crying Effect Adder

(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, sadnessIntensity = "50", tearsAmount = "30") {
    // Validate and parse parameters
    const sadLvl = Math.max(0, Math.min(100, isNaN(Number(sadnessIntensity)) ? 50 : Number(sadnessIntensity)));
    const tearsCount = Math.max(0, Math.min(200, isNaN(Number(tearsAmount)) ? 30 : Number(tearsAmount)));

    const canvas = document.createElement('canvas');
    canvas.width = originalImg.naturalWidth || originalImg.width;
    canvas.height = originalImg.naturalHeight || originalImg.height;
    const ctx = canvas.getContext('2d');

    // 1. Draw the original image
    ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);

    // 2. Apply "Sad" color effect (Desaturate & Blue Tint)
    try {
        const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        const data = imgData.data;
        const factor = sadLvl / 100;
        
        for (let i = 0; i < data.length; i += 4) {
            let r = data[i], g = data[i + 1], b = data[i + 2];
            
            // Calculate luminance for desaturation
            let l = 0.3 * r + 0.59 * g + 0.11 * b;
            
            // Blend original colors with grayscale based on intensity
            r = r + (l - r) * factor;
            g = g + (l - g) * factor;
            b = b + (l - b) * factor;
            
            // Apply blueish 'sorrowful' cool tint
            r = r * (1 - 0.2 * factor);
            b = b * (1 + 0.3 * factor);
            g = g * (1 - 0.1 * factor);
            
            data[i] = r;
            data[i + 1] = g;
            data[i + 2] = b;
        }
        ctx.putImageData(imgData, 0, 0);
    } catch (e) {
        // Fallback for CORS tainted canvas: Use a blended overlay instead
        const factor = sadLvl / 100;
        ctx.fillStyle = `rgba(10, 30, 70, ${factor * 0.4})`;
        ctx.fillRect(0, 0, canvas.width, canvas.height);
    }

    // 3. Apply sorrowful dark vignette around edges
    const factorNum = sadLvl / 100;
    if (factorNum > 0) {
        const gradient = ctx.createRadialGradient(
            canvas.width / 2, canvas.height / 2, Math.min(canvas.width, canvas.height) * 0.3,
            canvas.width / 2, canvas.height / 2, Math.max(canvas.width, canvas.height) * 0.8
        );
        gradient.addColorStop(0, 'rgba(0, 0, 0, 0)');
        gradient.addColorStop(1, `rgba(0, 5, 20, ${0.7 * factorNum})`);
        
        ctx.fillStyle = gradient;
        ctx.fillRect(0, 0, canvas.width, canvas.height);
    }

    // Helper function to draw a single realistic teardrop shape
    function drawTear(ctx, startX, startY, length, radius) {
        const dropCenterY = startY + length - radius;
        const cpY1 = startY + length * 0.3;
        const cpY2 = Math.max(startY + length * 0.4, dropCenterY - radius * 1.2);

        ctx.save();
        
        // Define teardrop outline
        ctx.beginPath();
        ctx.moveTo(startX, startY);
        // Left side curve trailing down
        ctx.bezierCurveTo(
            startX - radius * 0.2, cpY1,
            startX - radius, cpY2,
            startX - radius, dropCenterY
        );
        // Bottom curved droplet
        ctx.arc(startX, dropCenterY, radius, Math.PI, 0, true);
        // Right side curve trailing up
        ctx.bezierCurveTo(
            startX + radius, cpY2,
            startX + radius * 0.2, cpY1,
            startX, startY
        );
        ctx.closePath();

        // Fill with a watery, slightly bluish translucent gradient
        let tearGrad = ctx.createLinearGradient(startX, startY, startX, dropCenterY + radius);
        tearGrad.addColorStop(0, 'rgba(255, 255, 255, 0.05)');
        tearGrad.addColorStop(0.5, 'rgba(220, 235, 255, 0.15)');
        tearGrad.addColorStop(1, 'rgba(160, 200, 255, 0.45)');
        
        ctx.fillStyle = tearGrad;
        ctx.fill();

        // Edge stroke for refraction outline
        ctx.lineWidth = Math.max(1, radius * 0.05);
        ctx.strokeStyle = 'rgba(10, 30, 60, 0.15)'; 
        ctx.stroke();

        // Specular highlight (Bottom rim reflection)
        ctx.beginPath();
        ctx.arc(startX - radius * 0.3, dropCenterY + radius * 0.4, radius * 0.25, 0, Math.PI * 2);
        ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
        ctx.fill();

        // Top trail subtle highlight
        ctx.beginPath();
        ctx.moveTo(startX, startY);
        ctx.lineTo(startX, dropCenterY - radius * 0.5);
        ctx.lineWidth = Math.max(0.5, radius * 0.1);
        ctx.strokeStyle = 'rgba(255, 255, 255, 0.3)';
        ctx.stroke();

        ctx.restore();
    }

    // 4. Generate tears scattered across image, clustered roughly at "eye" locations
    for (let i = 0; i < tearsCount; i++) {
        let startX, startY;
        
        if (i < tearsCount * 0.6) {
            // Clustered 60% of tearing near eyes region
            let isLeft = i % 2 === 0;
            let clusterX = isLeft ? canvas.width * 0.38 : canvas.width * 0.62;
            let clusterY = canvas.height * 0.35;
            startX = clusterX + (Math.random() - 0.5) * canvas.width * 0.15;
            startY = clusterY + (Math.random() - 0.5) * canvas.height * 0.15;
        } else {
            // The rest are strewn vaguely overhead/mixed
            startX = canvas.width * Math.random();
            startY = canvas.height * Math.random() * 0.6;
        }
        
        // Prevent drawing way off canvas width
        startX = Math.max(0, Math.min(canvas.width, startX));
        
        let radius = Math.max(3, Math.min(25, canvas.width * (0.008 + Math.random() * 0.012)));
        let length = Math.max(20, canvas.height * (0.05 + Math.random() * 0.25));
        length = Math.max(length, radius * 2.5); // Ensure stream isn't too short for the drop
        
        drawTear(ctx, startX, startY, length, radius);
    }

    // Helper function to draw pooling water/tears at the bottom of the image
    function drawWave(ctx, waterHeight, waveCount, phase, color) {
        ctx.beginPath();
        let y = canvas.height - waterHeight;
        ctx.moveTo(0, canvas.height); // Starting at bottom-left corner
        ctx.lineTo(0, y);
        
        let waveAmp = Math.max(2, canvas.height * 0.012);
        let waveFreq = (waveCount * Math.PI * 2) / canvas.width;
        let step = Math.max(5, Math.ceil(canvas.width / 100));
        
        for (let x = 0; x <= canvas.width + step; x += step) {
            ctx.lineTo(x, y + Math.sin(x * waveFreq + phase) * waveAmp);
        }
        
        ctx.lineTo(canvas.width, canvas.height); // Down to bottom-right corner
        ctx.closePath();
        
        ctx.fillStyle = color;
        ctx.fill();
    }

    // 5. Draw the pool of tears rising at the bottom based on amount parameter
    const maxWaterHeight = canvas.height * 0.25; // max pool level is 25% of image
    const waterHeight = maxWaterHeight * (tearsCount / 100);
    
    if (waterHeight > 0) {
        // Draw background wave layer
        drawWave(ctx, waterHeight * 0.9, 2.5, 0, 'rgba(120, 180, 255, 0.3)');
        // Draw foreground wave layer
        drawWave(ctx, waterHeight, 3.5, 3, 'rgba(160, 210, 255, 0.45)');
        
        // Optional subtle white stroke on front wave to signify surface 
        ctx.lineWidth = 1;
        ctx.strokeStyle = 'rgba(255, 255, 255, 0.2)';
        ctx.stroke();
    }

    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 Crying Effect Adder is a creative tool designed to apply a sorrowful aesthetic to your photos. It modifies images by desaturating colors, adding a cool blue tint, and applying a dark vignette to evoke a melancholy mood. Additionally, the tool overlays realistic teardrop effects and can simulate a rising pool of water at the bottom of the frame. Users can adjust the intensity of the sadness and the number of tears to achieve a specific dramatic effect. This tool is ideal for creating expressive digital art, dramatic social media posts, or themed visual content for storytelling.

Leave a Reply

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