Please bookmark this page to avoid losing your image tool!

Image Birth Certificate Template 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 = "CERTIFICATE OF BIRTH",
    namePlaceholder = "[Full Name of Child]",
    dobPlaceholder = "[Date of Birth]",
    pobPlaceholder = "[Place of Birth: City, State]",
    motherNamePlaceholder = "[Mother's Full Maiden Name]",
    fatherNamePlaceholder = "[Father's Full Name]",
    textColor = "#2c3e50", // Dark grayish blue
    accentColor = "#3498db", // Nice blue
    borderColor = "#bdc3c7", // Silver/Gray border
    backgroundColor = "#ffffff",
    fontFamily = "serif", 
    photoX = 50, 
    photoY = 160,
    photoWidth = 100,
    photoHeight = 130
) {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    const canvasWidth = 794; // Approx A4 width at 96 DPI landscape, or common web width
    const canvasHeight = 560; // Landscape orientation, approximates 11 x 8.5 ratio
    canvas.width = canvasWidth;
    canvas.height = canvasHeight;

    // 1. Background
    ctx.fillStyle = backgroundColor;
    ctx.fillRect(0, 0, canvasWidth, canvasHeight);

    // 2. Border
    const borderWidth = 20; // Padding for the border from canvas edge
    ctx.strokeStyle = borderColor;
    ctx.lineWidth = 2;
    // Outer line of main border
    ctx.strokeRect(borderWidth / 2, borderWidth / 2, canvasWidth - borderWidth, canvasHeight - borderWidth);
    // Inner line of main border (decorative)
    ctx.strokeStyle = accentColor;
    ctx.lineWidth = 1;
    ctx.strokeRect(borderWidth / 2 + 4, borderWidth / 2 + 4, canvasWidth - borderWidth - 8, canvasHeight - borderWidth - 8);

    // Utility to draw text
    function drawText(text, x, y, size, color, align = 'left', baseLine = 'alphabetic', weight = 'normal') {
        ctx.font = `${weight} ${size}px ${fontFamily}`;
        ctx.fillStyle = color;
        ctx.textAlign = align;
        ctx.textBaseline = baseLine;
        ctx.fillText(text, x, y);
    }
    
    // Utility to draw a line for filling in text
    function drawDataLine(x, y, width) {
        ctx.beginPath();
        ctx.moveTo(x, y);
        ctx.lineTo(x + width, y);
        ctx.strokeStyle = textColor; // Use main text color for data lines
        ctx.lineWidth = 0.75; 
        ctx.stroke();
    }

    // 3. Title
    drawText(title, canvasWidth / 2, 70, 36, accentColor, 'center', 'middle', 'bold');
    drawText("This certifies that", canvasWidth / 2, 105, 16, textColor, 'center', 'middle');

    // Content layout constants
    const contentStartXFields = photoX + photoWidth + 30; 
    const contentMaxWidthFields = canvasWidth - contentStartXFields - (borderWidth + 10);
    const dataLineOffsetY = 10; // For lines under text (textbaseline middle + this offset)
    const fieldTextSize = 16; // Font size for main data fields
    
    // Vertical Spacing
    const fieldLineHeight = 30;
    const spaceAfterSeparator = 20;
    const spaceFactorAfterParents = 1.2; 
    const detailsBoxHeight = 60;
    const paddingAfterDetailsBox = 15;

    // 4. Original Image (Photo placeholder)
    ctx.strokeStyle = borderColor;
    ctx.lineWidth = 1;
    ctx.strokeRect(photoX, photoY, photoWidth, photoHeight); // Photo box border

    if (originalImg && originalImg.complete && originalImg.naturalWidth > 0) {
        try {
            // Clear the area inside the photo box border before drawing image
            ctx.fillStyle = backgroundColor;
            ctx.fillRect(photoX + 1, photoY + 1, photoWidth - 2, photoHeight - 2);
            ctx.drawImage(originalImg, photoX, photoY, photoWidth, photoHeight);
        } catch (e) {
            console.error("Error drawing original image:", e);
            drawText("Photo", photoX + photoWidth / 2, photoY + photoHeight / 2, 14, borderColor, 'center', 'middle');
        }
    } else {
         drawText("Photo", photoX + photoWidth / 2, photoY + photoHeight / 2, 14, borderColor, 'center', 'middle');
    }
    
    // 5. Certificate Details
    let currentY = 160; // Start Y for main content area (aligned with photo top)

    // Child's Name
    const childNameLabel = "Child's Full Name:";
    ctx.font = `normal ${fieldTextSize}px ${fontFamily}`; // Set font for measuring label
    const childNameLabelWidth = ctx.measureText(childNameLabel).width;
    drawText(childNameLabel, contentStartXFields, currentY, fieldTextSize, textColor, 'left', 'middle');
    drawText(namePlaceholder, contentStartXFields + childNameLabelWidth + 5, currentY, fieldTextSize, textColor, 'left', 'middle'); 
    drawDataLine(contentStartXFields + childNameLabelWidth + 5, currentY + dataLineOffsetY, contentMaxWidthFields - (childNameLabelWidth + 5));
    currentY += fieldLineHeight;

    // Date of Birth
    const dobLabelText = "Date of Birth:";
    // Font already set for fieldTextSize
    const dobLabelWidth = ctx.measureText(dobLabelText).width;
    drawText(dobLabelText, contentStartXFields, currentY, fieldTextSize, textColor, 'left', 'middle');
    drawText(dobPlaceholder, contentStartXFields + dobLabelWidth + 5, currentY, fieldTextSize, textColor, 'left', 'middle');
    drawDataLine(contentStartXFields + dobLabelWidth + 5, currentY + dataLineOffsetY, contentMaxWidthFields - (dobLabelWidth + 5));
    currentY += fieldLineHeight;

    // Place of Birth
    const pobLabelText = "Place of Birth:";
    const pobLabelWidth = ctx.measureText(pobLabelText).width;
    drawText(pobLabelText, contentStartXFields, currentY, fieldTextSize, textColor, 'left', 'middle');
    drawText(pobPlaceholder, contentStartXFields + pobLabelWidth + 5, currentY, fieldTextSize, textColor, 'left', 'middle');
    drawDataLine(contentStartXFields + pobLabelWidth + 5, currentY + dataLineOffsetY, contentMaxWidthFields - (pobLabelWidth + 5));
    currentY += fieldLineHeight;
    
    // Separator Line
    currentY += 10; 
    ctx.beginPath();
    ctx.moveTo(borderWidth + 10, currentY); 
    ctx.lineTo(canvasWidth - (borderWidth + 10), currentY); 
    ctx.strokeStyle = borderColor;
    ctx.lineWidth = 0.5;
    ctx.stroke();
    currentY += spaceAfterSeparator;

    // Parents' Names (side-by-side)
    const parentsFieldY = currentY;
    ctx.font = `normal ${fieldTextSize}px ${fontFamily}`; 
    const motherLabelString = "Mother's Name:";
    const fatherLabelString = "Father's Name:";
    const measuredMotherLabelWidth = ctx.measureText(motherLabelString).width;
    const measuredFatherLabelWidth = ctx.measureText(fatherLabelString).width;
    const actualParentLabelWidth = Math.max(measuredMotherLabelWidth, measuredFatherLabelWidth);
    
    const totalWidthForOneParentEntry = (canvasWidth - 2*(borderWidth+10) - 20) / 2; // 20 is mid_gap
    const parentNameInputLineWidth = totalWidthForOneParentEntry - actualParentLabelWidth - 5; // 5 is padding after label

    const motherLabelX = borderWidth + 10;
    drawText(motherLabelString, motherLabelX, parentsFieldY, fieldTextSize, textColor, 'left', 'middle');
    drawText(motherNamePlaceholder, motherLabelX + actualParentLabelWidth + 5, parentsFieldY, fieldTextSize, textColor, 'left', 'middle');
    drawDataLine(motherLabelX + actualParentLabelWidth + 5, parentsFieldY + dataLineOffsetY, parentNameInputLineWidth);
    
    const fatherLabelX = canvasWidth / 2 + 10; 
    drawText(fatherLabelString, fatherLabelX, parentsFieldY, fieldTextSize, textColor, 'left', 'middle');
    drawText(fatherNamePlaceholder, fatherLabelX + actualParentLabelWidth + 5, parentsFieldY, fieldTextSize, textColor, 'left', 'middle');
    drawDataLine(fatherLabelX + actualParentLabelWidth + 5, parentsFieldY + dataLineOffsetY, parentNameInputLineWidth);
    currentY += fieldLineHeight * spaceFactorAfterParents;

    // Additional Details Box
    const detailsBoxX = borderWidth + 10;
    const detailsBoxY = currentY;
    const detailsBoxWidth = canvasWidth - 2 * (borderWidth + 10);
    
    ctx.strokeStyle = borderColor;
    ctx.lineWidth = 1; 
    ctx.strokeRect(detailsBoxX, detailsBoxY, detailsBoxWidth, detailsBoxHeight);
    drawText("Additional Details:", detailsBoxX + 10, detailsBoxY + 15, 14, accentColor, 'left', 'middle'); 
    
    let detailTextY = detailsBoxY + detailsBoxHeight - 20; 
    const detailLabelFontSize = 12; 
    ctx.font = `normal ${detailLabelFontSize}px ${fontFamily}`; 

    let currentDetailX = detailsBoxX + 15;
    const numDetailFields = 3;
    const detailFieldSpacing = 15; 
    const detailFieldContentWidth = (detailsBoxWidth - 30 - (numDetailFields - 1) * detailFieldSpacing) / numDetailFields;

    const sexLabel = "Sex:";
    drawText(sexLabel, currentDetailX, detailTextY, detailLabelFontSize, textColor, 'left', 'middle');
    const sexLabelWidth = ctx.measureText(sexLabel).width;
    drawDataLine(currentDetailX + sexLabelWidth + 5, detailTextY + dataLineOffsetY * 0.8, detailFieldContentWidth - (sexLabelWidth + 5)); // Adjusted line Y
    currentDetailX += detailFieldContentWidth + detailFieldSpacing;

    const weightLabel = "Weight:";
    drawText(weightLabel, currentDetailX, detailTextY, detailLabelFontSize, textColor, 'left', 'middle');
    const weightLabelWidth = ctx.measureText(weightLabel).width;
    drawDataLine(currentDetailX + weightLabelWidth + 5, detailTextY + dataLineOffsetY * 0.8, detailFieldContentWidth - (weightLabelWidth + 5));
    currentDetailX += detailFieldContentWidth + detailFieldSpacing;
    
    const timeLabel = "Time:";
    drawText(timeLabel, currentDetailX, detailTextY, detailLabelFontSize, textColor, 'left', 'middle');
    const timeLabelWidth = ctx.measureText(timeLabel).width;
    drawDataLine(currentDetailX + timeLabelWidth + 5, detailTextY + dataLineOffsetY * 0.8, detailFieldContentWidth - (timeLabelWidth + 5));
    
    currentY += detailsBoxHeight + paddingAfterDetailsBox;

    // 6. Seal, Signatures, Date Issued (Bottom Area)
    const bottomElementsYStart = Math.max(currentY, canvasHeight - 130); 

    const sealCenterX = canvasWidth / 2;
    const sealCenterY = bottomElementsYStart + 35; 
    ctx.beginPath();
    ctx.arc(sealCenterX, sealCenterY, 30, 0, 2 * Math.PI, false);
    ctx.strokeStyle = accentColor;
    ctx.lineWidth = 1.5;
    ctx.stroke();
    drawText("OFFICIAL", sealCenterX, sealCenterY - 8, 10, accentColor, 'center', 'middle', 'bold');
    drawText("SEAL", sealCenterX, sealCenterY + 8, 10, accentColor, 'center', 'middle', 'bold');

    const signatureY = bottomElementsYStart + 80; 
    const signatureLineLength = (canvasWidth - 2 * (borderWidth + 10) - 40) / 2; 
    
    const officialSigX = borderWidth + 10;
    drawDataLine(officialSigX, signatureY, signatureLineLength);
    drawText("Official Attendant / Registrar", officialSigX + signatureLineLength/2, signatureY + 15, 12, textColor, 'center', 'top');

    const parentSigX = canvasWidth - (borderWidth + 10) - signatureLineLength;
    drawDataLine(parentSigX, signatureY, signatureLineLength);
    drawText("Parent / Guardian Signature", parentSigX + signatureLineLength/2, signatureY + 15, 12, textColor, 'center', 'top');

    drawText("Date Issued: ____________________", canvasWidth/2, signatureY + 35, 12, textColor, 'center', 'middle');

    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 Birth Certificate Template Generator is a web tool designed to create custom birth certificate templates. Users can input specific details, such as the child’s name, date of birth, place of birth, and parents’ names. This tool also allows for the addition of a personal photo, making it ideal for families looking to document their child’s birth in a visually appealing way. The generated certificate features customizable colors, fonts, and layout elements, ensuring a professional appearance. This tool is particularly useful for parents, registrars, and hospitals who need to produce or organize birth certificates.

Leave a Reply

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