Please bookmark this page to avoid losing your image tool!

Image Brave Deed 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.
function processImage(originalImg, title = "ОТВАЖНЫЙ ПОСТУПОК", subtitle = "Поступок, достойный уважения", titleColor = "#FFFFFF", subtitleColor = "#AAAAAA", bgColor = "#000000", frameColor = "#FFFFFF") {
    // Helper function to calculate text wrapping
    function getLines(context, text, maxWidth) {
        if (!text) return [];
        const words = text.split(' ');
        let line = '';
        let lines = [];
        for (let n = 0; n < words.length; n++) {
            let testLine = line + words[n] + ' ';
            let metrics = context.measureText(testLine);
            let testWidth = metrics.width;
            if (testWidth > maxWidth && n > 0) {
                lines.push(line.trim());
                line = words[n] + ' ';
            } else {
                line = testLine;
            }
        }
        if (line.trim() !== '') {
            lines.push(line.trim());
        }
        return lines;
    }

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

    // To prevent giant images from consuming too much memory/breaking the layout
    const MAX_WIDTH = 800;
    const MAX_HEIGHT = 800;
    let imgW = originalImg.width;
    let imgH = originalImg.height;

    // Scale down image proportionally if it exceeds bounds
    if (imgW > MAX_WIDTH || imgH > MAX_HEIGHT) {
        const ratio = Math.min(MAX_WIDTH / imgW, MAX_HEIGHT / imgH);
        imgW = Math.round(imgW * ratio);
        imgH = Math.round(imgH * ratio);
    }

    // Standard demotivator ("Brave Deed") visual calculations based on width
    const PADDING_SIDES = Math.max(40, Math.round(imgW * 0.12));
    const PADDING_TOP = PADDING_SIDES;
    const canvasWidth = imgW + PADDING_SIDES * 2;
    const maxTextWidth = canvasWidth - PADDING_SIDES * 1.5;

    // Responsive font sizing based on layout
    const titleFontSize = Math.max(24, Math.round(canvasWidth * 0.055));
    const subtitleFontSize = Math.max(16, Math.round(canvasWidth * 0.035));

    // Leverage canvas context default 300x150 just for calculating text height
    ctx.font = `${titleFontSize}px "Times New Roman", Times, serif`;
    const titleLines = getLines(ctx, title, maxTextWidth);
    const titleHeight = titleLines.length > 0 ? titleLines.length * (titleFontSize * 1.2) : 0;

    ctx.font = `${subtitleFontSize}px Arial, sans-serif`;
    const subtitleLines = getLines(ctx, subtitle, maxTextWidth);
    const subtitleHeight = subtitleLines.length > 0 ? subtitleLines.length * (subtitleFontSize * 1.3) : 0;

    // Gaps and overall height calculation
    const topTextGap = Math.round(PADDING_TOP * 0.5);
    const textGap = (titleLines.length > 0 && subtitleLines.length > 0) ? 15 : 0;
    const bottomTextGap = Math.max(30, PADDING_SIDES);

    let PADDING_BOTTOM = bottomTextGap;
    if (titleLines.length > 0 || subtitleLines.length > 0) {
        PADDING_BOTTOM = topTextGap + titleHeight + textGap + subtitleHeight + bottomTextGap;
    }

    // Set real canvas dimensions which resets previously set context styles
    canvas.width = canvasWidth;
    canvas.height = PADDING_TOP + imgH + PADDING_BOTTOM;

    // Draw Background
    ctx.fillStyle = bgColor;
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    // Draw Base Image
    ctx.drawImage(originalImg, PADDING_SIDES, PADDING_TOP, imgW, imgH);

    // Draw Classic Meme Thin Border Frame Around the Image
    const frameGap = Math.max(3, Math.round(imgW * 0.015));
    const frameThick = Math.max(1, Math.round(imgW * 0.004));
    
    ctx.strokeStyle = frameColor;
    ctx.lineWidth = frameThick;
    ctx.strokeRect(
        PADDING_SIDES - frameGap - frameThick / 2,
        PADDING_TOP - frameGap - frameThick / 2,
        imgW + frameGap * 2 + frameThick,
        imgH + frameGap * 2 + frameThick
    );

    // Draw Multiline Texts
    let currentY = PADDING_TOP + imgH + topTextGap;
    ctx.textAlign = 'center';
    ctx.textBaseline = 'top';

    // Output Title Text
    if (titleLines.length > 0) {
        ctx.font = `${titleFontSize}px "Times New Roman", Times, serif`;
        ctx.fillStyle = titleColor;
        titleLines.forEach(line => {
            ctx.fillText(line, canvas.width / 2, currentY);
            currentY += titleFontSize * 1.2;
        });
    }

    currentY += textGap;

    // Output Subtitle Text
    if (subtitleLines.length > 0) {
        ctx.font = `${subtitleFontSize}px Arial, sans-serif`;
        ctx.fillStyle = subtitleColor;
        subtitleLines.forEach(line => {
            ctx.fillText(line, canvas.width / 2, currentY);
            currentY += subtitleFontSize * 1.3;
        });
    }

    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 Brave Deed Generator allows you to transform your photos into classic demotivational-style meme images. The tool overlays a title and subtitle onto your image, featuring a framed layout with customizable text colors, subtitle colors, and background colors. This is ideal for creating humorous social media posts, personalized memes, or decorative digital content with a vintage internet aesthetic.

Leave a Reply

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