Please bookmark this page to avoid losing your image tool!

Photo Polaroid Instant Filter

(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,
    padding = 20, // Base padding (top, left, right) in pixels
    bottomPaddingFactor = 3, // Multiplier for bottom padding relative to 'padding'
    frameColor = "#f8f8f8", // Color of the Polaroid frame
    frameCornerRadius = 8, // Corner radius for the frame
    imageCornerRadius = 2, // Corner radius for the actual image
    // Vintage filter effects parameters
    sepia = 0.20, // Sepia amount (0 to 1, e.g., 0.2 for 20%)
    contrast = 0.90, // Contrast (0 to 2+, 1 is original, e.g., 0.9 for 90%)
    brightness = 1.10, // Brightness (0 to 2+, 1 is original, e.g., 1.1 for 110%)
    saturation = 0.90, // Saturation (0 to 2+, 1 is original, e.g., 0.9 for 90%)
    // Shadow effects parameters
    addShadow = 1, // 0 for no shadow, 1 for shadow
    shadowColor = "rgba(0,0,0,0.25)", // Color of the shadow
    shadowBlur = 15, // Blur radius for the shadow
    shadowOffsetX = 5, // Horizontal offset of the shadow
    shadowOffsetY = 7  // Vertical offset of the shadow
) {

    // Helper function to draw a rounded rectangle
    function _drawRoundedRect(ctx, x, y, width, height, radius) {
        radius = Number(radius); // Ensure radius is a number
        radius = Math.max(0, radius); // Ensure radius is not negative
        
        // Clamp radius to half of the shortest side if necessary
        if (width < 2 * radius) radius = width / 2;
        if (height < 2 * radius) radius = height / 2;

        // Prevent issues if width/height are 0 or negative
        if (width <=0 || height <= 0) {
             ctx.beginPath(); // create an empty path
             ctx.rect(x,y,width,height); // This will draw nothing or a line if one dim is 0
             ctx.closePath();
             return;
        }

        ctx.beginPath();
        ctx.moveTo(x + radius, y);
        ctx.arcTo(x + width, y, x + width, y + height, radius);
        ctx.arcTo(x + width, y + height, x, y + height, radius);
        ctx.arcTo(x, y + height, x, y, radius);
        ctx.arcTo(x, y, x + width, y, radius);
        ctx.closePath();
    }

    if (!originalImg || typeof originalImg.width === 'undefined' || originalImg.width === 0 || originalImg.height === 0) {
        console.error("processImage: Invalid image input. Ensure the image is loaded and has dimensions.");
        const errorCanvas = document.createElement('canvas');
        errorCanvas.width = 200;
        errorCanvas.height = 100;
        const errCtx = errorCanvas.getContext('2d');
        errCtx.fillStyle = '#dddddd'; // Light grey background for error message
        errCtx.fillRect(0,0,200,100);
        errCtx.fillStyle = 'red';
        errCtx.textAlign = 'center';
        errCtx.textBaseline = 'middle';
        errCtx.font = '12px Arial';
        errCtx.fillText('Error: Invalid Image Input', 100, 50);
        return errorCanvas;
    }

    const imgW = originalImg.width;
    const imgH = originalImg.height;

    // Ensure critical numeric parameters are numbers
    const numPadding = Number(padding);
    const numBottomPaddingFactor = Number(bottomPaddingFactor);

    const pT = numPadding;
    const pL = numPadding;
    const pR = numPadding;
    const pB = numPadding * numBottomPaddingFactor;

    const frameWidth = imgW + pL + pR;
    const frameHeight = imgH + pT + pB;

    const actualAddShadow = (Number(addShadow) === 1);
    const sOffsetX = actualAddShadow ? Number(shadowOffsetX) : 0;
    const sOffsetY = actualAddShadow ? Number(shadowOffsetY) : 0;
    const sBlur    = actualAddShadow ? Math.max(0, Number(shadowBlur)) : 0; // Blur must be non-negative
    
    let overall_min_x = 0, overall_max_x = frameWidth;
    let overall_min_y = 0, overall_max_y = frameHeight;

    if (actualAddShadow) {
        // Calculate bounding box including shadow
        overall_min_x = Math.min(0, sOffsetX - sBlur);
        overall_max_x = Math.max(frameWidth, frameWidth + sOffsetX + sBlur);
        overall_min_y = Math.min(0, sOffsetY - sBlur);
        overall_max_y = Math.max(frameHeight, frameHeight + sOffsetY + sBlur);
    }

    const canvasWidth = overall_max_x - overall_min_x;
    const canvasHeight = overall_max_y - overall_min_y;

    // Frame's top-left drawing position on the canvas
    const frameActualDrawX = -overall_min_x;
    const frameActualDrawY = -overall_min_y;

    const canvas = document.createElement('canvas');
    canvas.width = Math.max(1, canvasWidth); // Ensure canvas has at least 1x1 size
    canvas.height = Math.max(1, canvasHeight);
    const ctx = canvas.getContext('2d');

    // Draw shadow for the frame
    if (actualAddShadow) {
        ctx.shadowColor = String(shadowColor);
        ctx.shadowBlur = sBlur;
        ctx.shadowOffsetX = sOffsetX;
        ctx.shadowOffsetY = sOffsetY;
    }

    // Draw the frame
    ctx.fillStyle = String(frameColor);
    const fcr = Number(frameCornerRadius);
    if (fcr > 0 && frameWidth > 0 && frameHeight > 0) { // Only draw rounded rect if dimensions are positive
        _drawRoundedRect(ctx, frameActualDrawX, frameActualDrawY, frameWidth, frameHeight, fcr);
        ctx.fill();
    } else {
        ctx.fillRect(frameActualDrawX, frameActualDrawY, frameWidth, frameHeight);
    }

    // Clear shadow for drawing the image and subsequent operations
    if (actualAddShadow) {
        ctx.shadowColor = 'transparent'; // More robust than setting all to 0
        ctx.shadowBlur = 0;
        ctx.shadowOffsetX = 0;
        ctx.shadowOffsetY = 0;
    }

    // Prepare image filters
    let filterValues = [];
    const numSepia = Number(sepia);
    const numContrast = Number(contrast);
    const numBrightness = Number(brightness);
    const numSaturation = Number(saturation);

    if (numSepia !== 0) filterValues.push(`sepia(${numSepia})`);
    if (numContrast !== 1) filterValues.push(`contrast(${numContrast})`);
    if (numBrightness !== 1) filterValues.push(`brightness(${numBrightness})`);
    if (numSaturation !== 1) filterValues.push(`saturate(${numSaturation})`);
    
    if (filterValues.length > 0) {
        ctx.filter = filterValues.join(' ');
    }

    // Calculate image drawing position
    const imgDrawX = frameActualDrawX + pL;
    const imgDrawY = frameActualDrawY + pT;

    // Draw the image, potentially clipped with rounded corners
    // Ensure image dimensions are positive before attempting to draw or clip
    if (imgW > 0 && imgH > 0) {
        const icr = Number(imageCornerRadius);
        if (icr > 0) {
            ctx.save();
            _drawRoundedRect(ctx, imgDrawX, imgDrawY, imgW, imgH, icr);
            ctx.clip();
            ctx.drawImage(originalImg, imgDrawX, imgDrawY, imgW, imgH);
            ctx.restore();
        } else {
            ctx.drawImage(originalImg, imgDrawX, imgDrawY, imgW, imgH);
        }
    }
    

    // Reset filter to prevent affecting other drawings if canvas is reused
    ctx.filter = 'none';

    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 Photo Polaroid Instant Filter tool allows users to transform their images into a classic Polaroid-style photo with customizable features. Users can adjust padding, frame color, and corner radius, as well as apply vintage effects such as sepia, contrast, brightness, and saturation. Additionally, the tool offers shadow effects to enhance the visual appeal of the Polaroid frame. This tool is ideal for creating nostalgic photo presentations, social media posts, or personalized gifts, making images look artistic and vintage.

Leave a Reply

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