Please bookmark this page to avoid losing your image tool!

Image Polaroid Instant Photo Frame

(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.
async function processImage(
    originalImg,
    frameColor = '#FEFEFE', // Color of the Polaroid frame
    shadowColor = 'rgba(0,0,0,0.2)', // Color of the drop shadow
    text = '', // Optional text to write on the frame
    textColor = '#2c2c2c', // Color of the text
    font = '24px "Caveat Brush", cursive', // Font style for the text (Caveat Brush is good for a handwritten look)
    imagePadding = 15, // Padding around the image on sides and top (number)
    bottomPaddingScale = 4 // Scale factor for bottom padding relative to side/top padding (number)
) {
    // Helper function to load "Caveat Brush" font if specified and not available
    async function ensureCaveatBrushLoaded(fontUrl = 'https://fonts.gstatic.com/s/caveatbrush/v12/EYq0maZfwr9S9AUnAUeCo হইলX3Vndk0.woff2') {
        const fontFamilyToCheck = "Caveat Brush";
        
        // Check if FontFace API and document.fonts.check are supported
        if (document.fonts && typeof document.fonts.check === 'function') {
            if (!document.fonts.check(`12px "${fontFamilyToCheck}"`)) { // Check if font is already available
                const fontFace = new FontFace(fontFamilyToCheck, `url(${fontUrl})`);
                try {
                    await fontFace.load(); // Load the font
                    document.fonts.add(fontFace); // Add it to the document's font set
                } catch (e) {
                    console.error(`Error loading font "${fontFamilyToCheck}":`, e);
                    // Font loading failed; browser will use fallback font specified in 'font' string (e.g., cursive).
                }
            }
        } else {
            // Fallback for browsers without full FontFace API support (e.g., older browsers)
            // This method dynamically adds a @font-face rule but doesn't reliably know when it's loaded.
            // Font-display: swap helps by showing text with a fallback font immediately.
            const styleId = `dynamic-font-style-${fontFamilyToCheck.replace(/\s+/g, '-')}`;
            if (!document.getElementById(styleId)) {
                const style = document.createElement('style');
                style.id = styleId;
                style.textContent = `
                    @font-face {
                        font-family: "${fontFamilyToCheck}";
                        src: url(${fontUrl});
                        font-display: swap;
                    }
                `;
                document.head.appendChild(style);
            }
        }
    }

    const imgWidth = originalImg.width;
    const imgHeight = originalImg.height;

    // Validate and parse numeric parameters, providing defaults if parsing fails
    const numImagePadding = parseFloat(imagePadding);
    const sideTopPadding = !isNaN(numImagePadding) && numImagePadding >= 0 ? numImagePadding : 15;

    const numBottomPaddingScale = parseFloat(bottomPaddingScale);
    const scale = !isNaN(numBottomPaddingScale) && numBottomPaddingScale >= 0 ? numBottomPaddingScale : 4;
    
    const actualBottomPadding = sideTopPadding * scale;

    // Calculate dimensions of the white frame content (image + padding)
    const frameContentWidth = imgWidth + 2 * sideTopPadding;
    const frameContentHeight = imgHeight + sideTopPadding + actualBottomPadding;

    // Shadow properties
    const shadowBlurAmount = 10;
    const shadowOffsetXAmount = 3;
    const shadowOffsetYAmount = 3;

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

    // Calculate canvas dimensions to accommodate the frame and its shadow
    canvas.width = frameContentWidth + 2 * shadowBlurAmount + Math.abs(shadowOffsetXAmount);
    canvas.height = frameContentHeight + 2 * shadowBlurAmount + Math.abs(shadowOffsetYAmount);

    // Determine the top-left coordinates for drawing the frame rectangle.
    // This ensures there's enough space on the canvas for the shadow,
    // especially if the shadow has a negative offset.
    const rectDrawX = (shadowOffsetXAmount < 0 ? Math.abs(shadowOffsetXAmount) : 0) + shadowBlurAmount;
    const rectDrawY = (shadowOffsetYAmount < 0 ? Math.abs(shadowOffsetYAmount) : 0) + shadowBlurAmount;

    // Apply shadow settings
    ctx.shadowColor = shadowColor;
    ctx.shadowBlur = shadowBlurAmount;
    ctx.shadowOffsetX = shadowOffsetXAmount;
    ctx.shadowOffsetY = shadowOffsetYAmount;
    
    // Draw the main frame rectangle (which will cast the shadow)
    ctx.fillStyle = frameColor;
    ctx.fillRect(rectDrawX, rectDrawY, frameContentWidth, frameContentHeight);

    // Reset shadow for subsequent drawings on top of the frame
    ctx.shadowColor = 'transparent';
    ctx.shadowBlur = 0;
    ctx.shadowOffsetX = 0;
    ctx.shadowOffsetY = 0;

    // Calculate image position on the canvas
    const imgDrawX_onCanvas = rectDrawX + sideTopPadding;
    const imgDrawY_onCanvas = rectDrawY + sideTopPadding;
    
    // Draw the original image onto the frame
    ctx.drawImage(originalImg, imgDrawX_onCanvas, imgDrawY_onCanvas, imgWidth, imgHeight);
    
    // Optional: Draw a very subtle inner border around the photo area for a slightly inset look
    ctx.strokeStyle = 'rgba(0,0,0,0.08)'; // Very light, subtle border
    ctx.lineWidth = 1;
    // Stroke a 1px border carefully aligned with image pixels
    ctx.strokeRect(imgDrawX_onCanvas - 0.5, imgDrawY_onCanvas - 0.5, imgWidth + 1, imgHeight + 1);

    // Draw text if provided
    if (text && text.trim() !== '') {
        // If "Caveat Brush" (or any part of its name) is in the font string,
        // try to ensure it's loaded.
        if (font.toLowerCase().includes('caveat brush')) {
            await ensureCaveatBrushLoaded(); // Wait for font loading attempt
        }
        
        ctx.fillStyle = textColor;
        ctx.font = font; // Apply the full font string (e.g., '24px "Caveat Brush", cursive')
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle'; // Align text vertically to the middle

        // Calculate text position: centered in the bottom padding area of the frame
        const textContainerMidX = rectDrawX + frameContentWidth / 2;
        const textContainerMidY = imgDrawY_onCanvas + imgHeight + (actualBottomPadding / 2);
        
        ctx.fillText(text, textContainerMidX, textContainerMidY);
    }

    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 Polaroid Instant Photo Frame tool allows users to create a Polaroid-style frame around their images. This tool provides options for customizing the frame’s color, shadow, and text, enabling users to personalize their photos. It’s ideal for enhancing images for social media, creating unique prints for albums, or producing visually appealing invitations and announcements. Whether for personal use or creative projects, this tool adds a playful and nostalgic touch to digital photos.

Leave a Reply

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