Please bookmark this page to avoid losing your image tool!

Photo Reflection Insight 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, text = "No vuelvo a molestar a nadie, ya entiendo que con nadie cuento, solo conmigo", fontColor = "#FFFFFF", fontSize = 50, fontName = "Caveat", reflectionHeightRatio = 0.4, reflectionGap = 2) {

    /**
     * Dynamically loads a font from Google Fonts.
     * @param {string} name The CSS font-family name.
     * @param {string} url The URL to the font file (e.g., woff2).
     */
    const loadFont = async (name, url) => {
        try {
            const font = new FontFace(name, `url(${url})`);
            await font.load();
            document.fonts.add(font);
        } catch (e) {
            console.error(`Font "${name}" could not be loaded from ${url}. Using system default.`, e);
        }
    };

    /**
     * Calculates the lines for wrapping text to fit a max width.
     * @param {CanvasRenderingContext2D} context The canvas context.
     * @param {string} text The text to wrap.
     * @param {number} maxWidth The maximum width for a line.
     * @returns {string[]} An array of strings, where each string is a line.
     */
    const getWrappedLines = (context, text, maxWidth) => {
        const words = text.split(' ');
        const lines = [];
        let currentLine = words[0] || '';

        for (let i = 1; i < words.length; i++) {
            const word = words[i];
            const testLine = currentLine + " " + word;
            const metrics = context.measureText(testLine);
            if (metrics.width > maxWidth) {
                lines.push(currentLine);
                currentLine = word;
            } else {
                currentLine = testLine;
            }
        }
        lines.push(currentLine);
        return lines;
    };

    // Use a handwriting-style font for the "insight" text.
    // Caveat is a free Google Font.
    await loadFont(fontName, 'https://fonts.gstatic.com/s/caveat/v18/WnznHAc5bAfAsKJWk15j7x0.woff2');

    // 1. Create canvas and context
    const reflectionHeight = originalImg.height * reflectionHeightRatio;
    const canvas = document.createElement('canvas');
    canvas.width = originalImg.width;
    canvas.height = originalImg.height + reflectionGap + reflectionHeight;
    const ctx = canvas.getContext('2d');

    // 2. Draw the main image
    ctx.drawImage(originalImg, 0, 0, originalImg.width, originalImg.height);

    // 3. Create and draw the reflection
    ctx.save();
    const reflectionYStart = originalImg.height + reflectionGap;
    // Move the origin to the bottom of the original image, flip the context vertically
    ctx.translate(0, originalImg.height);
    ctx.scale(1, -1);
    // Draw the image upside down, starting from its "new" top, which is its old bottom
    // We clip the drawing to ensure it doesn't extend beyond the original image dimensions
    // The reflection will be drawn from y=originalImg.height to y=2*originalImg.height
    ctx.drawImage(originalImg, 0, -originalImg.height, originalImg.width, originalImg.height);
    ctx.restore();

    // 4. Apply a gradient to make the reflection fade out
    ctx.save();
    // Use 'destination-in' to apply the gradient as a mask on the existing reflection
    ctx.globalCompositeOperation = 'destination-in';
    const gradient = ctx.createLinearGradient(0, reflectionYStart, 0, canvas.height);
    gradient.addColorStop(0, 'rgba(0, 0, 0, 0.5)'); // Reflection starts at 50% opacity
    gradient.addColorStop(0.8, 'rgba(0, 0, 0, 0)'); // Fades to 0% opacity
    ctx.fillStyle = gradient;
    ctx.fillRect(0, reflectionYStart, canvas.width, reflectionHeight);
    ctx.restore();

    // 5. Prepare and render the text
    ctx.font = `${fontSize}px "${fontName}"`;
    const textMaxWidth = canvas.width * 0.9;
    const lines = getWrappedLines(ctx, text, textMaxWidth);
    const lineHeight = fontSize * 1.2;
    const textBlockHeight = (lines.length - 1) * lineHeight;
    
    // Position the text block vertically centered in the bottom third of the image
    const textStartY = originalImg.height - textBlockHeight - (fontSize * 1.5);

    // Style the text for better readability
    ctx.fillStyle = fontColor;
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.shadowColor = 'rgba(0, 0, 0, 0.8)';
    ctx.shadowOffsetX = 2;
    ctx.shadowOffsetY = 2;
    ctx.shadowBlur = 4;

    const x = canvas.width / 2;
    lines.forEach((line, index) => {
        ctx.fillText(line, x, textStartY + (index * 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 Photo Reflection Insight Tool allows users to create visually stunning images with a reflected effect. By simply uploading an image, users can generate a reflection that fades out gracefully below the original image. Additionally, the tool enables users to overlay customized text on the image, choosing the font style, size, and color, which can be particularly useful for creating personalized photo quotes, social media posts, or artistic presentations. The flexibility to adjust the height of the reflection and the gap between the image and its reflection provides further enhancement to the visual appeal. This tool is ideal for graphic designers, marketers, and anyone looking to enhance their images with elegant text and reflection effects.

Leave a Reply

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