Please bookmark this page to avoid losing your image tool!

Image Polaroid Instant Film Filter Effect 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,
    polaroidPhotoSize = 300, // The width/height of the square photo area in pixels
    sepiaStrength = 0.25,    // 0 to 1 for sepia effect
    desaturation = 0.15,     // 0 to 1 (0 = original saturation, 1 = grayscale)
    contrastValue = 0.95,    // Multiplier, e.g., 1 is normal
    brightnessValue = 1.05,  // Multiplier, e.g., 1 is normal
    blurRadius = 0.3,        // In pixels, for subtle softness
    borderColor = '#f3f3ea', // Color of the Polaroid border (off-white/light beige)
    vignetteIntensity = 0.35,// 0 to 1, strength of the dark corners
    grainAmount = 0.05,      // 0 to 1, strength of the film grain
    imageCornerRadiusRatio = 0.015 // Ratio of polaroidPhotoSize for rounded corners of the image
) {

    // Basic validation for the input image
    if (!originalImg || typeof originalImg.width === 'undefined' || originalImg.width === 0 || originalImg.height === 0) {
        console.error("Original image is invalid or not loaded. Ensure it's an Image object with dimensions.");
        const errorCanvas = document.createElement('canvas');
        errorCanvas.width = Math.max(1, polaroidPhotoSize); // Ensure canvas has some size
        errorCanvas.height = Math.max(1, polaroidPhotoSize);
        const errCtx = errorCanvas.getContext('2d');
        if (errCtx) {
            errCtx.fillStyle = 'red';
            errCtx.fillRect(0,0, errorCanvas.width, errorCanvas.height);
            errCtx.fillStyle = 'white';
            errCtx.font = '12px Arial';
            errCtx.textAlign = 'center';
            errCtx.fillText('Invalid Image', errorCanvas.width / 2, errorCanvas.height / 2);
        }
        return errorCanvas;
    }

    // Calculate border padding based on typical Polaroid proportions
    const paddingSideRatio = 0.06;
    const paddingTopRatio = 0.06;
    const paddingBottomRatio = 0.30; // Larger bottom "chin" characteristic of Polaroids

    const paddingSide = paddingSideRatio * polaroidPhotoSize;
    const paddingTop = paddingTopRatio * polaroidPhotoSize;
    const paddingBottom = paddingBottomRatio * polaroidPhotoSize;

    const canvasWidth = polaroidPhotoSize + 2 * paddingSide;
    const canvasHeight = polaroidPhotoSize + paddingTop + paddingBottom;

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

    // 1. Draw the Polaroid border
    ctx.fillStyle = borderColor;
    ctx.fillRect(0, 0, canvasWidth, canvasHeight);

    // Create an intermediate canvas for image processing (the photo part)
    const imgCanvas = document.createElement('canvas');
    imgCanvas.width = polaroidPhotoSize;
    imgCanvas.height = polaroidPhotoSize;
    const imgCtx = imgCanvas.getContext('2d');

    // Helper function for creating a rounded rectangle path
    const roundedRectPath = (context, x, y, w, h, r) => {
        if (w < 2 * r) r = w / 2;
        if (h < 2 * r) r = h / 2;
        if (r < 0) r = 0;
        context.beginPath();
        context.moveTo(x + r, y);
        context.arcTo(x + w, y, x + w, y + h, r);
        context.arcTo(x + w, y + h, x, y + h, r);
        context.arcTo(x, y + h, x, y, r);
        context.arcTo(x, y, x + w, y, r);
        context.closePath();
    };
    
    // 2. Apply rounded corners to the photo area if specified
    const cornerRadius = imageCornerRadiusRatio * polaroidPhotoSize;
    if (cornerRadius > 0) {
        imgCtx.save();
        roundedRectPath(imgCtx, 0, 0, polaroidPhotoSize, polaroidPhotoSize, cornerRadius);
        imgCtx.clip();
    }

    // 3. Draw the original image, cropped and scaled to fit the square photo area
    // This maintains aspect ratio by cropping either width or height.
    const G_imgAspectRatio = originalImg.width / originalImg.height;
    const P_photoAspectRatio = 1; // Target aspect ratio is square

    let sx, sy, sWidth, sHeight;
    if (G_imgAspectRatio > P_photoAspectRatio) { // Image is wider than target square
        sHeight = originalImg.height;
        sWidth = sHeight * P_photoAspectRatio; // sWidth will be originalImg.height
        sx = (originalImg.width - sWidth) / 2;
        sy = 0;
    } else { // Image is taller or same aspect as target square
        sWidth = originalImg.width;
        sHeight = sWidth / P_photoAspectRatio; // sHeight will be originalImg.width
        sy = (originalImg.height - sHeight) / 2;
        sx = 0;
    }
    imgCtx.drawImage(originalImg, sx, sy, sWidth, sHeight, 0, 0, polaroidPhotoSize, polaroidPhotoSize);
    
    if (cornerRadius > 0) {
      imgCtx.restore(); // Remove clipping path after drawing, so subsequent operations are not clipped
    }

    // 4. Apply filters (sepia, desaturation, contrast, brightness, blur)
    // Use a temporary canvas to apply filters to avoid issues with `ctx.filter` on self-drawing.
    const tempFilterCanvas = document.createElement('canvas');
    tempFilterCanvas.width = polaroidPhotoSize;
    tempFilterCanvas.height = polaroidPhotoSize;
    const tempFilterCtx = tempFilterCanvas.getContext('2d');

    let filterString = '';
    if (desaturation > 0) filterString += `saturate(${1 - Math.min(1, Math.max(0, desaturation))}) `;
    if (sepiaStrength > 0) filterString += `sepia(${Math.min(1, Math.max(0, sepiaStrength))}) `;
    // Ensure contrast and brightness are non-negative
    filterString += `contrast(${Math.max(0, contrastValue)}) `;
    filterString += `brightness(${Math.max(0, brightnessValue)}) `;
    if (blurRadius > 0) filterString += `blur(${Math.max(0, blurRadius)}px) `;
    
    if (filterString.trim() !== '') {
        tempFilterCtx.filter = filterString.trim();
    }
    tempFilterCtx.drawImage(imgCanvas, 0, 0); // Draw current imgCanvas (possibly clipped image) to tempFilterCanvas with filters

    // Copy filtered image back to imgCanvas
    imgCtx.clearRect(0, 0, polaroidPhotoSize, polaroidPhotoSize); 
    imgCtx.drawImage(tempFilterCanvas, 0, 0);

    // 5. Apply film grain
    if (grainAmount > 0 && grainAmount <= 1) {
        const imageData = imgCtx.getImageData(0, 0, polaroidPhotoSize, polaroidPhotoSize);
        const pixels = imageData.data;
        // Adjust grain intensity: grainAmount=1 -> max noise +/-25.
        const grainIntensity = grainAmount * 25; 

        for (let i = 0; i < pixels.length; i += 4) {
            // Only apply grain to non-transparent pixels (respecting rounded corners)
            if (pixels[i + 3] > 0) { 
                const noise = (Math.random() - 0.5) * grainIntensity; // Monochromatic noise
                pixels[i] = Math.max(0, Math.min(255, pixels[i] + noise));
                pixels[i + 1] = Math.max(0, Math.min(255, pixels[i + 1] + noise));
                pixels[i + 2] = Math.max(0, Math.min(255, pixels[i + 2] + noise));
            }
        }
        imgCtx.putImageData(imageData, 0, 0);
    }

    // 6. Apply vignette
    if (vignetteIntensity > 0 && vignetteIntensity <= 1) {
        imgCtx.save();
        const centerX = polaroidPhotoSize / 2;
        const centerY = polaroidPhotoSize / 2;
        
        // Outer radius slightly larger than half the diagonal to cover corners
        const outerRadius = Math.sqrt(centerX*centerX + centerY*centerY) * 1.1; // polaroidPhotoSize * 0.707 * 1.1
        
        // Inner radius defines transparent center. As intensity increases, transparent center shrinks.
        const baseInnerRadiusPercent = 0.4; // Percentage of photoSize
        const innerRadius = polaroidPhotoSize * baseInnerRadiusPercent * (1 - vignetteIntensity * 0.9);


        const gradient = imgCtx.createRadialGradient(centerX, centerY, innerRadius, centerX, centerY, outerRadius);
        gradient.addColorStop(0, 'rgba(0,0,0,0)');
        gradient.addColorStop(1, `rgba(0,0,0,${Math.min(1, Math.max(0,vignetteIntensity))})`);
        
        imgCtx.fillStyle = gradient;
        imgCtx.globalCompositeOperation = 'source-over'; 
        imgCtx.fillRect(0, 0, polaroidPhotoSize, polaroidPhotoSize);
        imgCtx.restore();
    }

    // 7. Draw the processed image (from imgCanvas) onto the final Polaroid canvas
    const photoX = paddingSide;
    const photoY = paddingTop;
    ctx.drawImage(imgCanvas, photoX, photoY, polaroidPhotoSize, polaroidPhotoSize);
    
    // 8. Optional: add a very subtle inner shadow/line to distinguish photo from border
    ctx.strokeStyle = 'rgba(0,0,0,0.1)';
    ctx.lineWidth = 0.5; // Keep it very thin
    // Offset by 0.5 for sharper lines if lineWidth is integer, but with 0.5 width not strictly needed.
    ctx.strokeRect(photoX - ctx.lineWidth, photoY - ctx.lineWidth, polaroidPhotoSize + ctx.lineWidth*2, polaroidPhotoSize + ctx.lineWidth*2);

    return finalCanvas;
}

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 Film Filter Effect Tool allows users to apply a vintage Polaroid filter effect to their images. This tool can create a nostalgic look by adding various enhancements such as sepia tones, desaturation, contrast adjustments, brightness changes, soft blurring, and film grain effects. Users can customize the size of the Polaroid frame, select the color of the border, and apply a vignette effect for a more distinct finish. This versatile tool is perfect for photographers and social media enthusiasts who want to transform their photos into charming, retro-style images, suitable for sharing on platforms like Instagram or printing for physical displays.

