Please bookmark this page to avoid losing your image tool!

Image Thought Reflection 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, bubblePosition = "top-right", bubbleScale = 0.6, reflectionEffect = "grayscale", bubbleColor = "white", bubbleStrokeColor = "black") {
    // 1. Set up the main canvas
    const w = originalImg.width;
    const h = originalImg.height;

    const canvas = document.createElement('canvas');
    canvas.width = w;
    canvas.height = h;
    const ctx = canvas.getContext('2d');

    // Draw the original image as the background
    ctx.drawImage(originalImg, 0, 0);

    // 2. Define thought bubble geometry based on parameters
    const bubbleW = w * Math.max(0.1, Math.min(1.0, bubbleScale));
    const bubbleH = bubbleW * 0.7; // Bubbles are often wider than they are tall
    const padding = w * 0.05;

    let bubbleX, bubbleY, tailTargetX, tailTargetY;

    // The tail of the bubble will point towards the center of the image
    tailTargetX = w / 2;
    tailTargetY = h / 2;

    switch (bubblePosition) {
        case "top-left":
            bubbleX = padding;
            bubbleY = padding;
            break;
        case "bottom-left":
            bubbleX = padding;
            bubbleY = h - bubbleH - padding;
            break;
        case "bottom-right":
            bubbleX = w - bubbleW - padding;
            bubbleY = h - bubbleH - padding;
            break;
        case "top-right":
        default:
            bubbleX = w - bubbleW - padding;
            bubbleY = padding;
            break;
    }

    // 3. Create the thought bubble path
    const bubblePath = new Path2D();
    const centerX = bubbleX + bubbleW / 2;
    const centerY = bubbleY + bubbleH / 2;

    // Main cloud/bubble shape (an ellipse)
    bubblePath.ellipse(centerX, centerY, bubbleW / 2, bubbleH / 2, 0, 0, Math.PI * 2);

    // Smaller circles for the "tail"
    const dx = tailTargetX - centerX;
    const dy = tailTargetY - centerY;
    const dist = Math.sqrt(dx * dx + dy * dy);
    const unitX = dx / dist;
    const unitY = dy / dist;

    // First tail bubble (larger, closer to the main bubble)
    const tailRadius1 = bubbleW * 0.1;
    const tailDist1 = (bubbleW / 2) + (tailRadius1 * 0.5);
    const tailX1 = centerX + unitX * tailDist1;
    const tailY1 = centerY + unitY * tailDist1;
    bubblePath.moveTo(tailX1 + tailRadius1, tailY1);
    bubblePath.arc(tailX1, tailY1, tailRadius1, 0, Math.PI * 2);

    // Second tail bubble (smaller, further away)
    const tailRadius2 = bubbleW * 0.07;
    const tailDist2 = tailDist1 + tailRadius1 + (tailRadius2 * 0.5);
    const tailX2 = centerX + unitX * tailDist2;
    const tailY2 = centerY + unitY * tailDist2;
    bubblePath.moveTo(tailX2 + tailRadius2, tailY2);
    bubblePath.arc(tailX2, tailY2, tailRadius2, 0, Math.PI * 2);

    // 4. Draw the bubble shape onto the canvas
    ctx.fillStyle = bubbleColor;
    ctx.strokeStyle = bubbleStrokeColor;
    ctx.lineWidth = Math.max(2, w * 0.005); // Make line width responsive
    ctx.fill(bubblePath);
    ctx.stroke(bubblePath);

    // 5. Prepare the "reflection" image on a temporary canvas
    const tempCanvas = document.createElement('canvas');
    tempCanvas.width = w;
    tempCanvas.height = h;
    const tempCtx = tempCanvas.getContext('2d');

    // Apply the chosen effect
    switch (reflectionEffect.toLowerCase()) {
        case "grayscale":
            tempCtx.filter = 'grayscale(100%)';
            break;
        case "blur":
            tempCtx.filter = 'blur(4px)';
            break;
        case "flip":
            tempCtx.translate(w, 0);
            tempCtx.scale(-1, 1);
            break;
        case "none":
        default:
            // No filter applied
            break;
    }

    // Draw the image onto the temp canvas to apply the effect
    tempCtx.drawImage(originalImg, 0, 0);

    // 6. Draw the reflection inside the thought bubble using a clipping mask
    ctx.save();
    ctx.clip(bubblePath); // Future drawing operations will only be visible inside this path
    
    // Draw the temporary canvas (with the effect) onto the main canvas,
    // scaled and positioned to fill the bubble's bounding box.
    ctx.drawImage(tempCanvas, bubbleX, bubbleY, bubbleW, bubbleH);
    
    ctx.restore(); // Remove the clipping mask

    // Return the final canvas element
    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 Thought Reflection Tool allows users to create visually engaging images by adding thought bubbles that reflect the content of the image. Users can customize the position and scale of the thought bubble, choose various reflection effects such as grayscale or blur, and select colors for the bubble and its outline. This tool is ideal for artists, educators, and content creators looking to enhance images for storytelling, presentations, or social media posts by providing a creative way to convey thoughts or ideas associated with the image.

Leave a Reply

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