Please bookmark this page to avoid losing your image tool!

Image YTP Tennis Rounds Generator

(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,
    player2ImgUrl = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAiIGhlaWdodD0iMTAwIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCI+PHJlY3Qgd2lkdGg9IjEwMCIgaGVpZ2h0PSIxMDAiIGZpbGw9IiNjY2MiLz48dGV4dCB4PSI1MCIgeT0iNjAiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSI1MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzY2NiI+PzwvdGV4dD48L3N2Zz4=',
    player1Name = 'Player 1',
    player2Name = 'Player 2',
    roundNumber = 1,
    vsText = 'VS',
    fontFamily = 'Impact, sans-serif',
    textColor = '#FFFFFF',
    strokeColor = '#000000',
    backgroundColor = '#333333'
) {
    /**
     * Helper function to load an image from a URL and return a Promise.
     * This is needed to handle the asynchronous loading of the second player's image.
     * @param {string} src - The source URL or data URI of the image.
     * @returns {Promise<HTMLImageElement>} - A promise that resolves with the loaded Image object.
     */
    const loadImage = (src) => {
        return new Promise((resolve, reject) => {
            if (!src) {
                reject(new Error('Image source is empty.'));
                return;
            }
            const img = new Image();
            // Allow cross-origin images to be drawn on the canvas without tainting it.
            img.crossOrigin = 'Anonymous';
            img.onload = () => resolve(img);
            img.onerror = (err) => reject(new Error(`Failed to load image from src: ${src}`));
            img.src = src;
        });
    };

    // Asynchronously load the second player's image from the provided URL.
    let player2Img;
    try {
        player2Img = await loadImage(player2ImgUrl);
    } catch (error) {
        console.error("Could not load Player 2 image:", error);
        // If loading fails, use the default placeholder image (which is a safe data URI).
        player2Img = await loadImage('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAiIGhlaWdodD0iMTAwIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCI+PHJlY3Qgd2lkdGg9IjEwMCIgaGVpZ2h0PSIxMDAiIGZpbGw9IiNjY2MiLz48dGV4dCB4PSI1MCIgeT0iNjAiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSI1MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzY2NiI+PzwvdGV4dD48L3N2Zz4=');
    }

    // Create a canvas element to draw on. A 16:9 aspect ratio is common for video thumbnails.
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    const width = 1280;
    const height = 720;
    canvas.width = width;
    canvas.height = height;

    // 1. Draw the background color.
    ctx.fillStyle = backgroundColor;
    ctx.fillRect(0, 0, width, height);

    // 2. Draw the player avatars.
    const avatarSize = 320;
    const avatarY = height / 2 - avatarSize / 2; // Vertically centered
    const p1AvatarX = width * 0.25 - avatarSize / 2; // Centered at 1/4th of the width
    const p2AvatarX = width * 0.75 - avatarSize / 2; // Centered at 3/4ths of the width

    ctx.drawImage(originalImg, p1AvatarX, avatarY, avatarSize, avatarSize);
    if (player2Img) {
        ctx.drawImage(player2Img, p2AvatarX, avatarY, avatarSize, avatarSize);
    }

    /**
     * Helper function for drawing text with a stroke (outline).
     * @param {string} text - The text to draw.
     * @param {number} x - The x-coordinate of the text's anchor point.
     * @param {number} y - The y-coordinate of the text's anchor point.
     * @param {number} size - The font size in pixels.
     * @param {number} [maxWidth] - Optional maximum width for the text.
     */
    const drawStrokedText = (text, x, y, size, maxWidth) => {
        ctx.font = `${size}px ${fontFamily}`;
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        ctx.strokeStyle = strokeColor;
        ctx.fillStyle = textColor;
        // A thicker stroke looks better for this style.
        ctx.lineWidth = size / 8;

        // Draw the stroke first, then the fill on top.
        ctx.strokeText(text, x, y, maxWidth);
        ctx.fillText(text, x, y, maxWidth);
    };

    // 3. Draw all the text elements.
    // "Round X" text at the top and center.
    drawStrokedText(`Round ${roundNumber}`, width / 2, 90, 80);

    // "VS" text in the absolute center.
    drawStrokedText(vsText, width / 2, height / 2, 110);

    // Player names below their respective avatars.
    const nameY = avatarY + avatarSize + 55; // 55px gap below the avatar
    const nameSize = 60;
    const nameMaxWidth = width / 2 - 60; // Max width to prevent names from overlapping the center

    drawStrokedText(player1Name, width * 0.25, nameY, nameSize, nameMaxWidth);
    drawStrokedText(player2Name, width * 0.75, nameY, nameSize, nameMaxWidth);

    // Return the final canvas, which can be appended to the DOM or used to create an image.
    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 YTP Tennis Rounds Generator is an online tool designed to create dynamic visual representations for tennis match rounds. Users can input images of two players along with their names and round details to generate a formatted image that highlights the participants in a match. The tool is particularly useful for content creators, streamers, and fans who want to visually represent tennis competitions, whether for social media posts, video thumbnails, or promotional graphics. With customizable options for colors, text, and player images, it enables personalized and attractive visuals for tennis events.

Leave a Reply

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