Please bookmark this page to avoid losing your image tool!

Image And Writer Tool Advanced Search

(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,
    text = "Advanced Search\\nWriter Tool",
    fontFamily = "Arial, sans-serif",
    fontSize = "60",
    textColor = "#FFFFFF",
    strokeColor = "#000000",
    strokeWidth = "3",
    shadowColor = "rgba(0,0,0,0.6)",
    shadowBlur = "15",
    boxColor = "rgba(0,0,0,0.5)",
    boxPadding = "20",
    textAlign = "center",
    textPosition = "middle",
    xPos = "auto",
    yPos = "auto",
    angleDegrees = "0",
    autoWrap = "1"
) {
    // Standardize canvas setup
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    canvas.width = originalImg.width;
    canvas.height = originalImg.height;

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

    // Ensure parameters are parsed correctly
    const size = parseInt(fontSize, 10) || 60;
    const sWidth = parseInt(strokeWidth, 10) || 0;
    const sBlur = parseInt(shadowBlur, 10) || 0;
    const padding = parseInt(boxPadding, 10) || 0;
    const angle = parseInt(angleDegrees, 10) || 0;
    const wrap = String(autoWrap) === "1";

    ctx.font = `bold ${size}px ${fontFamily}`;
    ctx.textAlign = (textAlign === "left" || textAlign === "right" || textAlign === "center") ? textAlign : "center";
    ctx.textBaseline = "middle";

    // Split text into lines, handling both escaped strings and real newlines
    let lines = [];
    if (wrap) {
        const segments = text.split(/\\n|\n/);
        const maxW = canvas.width * 0.9; // Wrap if exceeds 90%
        for (const segment of segments) {
            const words = segment.split(' ');
            let currentLine = words[0] || "";
            for (let i = 1; i < words.length; i++) {
                const word = words[i];
                const width = ctx.measureText(currentLine + " " + word).width;
                if (width < maxW) {
                    currentLine += " " + word;
                } else {
                    lines.push(currentLine);
                    currentLine = word;
                }
            }
            lines.push(currentLine);
        }
    } else {
        lines = text.split(/\\n|\n/);
    }

    // Determine actual coordinates
    let x = 0;
    if (String(xPos).toLowerCase() === "auto") {
        if (ctx.textAlign === "left") x = canvas.width * 0.05;
        else if (ctx.textAlign === "right") x = canvas.width * 0.95;
        else x = canvas.width / 2;
    } else {
        x = parseInt(xPos, 10) || 0;
    }

    let y = 0;
    if (String(yPos).toLowerCase() === "auto") {
        if (textPosition === "top") y = canvas.height * 0.15;
        else if (textPosition === "bottom") y = canvas.height * 0.85;
        else y = canvas.height / 2;
    } else {
        y = parseInt(yPos, 10) || 0;
    }

    // Apply translation and rotation
    ctx.save();
    ctx.translate(x, y);
    ctx.rotate((angle * Math.PI) / 180);

    // Precalculate height metrics
    const lineHeight = size * 1.2;
    const totalHeight = (lines.length - 1) * lineHeight;
    let currentY = -totalHeight / 2;

    // Draw Background Text Box if requested
    if (boxColor && boxColor.toLowerCase() !== "transparent") {
        let maxWidth = 0;
        for (let line of lines) {
            const metrics = ctx.measureText(line);
            if (metrics.width > maxWidth) {
                maxWidth = metrics.width;
            }
        }
        
        const bWidth = maxWidth + padding * 2;
        const bHeight = totalHeight + size + padding * 2;
        
        let bx = 0;
        if (ctx.textAlign === "left") bx = -padding;
        else if (ctx.textAlign === "right") bx = -maxWidth - padding;
        else bx = -maxWidth / 2 - padding;

        const by = -totalHeight / 2 - (size / 2) - padding;

        ctx.fillStyle = boxColor;
        ctx.shadowColor = "transparent"; 
        
        // Rounded Rectangle
        const radius = Math.min(10, bWidth / 2, bHeight / 2);
        ctx.beginPath();
        ctx.moveTo(bx + radius, by);
        ctx.lineTo(bx + bWidth - radius, by);
        ctx.quadraticCurveTo(bx + bWidth, by, bx + bWidth, by + radius);
        ctx.lineTo(bx + bWidth, by + bHeight - radius);
        ctx.quadraticCurveTo(bx + bWidth, by + bHeight, bx + bWidth - radius, by + bHeight);
        ctx.lineTo(bx + radius, by + bHeight);
        ctx.quadraticCurveTo(bx, by + bHeight, bx, by + bHeight - radius);
        ctx.lineTo(bx, by + radius);
        ctx.quadraticCurveTo(bx, by, bx + radius, by);
        ctx.closePath();
        ctx.fill();
    }

    // Render configuration for text lines
    for (let i = 0; i < lines.length; i++) {
        const line = lines[i];

        // Apply drop shadow specifically to the outermost layer (Stroke if exists, else Fill)
        if (sBlur > 0) {
            ctx.shadowColor = shadowColor;
            ctx.shadowBlur = sBlur;
            ctx.shadowOffsetX = 4;
            ctx.shadowOffsetY = 4;
        } else {
            ctx.shadowColor = "transparent";
            ctx.shadowBlur = 0;
        }

        // Render Stroke and Text
        if (sWidth > 0) {
            ctx.lineWidth = sWidth;
            ctx.strokeStyle = strokeColor;
            ctx.lineJoin = "round"; // Limits text-spikes
            ctx.miterLimit = 2;
            ctx.strokeText(line, 0, currentY);
            
            // Turn off shadow for the interior fill to keep it clean
            ctx.shadowColor = "transparent";
            ctx.shadowBlur = 0;
            ctx.shadowOffsetX = 0;
            ctx.shadowOffsetY = 0;
            
            ctx.fillStyle = textColor;
            ctx.fillText(line, 0, currentY);
        } else {
            ctx.fillStyle = textColor;
            ctx.fillText(line, 0, currentY);
        }

        currentY += lineHeight;
    }

    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 Image And Writer Tool Advanced Search allows users to overlay customized text onto images. It provides extensive styling options, including font family, size, text color, and text alignment. Users can enhance text readability by adding strokes, drop shadows, or a semi-transparent background box. The tool also supports advanced positioning features such as text rotation, automatic word wrapping, and vertical alignment (top, middle, or bottom). This tool is ideal for creating social media graphics, watermarking images, designing digital posters, or adding descriptive captions to visual content.

Leave a Reply

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