Please bookmark this page to avoid losing your image tool!

Image Subtitle Creator For Movies

(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,
    text = 'Your subtitle text here.\nUse \\n for a new line.',
    fontFamily = 'Impact', // Can be a web-safe font or a Google Font name like 'Roboto'
    fontSize = 60, // Base font size for a 1920px wide image
    fontColor = '#FFFFFF',
    strokeColor = '#000000',
    strokeWidth = 5, // Base stroke width for a 1920px wide image
    positionY = 8, // Percentage from the bottom of the image
    backgroundColor = 'rgba(0, 0, 0, 0)' // e.g., 'rgba(0, 0, 0, 0.5)' for a background bar
) {

    /**
     * Helper function to dynamically load a font from Google Fonts.
     * @param {string} font - The name of the font family.
     */
    const loadFont = async (font) => {
        const genericFamilies = ['serif', 'sans-serif', 'monospace', 'cursive', 'fantasy', 'system-ui'];
        if (!font || genericFamilies.includes(font.toLowerCase())) {
            return;
        }

        if (document.fonts.check(`12px "${font}"`)) {
            return;
        }

        try {
            const fontUrl = `https://fonts.googleapis.com/css2?family=${font.replace(/ /g, '+')}:wght@400;700&display=swap`;
            const style = document.createElement('style');
            style.id = `google-font-${font.replace(/ /g, '-')}`;
            style.innerHTML = `@import url('${fontUrl}');`;

            // Avoid re-adding the same style element
            if (!document.getElementById(style.id)) {
                document.head.appendChild(style);
                await document.fonts.load(`bold 12px "${font}"`);
                await document.fonts.ready;
            }
        } catch (e) {
            console.warn(`Could not load font face "${font}". The browser will use a fallback font.`, e);
        }
    };

    await loadFont(fontFamily);

    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    canvas.width = originalImg.naturalWidth;
    canvas.height = originalImg.naturalHeight;

    ctx.drawImage(originalImg, 0, 0);

    // Scale font and stroke based on image width relative to a 1920px HD standard
    const scaleFactor = canvas.width / 1920;
    const scaledFontSize = Math.round(fontSize * scaleFactor);
    const scaledStrokeWidth = Math.max(1, Math.round(strokeWidth * scaleFactor));

    const lines = text.split('\n');
    const lineHeight = scaledFontSize * 1.25;
    ctx.font = `bold ${scaledFontSize}px "${fontFamily}", sans-serif`;
    ctx.textAlign = 'center';
    ctx.textBaseline = 'bottom';
    ctx.lineJoin = 'round'; // For smoother stroke corners

    const totalTextBlockHeight = (lines.length - 1) * lineHeight + scaledFontSize;

    // Calculate the coordinates for the text
    const x = canvas.width / 2;
    const bottomMargin = (canvas.height * positionY) / 100;
    let currentY = canvas.height - bottomMargin;

    // Check if background color is set and visible
    const hasBackground = (() => {
        if (!backgroundColor || backgroundColor === 'transparent') return false;
        // Check for rgba/rgb alpha value of 0
        const match = backgroundColor.match(/rgba?\(.*?,\s*([\d.]+)\)/);
        if (match && parseFloat(match[1]) === 0) {
            return false;
        }
        return true;
    })();

    if (hasBackground) {
        // Measure text width for background sizing
        let maxTextWidth = 0;
        lines.forEach(line => {
            const metrics = ctx.measureText(line);
            if (metrics.width > maxTextWidth) {
                maxTextWidth = metrics.width;
            }
        });

        // Add some padding around the text for the background
        const bgPaddingX = scaledFontSize * 0.4;
        const bgPaddingY = scaledFontSize * 0.2;

        const bgWidth = maxTextWidth + (bgPaddingX * 2);
        const bgHeight = totalTextBlockHeight + (bgPaddingY * 2);

        const bgX = x - (bgWidth / 2);
        const bgY = (currentY - totalTextBlockHeight) - bgPaddingY;

        ctx.fillStyle = backgroundColor;
        ctx.fillRect(bgX, bgY, bgWidth, bgHeight);
    }

    // Draw the text lines, starting from the last line and moving upwards
    for (let i = lines.length - 1; i >= 0; i--) {
        const line = lines[i];

        // Apply stroke (outline)
        if (scaledStrokeWidth > 0) {
            ctx.strokeStyle = strokeColor;
            ctx.lineWidth = scaledStrokeWidth;
            ctx.strokeText(line, x, currentY);
        }

        // Apply fill (main color)
        ctx.fillStyle = fontColor;
        ctx.fillText(line, x, currentY);

        // Move the Y-coordinate up for the next line
        currentY -= lineHeight;
    }

    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 Subtitle Creator for Movies is a versatile online tool that enables users to add customizable text subtitles to images. Ideal for filmmakers, content creators, or anyone looking to enhance their visual media with text overlay, this tool allows for adjustments in font family, size, color, stroke, and position. Users can easily input their desired subtitle text, split it across multiple lines, and choose different background styles for better visibility. This tool is perfect for creating engaging promotional materials, social media posts, or enhancing viewing experiences for video content.

Leave a Reply

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