Please bookmark this page to avoid losing your image tool!

Friendly Race Image Maker

(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, eventName = "ДРУЖЕСКАЯ ГОНКА", speedValue = 180, gearValue = 5, lapText = "3/3", rivalDistance = 50) {
    const TARGET_W = 1280;
    const TARGET_H = 720;
    
    // Create the canvas context
    const canvas = document.createElement("canvas");
    canvas.width = TARGET_W;
    canvas.height = TARGET_H;
    const ctx = canvas.getContext("2d");

    // Helper function for drawing rounded rectangles safely
    function drawRoundRect(ctx, x, y, w, h, r) {
        if (w < 2 * r) r = w / 2;
        if (h < 2 * r) r = h / 2;
        ctx.beginPath();
        ctx.moveTo(x + r, y);
        ctx.arcTo(x + w, y, x + w, y + h, r);
        ctx.arcTo(x + w, y + h, x, y + h, r);
        ctx.arcTo(x, y + h, x, y, r);
        ctx.arcTo(x, y, x + w, y, r);
        ctx.closePath();
    }

    // 1. Draw the actual original image (scaled to COVER the 16:9 canvas)
    const scale = Math.max(TARGET_W / originalImg.width, TARGET_H / originalImg.height);
    const w = originalImg.width * scale;
    const h = originalImg.height * scale;
    const x = (TARGET_W - w) / 2;
    const y = (TARGET_H - h) / 2;
    ctx.drawImage(originalImg, x, y, w, h);

    // 2. Add an immersive vignette effect
    const vignette = ctx.createRadialGradient(TARGET_W / 2, TARGET_H / 2, TARGET_H * 0.4, TARGET_W / 2, TARGET_H / 2, TARGET_W * 0.75);
    vignette.addColorStop(0, "rgba(0,0,0,0)");
    vignette.addColorStop(1, "rgba(0,0,0,0.6)");
    ctx.fillStyle = vignette;
    ctx.fillRect(0, 0, TARGET_W, TARGET_H);

    // 3. Draw Checkered Flag at the top
    const sqSize = 25;
    for (let col = 0; col < Math.ceil(TARGET_W / sqSize); col++) {
        for (let row = 0; row < 2; row++) {
            ctx.fillStyle = (col + row) % 2 === 0 ? "#111" : "#eee";
            ctx.fillRect(col * sqSize, row * sqSize, sqSize, sqSize);
        }
    }

    // Add a trim under the checkered flag
    ctx.fillStyle = "#ff1a1a";
    ctx.fillRect(0, sqSize * 2, TARGET_W, 4);

    // 4. Rear-view mirror
    const mirrorW = 400;
    const mirrorH = 100;
    const mirrorX = (TARGET_W - mirrorW) / 2;
    const mirrorY = 20;

    // Mirror Frame
    ctx.fillStyle = "#111";
    drawRoundRect(ctx, mirrorX - 10, mirrorY - 10, mirrorW + 20, mirrorH + 20, 15);
    ctx.fill();
    ctx.lineWidth = 4;
    ctx.strokeStyle = "#333";
    ctx.stroke();

    // Mirror Reflection (flipped original image)
    ctx.save();
    drawRoundRect(ctx, mirrorX, mirrorY, mirrorW, mirrorH, 8);
    ctx.clip();
    
    ctx.translate(canvas.width, 0);
    ctx.scale(-1, 1);
    ctx.drawImage(originalImg, x, y, w, h); 
    
    // Slight bluish reflection tint
    ctx.fillStyle = "rgba(100, 150, 255, 0.2)";
    ctx.fillRect(0, 0, TARGET_W, TARGET_H);
    ctx.restore();

    // 5. Draw the Dashboard Outline
    const dashY = TARGET_H * 0.82;
    ctx.fillStyle = "#1a1a1a";
    ctx.beginPath();
    ctx.moveTo(0, dashY);
    ctx.lineTo(TARGET_W, dashY);
    ctx.lineTo(TARGET_W, TARGET_H);
    ctx.lineTo(0, TARGET_H);
    ctx.closePath();
    ctx.fill();

    // Dash trim
    ctx.beginPath();
    ctx.moveTo(0, dashY);
    ctx.lineTo(TARGET_W, dashY);
    ctx.strokeStyle = "#e60000";
    ctx.lineWidth = 6;
    ctx.stroke();

    // 6. Draw Dashboard Dials (Speedometer & Tachometer)
    const leftDashX = TARGET_W * 0.25;
    const rightDashX = TARGET_W * 0.75;
    const dashCenterY = TARGET_H * 0.92;
    const dialR = 85;

    // --- Left Dial (Speedometer) ---
    ctx.fillStyle = "#0c0c0c";
    ctx.beginPath();
    ctx.arc(leftDashX, dashCenterY, dialR, 0, 2 * Math.PI);
    ctx.fill();
    ctx.lineWidth = 6;
    ctx.strokeStyle = "#444";
    ctx.stroke();

    // Speed markings
    for(let i = 0; i <= 20; i++) {
        let angle = 0.75 * Math.PI + (i / 20) * 1.5 * Math.PI;
        let isMajor = i % 2 === 0;
        let innerR = isMajor ? dialR * 0.75 : dialR * 0.85;
        ctx.beginPath();
        ctx.moveTo(leftDashX + innerR * Math.cos(angle), dashCenterY + innerR * Math.sin(angle));
        ctx.lineTo(leftDashX + dialR * 0.95 * Math.cos(angle), dashCenterY + dialR * 0.95 * Math.sin(angle));
        ctx.strokeStyle = i >= 16 ? "#ff4d4d" : "#ffffff";
        ctx.lineWidth = isMajor ? 3 : 1;
        ctx.stroke();
    }

    let safeSpeed = Math.min(Math.max(Number(speedValue) || 0, 0), 200);
    let speedAngle = 0.75 * Math.PI + (safeSpeed / 200) * 1.5 * Math.PI;

    // Needle shadow
    ctx.beginPath();
    ctx.moveTo(leftDashX, dashCenterY);
    ctx.lineTo(leftDashX + dialR * 0.85 * Math.cos(speedAngle + 0.05), dashCenterY + dialR * 0.85 * Math.sin(speedAngle + 0.05));
    ctx.strokeStyle = "rgba(0,0,0,0.5)";
    ctx.lineWidth = 5;
    ctx.stroke();

    // Needle main
    ctx.beginPath();
    ctx.moveTo(leftDashX, dashCenterY);
    ctx.lineTo(leftDashX + dialR * 0.85 * Math.cos(speedAngle), dashCenterY + dialR * 0.85 * Math.sin(speedAngle));
    ctx.strokeStyle = "#ff1a1a";
    ctx.lineWidth = 4;
    ctx.stroke();

    // Speedometer Center Pin
    ctx.beginPath();
    ctx.arc(leftDashX, dashCenterY, 12, 0, 2 * Math.PI);
    ctx.fillStyle = "#111";
    ctx.fill();
    ctx.strokeStyle = "#555";
    ctx.lineWidth = 2;
    ctx.stroke();

    ctx.fillStyle = "#aaa";
    ctx.font = "bold 12px sans-serif";
    ctx.textAlign = "center";
    ctx.fillText("KM/H", leftDashX, dashCenterY + dialR * 0.5);
    ctx.fillStyle = "#fff";
    ctx.font = "bold 26px monospace";
    ctx.fillText(String(safeSpeed), leftDashX, dashCenterY + dialR * 0.25);

    // --- Right Dial (HUD info) ---
    ctx.fillStyle = "#0c0c0c";
    ctx.beginPath();
    ctx.arc(rightDashX, dashCenterY, dialR, 0, 2 * Math.PI);
    ctx.fill();
    ctx.lineWidth = 6;
    ctx.strokeStyle = "#444";
    ctx.stroke();

    ctx.fillStyle = "#00e6e6";
    ctx.font = "bold 16px monospace";
    ctx.textBaseline = "middle";
    ctx.fillText("GEAR", rightDashX, dashCenterY - 30);
    ctx.font = "bold 40px monospace";
    ctx.fillStyle = "#fff";
    ctx.fillText(String(gearValue), rightDashX, dashCenterY);

    ctx.fillStyle = "#00e6e6";
    ctx.font = "bold 14px monospace";
    ctx.fillText("LAP", rightDashX, dashCenterY + 35);
    ctx.fillStyle = "#fff";
    ctx.font = "bold 20px monospace";
    ctx.fillText(lapText, rightDashX, dashCenterY + 55);

    // 7. Draw the Steering Wheel
    const wcx = TARGET_W / 2;
    const wcy = TARGET_H * 0.98;
    const wr = 260;

    // Steering wheel shadow
    ctx.beginPath();
    ctx.arc(wcx, wcy + 15, wr, 1.1 * Math.PI, 1.9 * Math.PI);
    ctx.lineWidth = 45;
    ctx.strokeStyle = "rgba(0,0,0,0.6)";
    ctx.stroke();

    // Wrap around steering rim
    ctx.beginPath();
    ctx.arc(wcx, wcy, wr, 1.1 * Math.PI, 1.9 * Math.PI);
    ctx.lineWidth = 45;
    ctx.strokeStyle = "#252525";
    ctx.stroke();

    // Inner rim details
    ctx.beginPath();
    ctx.arc(wcx, wcy, wr, 1.1 * Math.PI, 1.9 * Math.PI);
    ctx.lineWidth = 20;
    ctx.strokeStyle = "#383838";
    ctx.stroke();

    // Center hub
    ctx.beginPath();
    ctx.arc(wcx, wcy, 80, 0, 2 * Math.PI);
    ctx.fillStyle = "#111";
    ctx.fill();

    // Wheel Spokes
    ctx.fillStyle = "#1e1e1e";
    // Left spoke
    ctx.beginPath();
    ctx.moveTo(wcx - wr + 22, wcy - 20);
    ctx.lineTo(wcx - 60, wcy - 50);
    ctx.lineTo(wcx - 40, wcy + 20);
    ctx.lineTo(wcx - wr + 22, wcy + 50);
    ctx.fill();

    // Right spoke
    ctx.beginPath();
    ctx.moveTo(wcx + wr - 22, wcy - 20);
    ctx.lineTo(wcx + 60, wcy - 50);
    ctx.lineTo(wcx + 40, wcy + 20);
    ctx.lineTo(wcx + wr - 22, wcy + 50);
    ctx.fill();

    // 8. Draw "RIVAL" Target Box to establish "Friendly Race" context
    const rCx = TARGET_W * 0.55;
    const rCy = TARGET_H * 0.55;
    const targetSize = 25;

    ctx.strokeStyle = "#ff4d4d";
    ctx.lineWidth = 3;
    
    // Target Box corners
    ctx.beginPath(); ctx.moveTo(rCx - 90, rCy - 60 + targetSize); ctx.lineTo(rCx - 90, rCy - 60); ctx.lineTo(rCx - 90 + targetSize, rCy - 60); ctx.stroke();
    ctx.beginPath(); ctx.moveTo(rCx + 90 - targetSize, rCy - 60); ctx.lineTo(rCx + 90, rCy - 60); ctx.lineTo(rCx + 90, rCy - 60 + targetSize); ctx.stroke();
    ctx.beginPath(); ctx.moveTo(rCx - 90, rCy + 60 - targetSize); ctx.lineTo(rCx - 90, rCy + 60); ctx.lineTo(rCx - 90 + targetSize, rCy + 60); ctx.stroke();
    ctx.beginPath(); ctx.moveTo(rCx + 90 - targetSize, rCy + 60); ctx.lineTo(rCx + 90, rCy + 60); ctx.lineTo(rCx + 90, rCy + 60 - targetSize); ctx.stroke();

    // Target Text Background
    ctx.fillStyle = "rgba(0,0,0,0.7)";
    drawRoundRect(ctx, rCx - 60, rCy - 100, 120, 50, 6);
    ctx.fill();

    ctx.fillStyle = "#ff3333";
    ctx.font = "bold 16px sans-serif";
    ctx.textAlign = "center";
    ctx.textBaseline = "middle";
    ctx.fillText("RIVAL", rCx, rCy - 85);
    ctx.fillStyle = "#fff";
    ctx.fillText(`▼ ${rivalDistance}m`, rCx, rCy - 65);

    // 9. Overlay Title and Game HUD Elements
    // POS (Position)
    ctx.fillStyle = "#FFD700";
    ctx.font = "italic bold 44px Impact, sans-serif";
    ctx.textAlign = "left";
    ctx.fillText("POS", 40, 100);
    ctx.fillStyle = "#fff";
    ctx.fillText("1 / 2", 130, 100);

    // Match Time
    ctx.fillStyle = "#fff";
    ctx.font = "bold 32px monospace";
    ctx.textAlign = "right";
    ctx.fillText("TIME 02:45", TARGET_W - 40, 95);

    // Spectacular Arcade Title Header "ДРУЖЕСКАЯ ГОНКА"
    ctx.font = "italic bold 56px Impact, sans-serif";
    ctx.textAlign = "center";
    ctx.textBaseline = "middle";

    // Text shadow for pop
    ctx.fillStyle = "rgba(0,0,0,0.8)";
    ctx.fillText(eventName, TARGET_W / 2 + 5, 185);

    // Gradient filling for the title
    const textGrad = ctx.createLinearGradient(0, 150, 0, 210);
    textGrad.addColorStop(0, "#ffffff");
    textGrad.addColorStop(1, "#c0c0c0");
    ctx.fillStyle = textGrad;
    ctx.fillText(eventName, TARGET_W / 2, 180);

    // Stroke outline for racing flair
    ctx.strokeStyle = "#cc0000";
    ctx.lineWidth = 3;
    ctx.strokeText(eventName, TARGET_W / 2, 180);

    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 Friendly Race Image Maker is a creative tool that transforms any uploaded image into an immersive, arcade-style racing game screenshot. It overlays a dynamic cockpit interface onto your photo, featuring elements such as a speedometer, gear indicator, lap counter, a steering wheel, and a rear-view mirror. The tool also adds cinematic effects like a vignette, a checkered flag header, and a ‘RIVAL’ tracking HUD to enhance the sense of speed and competition. This tool is perfect for creating fun, themed social media content, gaming memes, or personalized racing-themed graphics.

Leave a Reply

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