Please bookmark this page to avoid losing your image tool!

Image Text Print With Custom Message 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.
/**
 * Overlays a custom text message onto an image, with options for styling and positioning.
 * It supports web-safe fonts and dynamically loads fonts from Google Fonts.
 * The text is automatically wrapped to fit the image width and also respects newline characters.
 *
 * @param {Image} originalImg The original Image object to draw upon.
 * @param {string} [message="Не клеится дело-зови друга смело!"] The text message to print. Supports newline characters (\n).
 * @param {string} [fontFamily='Anton'] The font family for the text. Can be a web-safe font or a Google Font name.
 * @param {number} [fontSize=48] The font size in pixels.
 * @param {string} [fontColor='#FFFFFF'] The fill color of the text (e.g., hex, rgb, or color name).
 * @param {string} [strokeColor='#000000'] The outline color of the text.
 * @param {number} [strokeWidth=3] The width of the text outline. Set to 0 for no outline.
 * @param {string} [verticalAlign='bottom'] Vertical alignment of the text block: 'top', 'middle', or 'bottom'.
 * @param {string} [horizontalAlign='center'] Horizontal alignment of the text: 'left', 'center', or 'right'.
 * @param {number} [padding=20] The padding in pixels from the image edges for the text block.
 * @returns {Promise<HTMLCanvasElement>} A promise that resolves to a new canvas element with the image and text.
 */
async function processImage(
    originalImg,
    message = "Не клеится дело-зови друга смело!",
    fontFamily = 'Anton',
    fontSize = 48,
    fontColor = '#FFFFFF',
    strokeColor = '#000000',
    strokeWidth = 3,
    verticalAlign = 'bottom',
    horizontalAlign = 'center',
    padding = 20
) {
    // Ensure numeric parameters from user input are correctly typed.
    const numFontSize = Number(fontSize);
    const numStrokeWidth = Number(strokeWidth);
    const numPadding = Number(padding);
    let currentFontFamily = fontFamily;

    // --- FONT LOADING ---
    // List of common web-safe fonts that don't require dynamic loading.
    const webSafeFonts = ['Arial', 'Verdana', 'Helvetica', 'Georgia', 'Times New Roman', 'Courier New', 'Impact', 'Comic Sans MS'];

    // Dynamically load the font if it's not a common web-safe font.
    if (!webSafeFonts.some(safeFont => currentFontFamily.includes(safeFont))) {
        try {
            const fontUrl = `https://fonts.googleapis.com/css2?family=${currentFontFamily.replace(/ /g, '+')}&display=swap`;

            // Add the font's stylesheet to the document head if it's not already there.
            if (!document.querySelector(`link[href="${fontUrl}"]`)) {
                const link = document.createElement('link');
                link.href = fontUrl;
                link.rel = 'stylesheet';
                document.head.appendChild(link);
                // Wait for the stylesheet to load before proceeding.
                await new Promise((resolve, reject) => {
                    link.onload = resolve;
                    link.onerror = reject;
                });
            }
            // Use the FontFaceSet API to ensure the font is fully loaded and ready for canvas rendering.
            await document.fonts.load(`${numFontSize}px "${currentFontFamily}"`);
        } catch (error) {
            console.warn(`Could not load Google Font "${currentFontFamily}". Using 'Arial' as fallback.`, error);
            currentFontFamily = 'Arial'; // Revert to a safe font if loading fails.
        }
    }

    // --- CANVAS SETUP ---
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    canvas.width = originalImg.naturalWidth;
    canvas.height = originalImg.naturalHeight;
    ctx.drawImage(originalImg, 0, 0);

    // --- TEXT STYLING ---
    ctx.font = `${numFontSize}px "${currentFontFamily}"`;
    ctx.fillStyle = fontColor;
    ctx.strokeStyle = strokeColor;
    ctx.lineWidth = numStrokeWidth;
    ctx.textAlign = horizontalAlign.toLowerCase();
    ctx.textBaseline = 'top'; // Use a consistent baseline for simpler line position calculations.

    // --- TEXT WRAPPING ---
    const lines = [];
    if (message && message.trim() !== '') {
        const maxWidth = canvas.width > numPadding * 2 ? canvas.width - numPadding * 2 : canvas.width;
        const messageLines = message.trim().split('\n');

        messageLines.forEach(messageLine => {
            const words = messageLine.split(' ');
            if (words.length === 0) return;

            let currentLine = words[0] || '';
            for (let i = 1; i < words.length; i++) {
                const word = words[i];
                const testLine = currentLine + " " + word;
                if (ctx.measureText(testLine).width < maxWidth) {
                    currentLine = testLine;
                } else {
                    lines.push(currentLine);
                    currentLine = word;
                }
            }
            lines.push(currentLine);
        });
    } else {
        return canvas; // Return early if there's no message to draw
    }

    // --- POSITIONING & DRAWING ---
    const lineHeight = numFontSize * 1.2;
    // Calculate the total height of the text block for vertical alignment.
    const totalTextHeight = (lines.length - 1) * lineHeight + numFontSize;

    // Determine the starting Y-coordinate for the text block.
    let y;
    switch (verticalAlign.toLowerCase()) {
        case 'top':
            y = numPadding;
            break;
        case 'middle':
            y = (canvas.height - totalTextHeight) / 2;
            break;
        case 'bottom':
        default:
            y = canvas.height - totalTextHeight - numPadding;
            break;
    }

    // Determine the starting X-coordinate based on horizontal alignment.
    let x;
    switch (horizontalAlign.toLowerCase()) {
        case 'left':
            x = numPadding;
            break;
        case 'right':
            x = canvas.width - numPadding;
            break;
        case 'center':
        default:
            x = canvas.width / 2;
            break;
    }

    // Draw each line of the wrapped text.
    for (let i = 0; i < lines.length; i++) {
        const lineY = y + (i * lineHeight);
        // Draw the stroke (outline) first so it appears behind the fill.
        if (numStrokeWidth > 0) {
            ctx.strokeText(lines[i], x, lineY);
        }
        ctx.fillText(lines[i], x, lineY);
    }

    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 Text Print With Custom Message Tool allows users to overlay custom text messages onto images, with various styling options and precise positioning. This tool supports web-safe fonts as well as dynamic loading of Google Fonts, ensuring that users can choose their desired font style. The text is automatically wrapped to fit the image width and can handle newline characters, making it suitable for creating personalized graphics, social media posts, invitations, and other visual content. Users can customize attributes like font size, color, and alignment, making it a versatile solution for enhancing images with textual elements.

Leave a Reply

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