Please bookmark this page to avoid losing your image tool!

Dark Modern Japanese Carry Trade Educational Carousel Image 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, 
    title = "The Japanese\nCarry Trade", 
    content = "Investors borrow Yen at near 0% interest to buy higher-yielding assets globally. When the Yen strengthens abruptly, this massive leveraged trade violently unwinds across global markets.",
    slideIndex = 1,
    totalSlides = 5,
    accentColor = "#FF3344",
    brandHandle = "@macro.finance"
) {
    // 1. Setup Canvas (Instagram Carousel Portrait Size)
    const width = 1080;
    const height = 1350;
    const canvas = document.createElement('canvas');
    canvas.width = width;
    canvas.height = height;
    const ctx = canvas.getContext('2d');

    // 2. Load Google Fonts
    const fontFamily = 'Space Grotesk';
    if (!document.getElementById('carousel-font')) {
        const link = document.createElement('link');
        link.id = 'carousel-font';
        link.href = `https://fonts.googleapis.com/css2?family=${fontFamily.replace(' ', '+')}:wght@400;700;800&display=swap`;
        link.rel = 'stylesheet';
        document.head.appendChild(link);
    }

    try {
        await Promise.race([
            document.fonts.load(`800 100px "${fontFamily}"`),
            document.fonts.load(`400 48px "${fontFamily}"`),
            new Promise(resolve => setTimeout(resolve, 2000)) // 2s timeout fallback
        ]);
    } catch (e) {
        console.warn("Font loading error/timeout. Falling back to sans-serif.");
    }

    const fontBase = `"${fontFamily}", sans-serif`;

    // 3. Draw Deep Background (Dark Modern Finance aesthetic)
    ctx.fillStyle = '#090A0F';
    ctx.fillRect(0, 0, width, height);

    // 4. Draw Background Image and Blend
    if (originalImg && originalImg.width > 0) {
        ctx.globalAlpha = 0.15; // Low opacity for darkness
        ctx.globalCompositeOperation = 'luminosity'; // Grayscale-like atmospheric blend
        
        const scale = Math.max(width / originalImg.width, height / originalImg.height);
        const imgW = originalImg.width * scale;
        const imgH = originalImg.height * scale;
        const x = (width - imgW) / 2;
        const y = (height - imgH) / 2;
        
        ctx.drawImage(originalImg, x, y, imgW, imgH);
        
        ctx.globalAlpha = 1.0;
        ctx.globalCompositeOperation = 'source-over';
    }

    // 5. Draw Decorative Elements (Trading/Japanese Motif)
    
    // Abstract Candle Stick Motif
    ctx.globalAlpha = 0.04;
    ctx.fillStyle = '#FFFFFF';
    for(let i=0; i<18; i++) {
        let cx = 50 + i * 60;
        let cY = 800 + Math.sin(i) * 150 - 50;
        let cHeight = 80 + Math.cos(i*2) * 100;
        // Wick
        ctx.fillRect(cx + 8, cY - 30, 4, cHeight + 60);
        // Body (Red or Green concept, but white for wireframe look)
        ctx.fillRect(cx, cY, 20, cHeight);
    }
    ctx.globalAlpha = 1.0;

    // Glowing Accent Circle (Subtle Japanese Sun)
    ctx.globalAlpha = 0.1;
    let gradient = ctx.createRadialGradient(width - 100, 250, 0, width - 100, 250, 400);
    gradient.addColorStop(0, accentColor);
    gradient.addColorStop(1, 'transparent');
    ctx.fillStyle = gradient;
    ctx.fillRect(width - 500, 0, 500, 650);
    ctx.globalAlpha = 1.0;

    // Giant faint Yen symbol 
    ctx.fillStyle = 'rgba(255, 255, 255, 0.02)';
    ctx.font = `800 800px ${fontBase}`;
    ctx.fillText("¥", width - 600, height - 100);

    // Minimalist finance Grid
    ctx.strokeStyle = 'rgba(255, 255, 255, 0.03)';
    ctx.lineWidth = 1;
    for(let i = 0; i <= width; i += 120) {
        ctx.beginPath(); ctx.moveTo(i, 0); ctx.lineTo(i, height); ctx.stroke();
    }
    for(let i = 0; i <= height; i += 120) {
        ctx.beginPath(); ctx.moveTo(0, i); ctx.lineTo(width, i); ctx.stroke();
    }

    // 6. Draw UI Elements (Carousel Navigator)
    
    // Swipe indicator text
    ctx.fillStyle = accentColor;
    ctx.font = `800 24px ${fontBase}`;
    ctx.letterSpacing = "4px"; // Standard canvas API support varies, manual spacing simulation if needed, but modern browsers support
    if (ctx.letterSpacing !== undefined) ctx.letterSpacing = "4px";
    
    const navText = `SLIDE ${String(slideIndex).padStart(2, '0')}`;
    ctx.fillText(navText, 100, 160);
    if (ctx.letterSpacing !== undefined) ctx.letterSpacing = "0px";

    // Progress bar components
    const barWidth = 880;
    const barY = 190;
    ctx.fillStyle = 'rgba(255, 255, 255, 0.15)';
    ctx.fillRect(100, barY, barWidth, 4);
    
    ctx.fillStyle = accentColor;
    const progressWidth = barWidth * (slideIndex / totalSlides);
    ctx.fillRect(100, barY, progressWidth, 4);
    
    // Total slides dots or markers
    ctx.fillStyle = '#090A0F';
    for(let i = 1; i < totalSlides; i++) {
        let markerX = 100 + (barWidth * (i / totalSlides));
        ctx.fillRect(markerX - 2, barY, 4, 4);
    }

    // 7. Typography (Text Layout Helper)
    function wrapText(context, text, x, y, maxWidth, lineHeight, isTitle = false) {
        let paragraphs = text.split('\n');
        let currentY = y;
        
        for (let p = 0; p < paragraphs.length; p++) {
            let words = paragraphs[p].trim().split(' ');
            let line = '';
            
            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) {
                    context.fillText(line, x, currentY);
                    line = words[n] + ' ';
                    currentY += lineHeight;
                } else {
                    line = testLine;
                }
            }
            context.fillText(line, x, currentY);
            currentY += lineHeight;
        }
        return currentY;
    }

    // Draw Title
    ctx.fillStyle = '#FFFFFF';
    ctx.font = `800 90px ${fontBase}`;
    let titleEndY = wrapText(ctx, title, 100, 360, 880, 105, true);

    // Decorative Separator Line
    ctx.fillStyle = accentColor;
    ctx.fillRect(100, titleEndY + 20, 150, 8);

    // Draw Content Body
    ctx.fillStyle = '#B0B5C0'; // Modern cool-gray
    ctx.font = `400 44px ${fontBase}`;
    wrapText(ctx, content, 100, titleEndY + 120, 880, 68);

    // 8. Footer (Brand Handle and Save Icon)
    const footerY = height - 100;
    
    // Handle
    ctx.fillStyle = '#FFFFFF';
    ctx.font = `700 28px ${fontBase}`;
    ctx.fillText(String(brandHandle), 100, footerY);

    // "Swipe" or "Save" prompt depending on slide index
    ctx.fillStyle = 'rgba(255, 255, 255, 0.4)';
    const ctaText = slideIndex === totalSlides ? "SAVE POST" : "SWIPE";
    ctx.font = `700 24px ${fontBase}`;
    if (ctx.letterSpacing !== undefined) ctx.letterSpacing = "2px";
    ctx.fillText(ctaText, width - 260, footerY);
    if (ctx.letterSpacing !== undefined) ctx.letterSpacing = "0px";

    // Draw Save Ribbon/Icon
    ctx.beginPath();
    const iconX = width - 110;
    const iconY = footerY - 22;
    ctx.moveTo(iconX, iconY);
    ctx.lineTo(iconX + 24, iconY);
    ctx.lineTo(iconX + 24, iconY + 32);
    ctx.lineTo(iconX + 12, iconY + 22);
    ctx.lineTo(iconX, iconY + 32);
    ctx.closePath();
    ctx.strokeStyle = 'rgba(255, 255, 255, 0.5)';
    ctx.lineWidth = 2.5;
    ctx.lineJoin = 'round';
    ctx.stroke();

    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

This tool generates high-quality, professional social media carousel images designed with a dark, modern finance aesthetic. It allows users to create multi-slide educational content by overlaying custom titles, body text, and branding onto background images. The generator automatically applies sophisticated design elements such as typographic layouts, progress indicators, decorative financial motifs (like candlestick patterns and currency symbols), and accent colors. It is ideal for finance educators, macro analysts, and content creators looking to produce polished, Instagram-ready portrait-sized carousels for explaining complex economic topics.

Leave a Reply

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