Leave a Reply

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

Other Image Tools:

Image Holga Camera Filter Effect Tool

Image Fisheye Lens Distortion Filter Effect Tool

Image Kodak Gold 200 Film Filter Effect Tool

Photo Macro Filter Effect Tool

Image Neutral Density Filter Effect Tool

Image Green Filter Black And White Effect Tool

Image Large Format Film Filter Effect Creator

Image Pinhole Camera Filter Effect Tool

Image Warming Filter Effect Tool

Image Fujifilm Pro 400H Filter Effect Application

Image Diffusion Filter Effect Tool

Image Push-Processed Film Filter Effect Tool

Image Color Temperature Orange Filter Effect Tool

Image Kodak Ektar 100 Film Filter Effect

Image Yellow Filter Black And White Effect Tool

Image Expired Film Filter Effect Tool

Image Circular Polarizer Filter Effect Tool

Image Lomography Purple Filter Effect Tool

Image Split Field Filter Effect Tool

Image Soft Focus Filter Effect Tool

Image Medium Format Film Filter Effect

Image Wide-Angle Lens Perspective Filter Effect Tool

Olympus OM-1 Photo Filter Effect Tool

Image Fujifilm Velvia Filter Effect Tool

Image Lensbaby Selective Focus Filter Effect Tool

Image Color Temperature Blue Filter Effect Tool

Image UV Filter Effect Tool

Image Red Filter Black And White Effect Tool

Image Redscale Film Filter Effect

Image Cinestill 800T Filter Effect Tool

Image Glimmer Glass Filter Effect Tool

Image Star Filter Effect Tool

Image Kodak Portra 400 Film Filter Effect

Image Fujifilm Superia Filter Effect Tool

Image Tilt-Shift Lens Filter Effect Tool

Image Graduated Neutral Density Filter Effect Tool

See All →