Please bookmark this page to avoid losing your image tool!

Image Verbs Reference 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, numberOfVerbs = 10, fontFamily = 'Roboto', fontSize = 24, textColor = '#333333') {

    /**
     * Dynamically loads a font from Google Fonts if it's not a standard web-safe font.
     * This ensures that Cyrillic characters are displayed correctly.
     * @param {string} family - The font family name.
     * @param {number} size - The font size, needed for the Font Loading API.
     * @returns {Promise<string>} The effective font family name (original or fallback).
     */
    const loadFont = async (family, size) => {
        const webSafeFonts = ['Arial', 'Verdana', 'Helvetica', 'Tahoma', 'Trebuchet MS', 'Times New Roman', 'Georgia', 'Garamond', 'Courier New', 'Brush Script MT'];
        // Check if the font is a common web-safe font
        if (webSafeFonts.find(f => f.toLowerCase() === family.toLowerCase())) {
            return family;
        }

        // If not web-safe, assume it's a Google Font and try to load it.
        const fontId = `google-font-stylesheet-${family.replace(/\s+/g, '-')}`;
        try {
            if (!document.getElementById(fontId)) {
                const fontName = family.replace(/\s+/g, '+');
                const url = `https://fonts.googleapis.com/css2?family=${fontName}:wght@400;700&display=swap`;
                const link = document.createElement('link');
                link.id = fontId;
                link.href = url;
                link.rel = 'stylesheet';
                document.head.appendChild(link);
            }
            // Use the Font Loading API to wait until the font is ready.
            await document.fonts.load(`${size}px ${family}`);
            return family;
        } catch (e) {
            console.warn(`Could not load Google Font "${family}". Falling back to 'Arial'.`, e);
            return 'Arial'; // Fallback to a reliable web-safe font
        }
    };

    // Ensure the specified font is loaded before we start measuring text.
    const effectiveFontFamily = await loadFont(fontFamily, fontSize);

    // A predefined list of evocative Russian verbs ("Глаголы").
    const verbs = [
        'Смотреть', 'Думать', 'Чувствовать', 'Бежать', 'Лететь',
        'Создавать', 'Разрушать', 'Помнить', 'Забывать', 'Расти',
        'Падать', 'Начинать', 'Заканчивать', 'Любить', 'Ждать',
        'Надеяться', 'Мечтать', 'Открывать', 'Закрывать', 'Искать',
        'Находить', 'Менять', 'Строить', 'Дышать', 'Жить',
        'Петь', 'Танцевать', 'Говорить', 'Молчать', 'Смеяться',
        'Плакать', 'Улыбаться', 'Играть', 'Прятать', 'Светить',
        'Слушать', 'Держать', 'Касаться', 'Верить', 'Терять'
    ];

    // Helper function to get N random unique items from an array.
    const getRandomItems = (arr, n) => {
        const shuffled = [...arr].sort(() => 0.5 - Math.random());
        return shuffled.slice(0, Math.min(n, arr.length));
    };

    const selectedVerbs = getRandomItems(verbs, numberOfVerbs);

    // Create a canvas to draw the final result.
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    // --- Layout Calculations ---

    // 1. Calculate scaled image dimensions to fit within a max boundary.
    let imgWidth = originalImg.naturalWidth;
    let imgHeight = originalImg.naturalHeight;
    const maxDim = 500;
    if (imgWidth > maxDim || imgHeight > maxDim) {
        if (imgWidth > imgHeight) {
            imgHeight = (maxDim / imgWidth) * imgHeight;
            imgWidth = maxDim;
        } else {
            imgWidth = (maxDim / imgHeight) * imgWidth;
            imgHeight = maxDim;
        }
    }

    // 2. Calculate dimensions required for the text block.
    ctx.font = `${fontSize}px ${effectiveFontFamily}`;
    const textMetrics = selectedVerbs.map(verb => ctx.measureText(verb));
    const maxTextWidth = Math.max(...textMetrics.map(m => m.width));
    const lineHeight = fontSize * 1.5;
    const textBlockHeight = lineHeight * selectedVerbs.length;
    
    // 3. Determine final canvas dimensions with padding and spacing.
    const padding = 25;
    const gap = 25;
    canvas.width = padding + imgWidth + gap + maxTextWidth + padding;
    canvas.height = padding + Math.max(imgHeight, textBlockHeight) + padding;

    // --- Drawing Operations ---

    // 1. Draw a background.
    ctx.fillStyle = '#ffffff';
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    // 2. Draw the image. It's vertically centered relative to the overall height.
    const contentHeight = Math.max(imgHeight, textBlockHeight);
    const imageY = padding + (contentHeight - imgHeight) / 2;
    ctx.drawImage(originalImg, padding, imageY, imgWidth, imgHeight);

    // 3. Draw the verbs. The entire text block is vertically centered.
    ctx.fillStyle = textColor;
    ctx.font = `${fontSize}px ${effectiveFontFamily}`;
    ctx.textAlign = 'left';
    ctx.textBaseline = 'middle';
    
    const textStartX = padding + imgWidth + gap;
    const textStartY = padding + (contentHeight - textBlockHeight) / 2;

    selectedVerbs.forEach((verb, index) => {
        const y = textStartY + (index * lineHeight) + (lineHeight / 2);
        ctx.fillText(verb, textStartX, y);
    });

    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 Verbs Reference Tool allows users to enhance images by adding a selection of evocative Russian verbs in a visually appealing layout. Users can upload an image and specify the number of verbs to include, along with font preferences. This tool is particularly useful for language learners, educators, or creative professionals who wish to combine imagery with text to convey themes or emotions, make educational materials, or create visually engaging social media content.

Leave a Reply

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