Please bookmark this page to avoid losing your image tool!

Почтальон Шарик

(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 = "ПОЧТАЛЬОН ШАРИК", 
    location = "ПРОСТОКВАШИНО", 
    bgColor = "#f4ecd8"
) {
    // Determine dimensions based on original image size to remain proportional
    const w = originalImg.width;
    const h = originalImg.height;
    
    // Scale margins and features based on image size
    const margin = Math.max(w, h) * 0.08; 
    const bottomMargin = margin * 2;
    const holeRadius = margin * 0.2;
    
    const cw = w + margin * 2;
    const ch = h + margin + bottomMargin;
    
    // Offscreen canvas for constructing the perforated stamp
    const stampCanvas = document.createElement('canvas');
    stampCanvas.width = cw;
    stampCanvas.height = ch;
    const sCtx = stampCanvas.getContext('2d');
    
    // Fill stamp background color
    sCtx.fillStyle = bgColor;
    sCtx.fillRect(0, 0, cw, ch);
    
    // Create perforation holes along the border using destination-out
    sCtx.globalCompositeOperation = 'destination-out';
    
    // Top and Bottom perforations
    const numHolesX = Math.round(cw / (holeRadius * 3));
    const spacingX = cw / numHolesX;
    sCtx.fillStyle = '#000';
    
    for (let i = 0; i <= numHolesX; i++) {
        const x = i * spacingX;
        sCtx.beginPath(); sCtx.arc(x, 0, holeRadius, 0, Math.PI * 2); sCtx.fill();
        sCtx.beginPath(); sCtx.arc(x, ch, holeRadius, 0, Math.PI * 2); sCtx.fill();
    }
    
    // Left and Right perforations
    const numHolesY = Math.round(ch / (holeRadius * 3));
    const spacingY = ch / numHolesY;
    
    for (let i = 0; i <= numHolesY; i++) {
        const y = i * spacingY;
        sCtx.beginPath(); sCtx.arc(0, y, holeRadius, 0, Math.PI * 2); sCtx.fill();
        sCtx.beginPath(); sCtx.arc(cw, y, holeRadius, 0, Math.PI * 2); sCtx.fill();
    }
    
    // Switch back to normal drawing mode
    sCtx.globalCompositeOperation = 'source-over';
    
    // Draw the actual image inside the stamp
    sCtx.drawImage(originalImg, margin, margin, w, h);
    
    // Draw a subtle border around the image itself
    sCtx.lineWidth = Math.max(1, margin * 0.05);
    sCtx.strokeStyle = '#333333';
    sCtx.strokeRect(margin, margin, w, h);
    
    // Add custom text at the bottom margin (like stamp title or nominal value)
    sCtx.fillStyle = '#2b2b2b';
    sCtx.font = `bold ${margin * 0.75}px "Arial", sans-serif`;
    sCtx.textAlign = 'center';
    sCtx.textBaseline = 'middle';
    sCtx.fillText(title, cw / 2, h + margin + bottomMargin / 2);
    
    // Draw an overlay Postmark (Russian cancellation stamp)
    const pr = Math.min(w, h) * 0.25; // Postmark radius
    const px = margin + w - pr * 0.6; // Position near the top right logic corner
    const py = margin + pr * 0.6;
    
    sCtx.save();
    sCtx.translate(px, py);
    // Slight random-looking tilt
    sCtx.rotate(-0.15);
    
    sCtx.strokeStyle = 'rgba(25, 25, 25, 0.75)';
    sCtx.fillStyle = 'rgba(25, 25, 25, 0.75)';
    sCtx.lineWidth = Math.max(2, pr * 0.04);
    
    // Postmark outer and inner circles
    sCtx.beginPath(); sCtx.arc(0, 0, pr, 0, Math.PI * 2); sCtx.stroke();
    sCtx.beginPath(); sCtx.arc(0, 0, pr * 0.75, 0, Math.PI * 2); sCtx.stroke();
    
    // Circular text in postmark
    const textStr = ` ${location} ★ ${title} ★ `;
    sCtx.font = `bold ${pr * 0.22}px "Courier New", monospace`;
    sCtx.textAlign = 'center';
    sCtx.textBaseline = 'middle';
    const angleStep = (Math.PI * 2) / textStr.length;
    
    for (let i = 0; i < textStr.length; i++) {
        sCtx.save();
        sCtx.rotate(i * angleStep - Math.PI / 2);
        sCtx.translate(0, -pr * 0.88);
        sCtx.fillText(textStr[i], 0, 0);
        sCtx.restore();
    }
    
    // Postmark center date (using 1978 as a nod to Prostokvashino's debut)
    sCtx.font = `bold ${pr * 0.25}px "Courier New", monospace`;
    sCtx.fillText("12.04.1978", 0, -pr * 0.15);
    sCtx.fillText("ПОЧТА", 0, pr * 0.25);
    
    // Postmark wavy cancellation lines extending to the left
    sCtx.beginPath();
    const waveCount = 5;
    const waveLength = w * 0.35 + pr;
    const waveFreq = (Math.PI * 2) / (pr * 0.6); // Based on postmark radius for clean scale
    const waveAmplitude = pr * 0.08;
    
    for (let i = 0; i < waveCount; i++) {
        const startY = -pr * 0.4 + i * (pr * 0.2);
        sCtx.moveTo(-pr, startY);
        // Draw the wavy path
        for (let wx = -pr; wx > -waveLength; wx -= 2) {
            const wy = startY + Math.sin((wx + pr) * waveFreq) * waveAmplitude;
            sCtx.lineTo(wx, wy);
        }
    }
    sCtx.stroke();
    sCtx.restore();
    
    // Generate Final Canvas featuring drop shadow and proper margin fitting
    const outputCanvas = document.createElement('canvas');
    const shadowPadding = margin * 1.5; 
    outputCanvas.width = cw + shadowPadding * 2;
    outputCanvas.height = ch + shadowPadding * 2;
    const oCtx = outputCanvas.getContext('2d');
    
    // Setup shadow effect for realism
    oCtx.shadowColor = 'rgba(0, 0, 0, 0.4)';
    oCtx.shadowBlur = margin * 0.4;
    oCtx.shadowOffsetX = margin * 0.15;
    oCtx.shadowOffsetY = margin * 0.25;
    
    // Draw the completed stamp onto the shadowed canvas
    oCtx.drawImage(stampCanvas, shadowPadding, shadowPadding);
    
    return outputCanvas;
}

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 transforms any uploaded image into a vintage-style postage stamp. It applies a perforated border effect, adds a custom background color, and overlays a classic circular postmark with decorative cancellation lines and text. It is ideal for creating nostalgic digital art, themed scrapbooking elements, or unique social media graphics that mimic old-fashioned mail aesthetics.

Leave a Reply

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