Please bookmark this page to avoid losing your image tool!

Image Vintage Postage Stamp Frame Creator

(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,
    frameColor = "rgb(245, 240, 230)", // A warm, aged paper color for the stamp body
    pageColor = "rgb(255, 253, 250)",   // A very light cream for the "page" background visible through perforations
    perforationDiameter = 10,          // Diameter of the perforation circles
    imagePadding = 20,                 // Padding between the image edge and the "valley" of the perforations
    postageText = "POSTAGE",           // Text like "POSTAGE" usually at the top
    valueText = "25c",                 // Text for the stamp's value, e.g., "25c", "1£"
    textColor = "rgb(70, 60, 50)",     // Dark, slightly desaturated brown for text
    fontFamily = "'Times New Roman', Times, serif", // A classic serif font
    fontSize = 14,                     // Desired font size for text elements
    imageBorderColor = "rgba(0,0,0,0.1)", // Subtle border color around the image itself
    imageBorderWidth = 1               // Width of the border around the image. Set to 0 to disable.
) {
    // Ensure perforationDiameter is positive for radius calculation
    const effectivePerforationDiameter = Math.max(0, perforationDiameter);
    const radius = effectivePerforationDiameter / 2;

    // Calculate dimensions for the stamp paper (the part that gets the frameColor)
    // This is the area inside the "valleys" of the perforations.
    const stampPaperWidth = originalImg.width + 2 * imagePadding;
    const stampPaperHeight = originalImg.height + 2 * imagePadding;

    // Canvas dimensions need to accommodate the perforations extending outwards
    // The full canvas includes half of the perforation circles on its edges.
    const canvasWidth = stampPaperWidth + 2 * radius;
    const canvasHeight = stampPaperHeight + 2 * radius;

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

    // 1. Fill canvas with pageColor. This is the color seen through perforation holes
    // or the color of the "sheet" the stamp is on.
    ctx.fillStyle = pageColor;
    ctx.fillRect(0, 0, canvasWidth, canvasHeight);

    // 2. Draw the main body of the stamp.
    // This is a rectangle of frameColor, which will then be "perforated".
    ctx.fillStyle = frameColor;
    if (radius > 0) {
        // If there are perforations, the frameColor rect is inset by `radius`.
        ctx.fillRect(radius, radius, stampPaperWidth, stampPaperHeight);
    } else {
        // No perforations, so the frameColor fills the entire canvas.
        ctx.fillRect(0, 0, canvasWidth, canvasHeight);
    }

    // 3. "Punch out" the perforations by drawing circles of pageColor.
    // This only happens if there's a positive perforation diameter.
    if (radius > 0 && effectivePerforationDiameter > 0) {
        ctx.fillStyle = pageColor; // Color for the "holes"

        // Top and Bottom edges: iterate along X-axis
        // Circles are centered on the edges of the stampPaperRect.
        for (let curX = radius; curX <= radius + stampPaperWidth; curX += effectivePerforationDiameter) {
            // Top edge punches
            ctx.beginPath();
            ctx.arc(curX, radius, radius, 0, 2 * Math.PI);
            ctx.fill();

            // Bottom edge punches
            ctx.beginPath();
            ctx.arc(curX, radius + stampPaperHeight, radius, 0, 2 * Math.PI);
            ctx.fill();
        }

        // Left and Right edges: iterate along Y-axis
        // Start curY from `radius + effectivePerforationDiameter` and end before `radius + stampPaperHeight`
        // to avoid re-drawing corner perforations already handled by the X-axis loops.
        for (let curY = radius + effectivePerforationDiameter; curY < radius + stampPaperHeight; curY += effectivePerforationDiameter) {
            // Left edge punches
            ctx.beginPath();
            ctx.arc(radius, curY, radius, 0, 2 * Math.PI);
            ctx.fill();

            // Right edge punches
            ctx.beginPath();
            ctx.arc(radius + stampPaperWidth, curY, radius, 0, 2 * Math.PI);
            ctx.fill();
        }
    }

    // 4. Calculate image drawing position
    // The image is placed inside the stampPaper area, offset by imagePadding and radius.
    const imgDrawX = radius + imagePadding;
    const imgDrawY = radius + imagePadding;

    // 5. Draw an optional thin border around the image itself
    if (imageBorderWidth > 0 && imageBorderColor && imageBorderColor !== "transparent") {
        ctx.strokeStyle = imageBorderColor;
        ctx.lineWidth = imageBorderWidth;
        // This border is drawn on the edge of the image rectangle.
        ctx.strokeRect(imgDrawX, imgDrawY, originalImg.width, originalImg.height);
    }
    
    // 6. Draw the original image onto the canvas
    ctx.drawImage(originalImg, imgDrawX, imgDrawY, originalImg.width, originalImg.height);

    // 7. Add vintage text elements (e.g., "POSTAGE", value)
    if (postageText || valueText) {
        // Calculate usable font size based on imagePadding and requested fontSize
        const textHeightAllowance = imagePadding - 4; // Allow 2px margin top/bottom within padding
        let finalFontSize = Math.min(fontSize, textHeightAllowance);
        finalFontSize = Math.max(6, finalFontSize); // Ensure a minimum readable size (e.g., 6px)

        // Only draw text if the calculated font size is reasonably large
        if (finalFontSize >= 6) {
            ctx.font = `${finalFontSize}px ${fontFamily}`;
            ctx.fillStyle = textColor;
            ctx.textAlign = "center";
            ctx.textBaseline = "middle"; // Vertically center text in its line

            const textCenterX = canvasWidth / 2;

            if (postageText) {
                // Place "POSTAGE" text in the top padding area
                const postageTextY = radius + imagePadding / 2;
                ctx.fillText(postageText.toUpperCase(), textCenterX, postageTextY);
            }

            if (valueText) {
                // Place value text in the bottom padding area
                const valueTextY = canvasHeight - radius - imagePadding / 2;
                ctx.fillText(valueText, textCenterX, valueTextY);
            }
        }
    }

    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 Vintage Postage Stamp Frame Creator is a tool designed to transform any image into a visually appealing vintage postage stamp format. Users can customize various aspects of the stamp, including frame color, background color, perforation diameter, and text elements such as the type of postage and its value. This tool is ideal for creating personalized stamps for artistic projects, invitations, greeting cards, or any creative endeavor where a vintage flair is desired. It provides a simple and user-friendly interface to add a nostalgic touch to your images.

Leave a Reply

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