Please bookmark this page to avoid losing your image tool!

Image To Cake 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, text = "А как же торт?", bodyColor = "#F5DEB3", icingColor = "#FFF0F5", numCandles = 3) {
    numCandles = parseInt(numCandles) || 0;

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

    // 1. Draw festive background
    ctx.fillStyle = "#e0f7fa";
    ctx.fillRect(0, 0, width, height);

    // Add confetti/sprinkles in background
    const confettiColors = ["#FF69B4", "#33CC33", "#6666FF", "#FFCC00", "#FF9900", "#FF3333"];
    for (let i = 0; i < 200; i++) {
        let spX = Math.random() * width;
        let spY = Math.random() * height;
        let spW = Math.random() * 8 + 4;
        let spH = Math.random() * 4 + 2;
        
        ctx.save();
        ctx.translate(spX, spY);
        ctx.rotate(Math.random() * Math.PI);
        ctx.fillStyle = confettiColors[Math.floor(Math.random() * confettiColors.length)];
        ctx.fillRect(-spW / 2, -spH / 2, spW, spH);
        ctx.restore();
    }

    // Cake geometrical setups
    const cx = 400; // Center X
    const cy = 550; // Center Y at bottom of cake
    const rx = 260; // Radius X (Width)
    const ry = 100; // Radius Y (Perspective Depth)
    const h = 200;  // Height of the cake
    const ty = cy - h;// Top Y position

    // 2. Draw cake plate
    ctx.fillStyle = "#fcfcfc";
    ctx.beginPath();
    ctx.ellipse(cx, cy + 15, rx + 60, ry + 30, 0, 0, Math.PI * 2);
    ctx.fill();
    ctx.strokeStyle = "#cccccc";
    ctx.lineWidth = 4;
    ctx.stroke();

    // 3. Draw cake base (cylinder body)
    ctx.fillStyle = bodyColor;
    ctx.beginPath();
    // Bottom ellipse
    ctx.ellipse(cx, cy, rx, ry, 0, 0, Math.PI * 2);
    ctx.fill();
    // Body rectangle
    ctx.fillRect(cx - rx, ty, rx * 2, h);

    // 4. Draw cake filling/layer (a dark stripe in the middle)
    ctx.fillStyle = "#8b4513"; // Chocolate filling
    ctx.beginPath();
    ctx.ellipse(cx, cy - h / 2, rx, ry, 0, 0, Math.PI, false);
    ctx.lineTo(cx - rx, cy - h / 2 - 12);
    ctx.ellipse(cx, cy - h / 2 - 12, rx, ry, 0, Math.PI, 0, true);
    ctx.fill();

    // 5. Draw Image on top as photo icing (clipped to top ellipse)
    ctx.save();
    ctx.beginPath();
    ctx.ellipse(cx, ty, rx, ry, 0, 0, Math.PI * 2);
    ctx.clip(); // Clip everything drawn next to this top surface

    // Calculate object-fit: cover logic for the ellipse constraints
    const imgRatio = originalImg.width / originalImg.height;
    const areaRatio = rx / ry; 
    let sw = originalImg.width, sh = originalImg.height;
    let sx = 0, sy = 0;
    
    if (imgRatio > areaRatio) {
        sw = originalImg.height * areaRatio;
        sx = (originalImg.width - sw) / 2;
    } else {
        sh = originalImg.width / areaRatio;
        sy = (originalImg.height - sh) / 2;
    }

    ctx.drawImage(originalImg, sx, sy, sw, sh, cx - rx, ty - ry, rx * 2, ry * 2);
    
    // Add a slight lightening overlay to blend it like icing
    ctx.fillStyle = "rgba(255,255,255,0.15)";
    ctx.fillRect(cx - rx, ty - ry, rx * 2, ry * 2);
    ctx.restore();

    // 6. Draw icing decorations (drips around the top edge)
    ctx.fillStyle = icingColor;
    
    // Front half drips
    for (let i = 0; i <= 120; i++) {
        let t = (i / 120) * Math.PI; // 0 to PI
        let scX = cx + rx * Math.cos(t);
        let scY = ty + ry * Math.sin(t);
        
        // Random but deterministic drip lengths
        let dripLength = 25 + Math.sin(i * 12345) * 20; 
        
        ctx.beginPath();
        ctx.arc(scX, scY, 18, 0, Math.PI * 2);
        ctx.fill();
        
        // Drip going down
        ctx.fillRect(scX - 10, scY, 20, dripLength);
        ctx.beginPath();
        ctx.arc(scX, scY + dripLength, 10, 0, Math.PI * 2);
        ctx.fill();
    }

    // Top border piping framing the photo
    for (let i = 0; i <= 200; i++) {
        let t = (i / 200) * Math.PI * 2; 
        let scX = cx + (rx - 10) * Math.cos(t);
        let scY = ty + (ry - 10) * Math.sin(t);
        ctx.beginPath();
        ctx.arc(scX, scY, 12, 0, Math.PI * 2);
        ctx.fill();
    }

    // Bottom border piping
    for (let i = 0; i <= 100; i++) {
        let t = (i / 100) * Math.PI; 
        let scX = cx + rx * Math.cos(t);
        let scY = cy + ry * Math.sin(t);
        ctx.beginPath();
        ctx.arc(scX, scY, 16, 0, Math.PI * 2);
        ctx.fill();
    }

    // 7. Draw candles
    if (numCandles > 0) {
        for (let k = 0; k < numCandles; k++) {
            let cRx = rx * 0.7; // Place along an inner arc
            
            // Distribute evenly
            let candleX = cx;
            if (numCandles > 1) {
                candleX = cx - cRx + (2 * cRx * k) / (numCandles - 1);
            }
            let candleY = ty - 15 + Math.sin(k * 7) * 15; // slight staggered Y effect
            
            // Candle Base
            ctx.fillStyle = (k % 2 === 0) ? "#FF4500" : "#00CED1"; // Alternating red & cyan
            ctx.fillRect(candleX - 8, candleY - 60, 16, 60);
            
            // Candle Stripes
            ctx.strokeStyle = "#FFFFFF";
            ctx.lineWidth = 3;
            ctx.beginPath();
            ctx.moveTo(candleX - 8, candleY - 45);
            ctx.lineTo(candleX + 8, candleY - 55);
            ctx.moveTo(candleX - 8, candleY - 25);
            ctx.lineTo(candleX + 8, candleY - 35);
            ctx.moveTo(candleX - 8, candleY - 5);
            ctx.lineTo(candleX + 8, candleY - 15);
            ctx.stroke();

            // Wick
            ctx.fillStyle = "#333333";
            ctx.fillRect(candleX - 1.5, candleY - 70, 3, 10);

            // Flame (outer)
            ctx.fillStyle = "#FFD700";
            ctx.beginPath();
            ctx.moveTo(candleX, candleY - 90);
            ctx.quadraticCurveTo(candleX + 12, candleY - 70, candleX, candleY - 70);
            ctx.quadraticCurveTo(candleX - 12, candleY - 70, candleX, candleY - 90);
            ctx.fill();
            
            // Flame (inner)
            ctx.fillStyle = "#FFA500";
            ctx.beginPath();
            ctx.moveTo(candleX, candleY - 83);
            ctx.quadraticCurveTo(candleX + 6, candleY - 70, candleX, candleY - 70);
            ctx.quadraticCurveTo(candleX - 6, candleY - 70, candleX, candleY - 83);
            ctx.fill();
        }
    }

    // 8. Draw "А как же торт?" Text
    if (text) {
        ctx.font = "bold 56px 'Trebuchet MS', 'Arial Black', sans-serif";
        ctx.textAlign = "center";
        ctx.textBaseline = "middle";
        
        let textY = cy + ry + 85; 

        // Shadow/Border
        ctx.fillStyle = "#881144";
        ctx.fillText(text, (width / 2) + 4, textY + 4);
        
        // Fill
        ctx.fillStyle = "#ff5588";
        ctx.fillText(text, width / 2, textY);
    }

    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 To Cake Generator is a creative tool that transforms any uploaded photo into a festive digital cake graphic. It overlays your image onto the top of a stylized cake, complete with customizable icing colors, cake body tones, and a choice of candles. The tool also allows you to add personalized celebratory text and features a decorative background with confetti. This is ideal for creating fun, themed digital greetings, social media posts for birthdays, or whimsical celebratory images.

Leave a Reply

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