Please bookmark this page to avoid losing your image tool!

Image Polaroid Filter Application

(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,
    photoSize = 300,
    borderColor = "#F0F0F0",
    vintageLevel = 0.35, // 0 (none) to 1 (strong)
    vignetteStrength = 0.4, // 0 (none) to 1 (strong)
    shadowBlur = 20,
    shadowOffsetX = 7,
    shadowOffsetY = 7,
    shadowColor = "rgba(0,0,0,0.25)"
) {
    // Ensure numeric parameters are numbers and provide fallbacks if NaN
    const numPhotoSize = Number(photoSize) || 300;
    let numVintageLevel = Number(vintageLevel);
    if (isNaN(numVintageLevel)) numVintageLevel = 0.35;
    let numVignetteStrength = Number(vignetteStrength);
    if (isNaN(numVignetteStrength)) numVignetteStrength = 0.4;
    const numShadowBlur = Number(shadowBlur) || 0;
    const numShadowOffsetX = Number(shadowOffsetX) || 0;
    const numShadowOffsetY = Number(shadowOffsetY) || 0;

    // Validate and clamp strength/level parameters
    numVintageLevel = Math.max(0, Math.min(1, numVintageLevel));
    numVignetteStrength = Math.max(0, Math.min(1, numVignetteStrength));

    // 1. Calculate dimensions for the Polaroid frame and photo area
    const imageToDrawSize = numPhotoSize; // Photo area is square

    // Classic Polaroid-like border proportions (relative to photo size)
    const sideBorder = imageToDrawSize * 0.07;
    const topBorder = imageToDrawSize * 0.07;
    const bottomBorder = imageToDrawSize * 0.30; // Larger bottom border

    const frameWidth = imageToDrawSize + 2 * sideBorder;
    const frameHeight = imageToDrawSize + topBorder + bottomBorder;

    // Canvas size needs to accommodate the frame and its shadow
    const absShadowBlur = Math.abs(numShadowBlur);
    const canvasWidth = frameWidth + 2 * absShadowBlur + Math.abs(numShadowOffsetX);
    const canvasHeight = frameHeight + 2 * absShadowBlur + Math.abs(numShadowOffsetY);

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

    // 3. Determine Source Image Cropping (center crop to square)
    // Use naturalWidth/Height for intrinsic image dimensions
    const imgNaturalWidth = originalImg.naturalWidth || originalImg.width;
    const imgNaturalHeight = originalImg.naturalHeight || originalImg.height;

    if (imgNaturalWidth === 0 || imgNaturalHeight === 0) {
        // Handle invalid image dimensions gracefully (e.g., draw empty Polaroid)
        console.error("Original image has zero width or height.");
        // Optionally draw just the frame or return an empty canvas
    }

    let sx = 0, sy = 0, sWidth = imgNaturalWidth, sHeight = imgNaturalHeight;

    if (imgNaturalWidth > 0 && imgNaturalHeight > 0) { // Proceed with cropping only if dimensions are valid
        if (imgNaturalWidth / imgNaturalHeight > 1) { // Landscape image
            sHeight = imgNaturalHeight;
            sWidth = imgNaturalHeight; // Crop to square based on height
            sx = (imgNaturalWidth - sWidth) / 2;
            sy = 0;
        } else { // Portrait or square image
            sWidth = imgNaturalWidth;
            sHeight = imgNaturalWidth; // Crop to square based on width
            sx = 0;
            sy = (imgNaturalHeight - sHeight) / 2;
        }
    }


    // 4. Draw Polaroid Frame (with shadow)
    // Calculate top-left position of the frame, allowing space for shadow
    const frameRectX = absShadowBlur + (numShadowOffsetX < 0 ? Math.abs(numShadowOffsetX) : 0);
    const frameRectY = absShadowBlur + (numShadowOffsetY < 0 ? Math.abs(numShadowOffsetY) : 0);
    
    if (absShadowBlur > 0 || numShadowOffsetX !== 0 || numShadowOffsetY !== 0) {
        ctx.shadowColor = shadowColor;
        ctx.shadowBlur = absShadowBlur;
        ctx.shadowOffsetX = numShadowOffsetX;
        ctx.shadowOffsetY = numShadowOffsetY;
    }

    ctx.fillStyle = borderColor;
    ctx.fillRect(frameRectX, frameRectY, frameWidth, frameHeight);

    // Reset shadow for subsequent drawing operations (image, vignette)
    ctx.shadowColor = 'transparent';
    ctx.shadowBlur = 0;
    ctx.shadowOffsetX = 0;
    ctx.shadowOffsetY = 0;

    // 5. Draw Image with Vintage Filters
    const imgDestX = frameRectX + sideBorder;
    const imgDestY = frameRectY + topBorder;

    if (numVintageLevel > 0) {
        const sepiaVal = numVintageLevel * 0.6;       // Max 60% sepia
        const saturateVal = 1 - numVintageLevel * 0.5; // Reduce saturation up to 50%
        const brightnessVal = 1 + numVintageLevel * 0.05; // Slight brightness increase
        const contrastVal = 1 - numVintageLevel * 0.1; // Slight contrast decrease (soften)
        
        ctx.filter = `sepia(${sepiaVal.toFixed(2)}) saturate(${saturateVal.toFixed(2)}) brightness(${brightnessVal.toFixed(2)}) contrast(${contrastVal.toFixed(2)})`;
    }
    
    if (sWidth > 0 && sHeight > 0) { // Only draw if source dimensions are valid
        ctx.drawImage(
            originalImg,
            sx, sy, sWidth, sHeight, // Source rect (cropped square from original image)
            imgDestX, imgDestY, imageToDrawSize, imageToDrawSize // Destination rect (photo area on canvas)
        );
    }


    // Reset filter after drawing image, so vignette is not affected by image filters
    ctx.filter = 'none';

    // 6. Apply Vignette (Overlay on top of the image)
    if (numVignetteStrength > 0 && imageToDrawSize > 0) {
        const vignetteCenterX = imgDestX + imageToDrawSize / 2;
        const vignetteCenterY = imgDestY + imageToDrawSize / 2;
        
        const outerRadius = (imageToDrawSize / 2) * Math.sqrt(2); // Distance from center to corner of square photo area
        
        // Inner radius calculation determines how far the vignette effect spreads:
        // vignetteStrength = 0 -> innerRadiusRatio = 1 (innerRadius = outerRadius, no visible effect)
        // vignetteStrength = 1 -> innerRadiusRatio = 0.3 (strong vignette, transparent center is 30% of outerRadius)
        const innerRadiusRatio = 1 - numVignetteStrength * 0.7; 
        const innerRadius = outerRadius * innerRadiusRatio;

        const gradient = ctx.createRadialGradient(
            vignetteCenterX, vignetteCenterY, innerRadius,
            vignetteCenterX, vignetteCenterY, outerRadius
        );

        // Vignette color is typically dark (black)
        gradient.addColorStop(0, `rgba(0,0,0,0)`); // Center of vignette is transparent
        // Opacity of vignette edges controlled by numVignetteStrength. Max 0.8 alpha for a less harsh effect.
        gradient.addColorStop(1, `rgba(0,0,0,${(numVignetteStrength * 0.8).toFixed(2)})`); 

        ctx.fillStyle = gradient;
        ctx.fillRect(imgDestX, imgDestY, imageToDrawSize, imageToDrawSize); // Apply gradient over the photo area
    }

    // 7. Return Canvas
    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 Filter Application allows users to apply a classic Polaroid style to their images. This tool enables you to transform your photos by cropping them to a square format, adding a stylish border, and applying vintage effects such as sepia tones, saturation adjustments, and brightness tweaks. Additionally, you can customize the shadow effects and add a vignette for an enhanced visual impact. Ideal for creating nostalgic images, this application can be used for personal projects, social media posts, or any creative endeavors where a Polaroid-like appearance is desired.

Leave a Reply

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