Please bookmark this page to avoid losing your image tool!

Photo Mania Maker

(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, numPhotos = "15", zoomLevel = "1.15") {
    // Parse constraint parameters
    let count = parseInt(numPhotos, 10);
    if (isNaN(count) || count < 1) count = 15;
    if (count > 50) count = 50; // Cap to avoid performance issues
    
    let zoom = parseFloat(zoomLevel);
    if (isNaN(zoom) || zoom < 1) zoom = 1.15;
    if (zoom > 3) zoom = 3;

    const width = originalImg.naturalWidth;
    const height = originalImg.naturalHeight;

    // Create the main output canvas
    const canvas = document.createElement('canvas');
    canvas.width = width;
    canvas.height = height;
    const ctx = canvas.getContext('2d');

    // Optimization check: Use an offscreen canvas to pre-apply heavy filters
    // This gives the polaroid inner images their "Photomania" pop!
    const vibrantCanvas = document.createElement('canvas');
    vibrantCanvas.width = width;
    vibrantCanvas.height = height;
    const vCtx = vibrantCanvas.getContext('2d');
    
    // Fill background for transparent PNGs
    vCtx.fillStyle = '#111111';
    vCtx.fillRect(0, 0, width, height);
    vCtx.filter = 'saturate(1.5) contrast(1.1) brightness(1.05)';
    vCtx.drawImage(originalImg, 0, 0, width, height);
    vCtx.filter = 'none';

    // Build main background
    ctx.fillStyle = '#111111';
    ctx.fillRect(0, 0, width, height);
    
    // Paint a blurred & darkened background of the original image
    ctx.filter = `blur(${Math.max(width, height) * 0.015}px) brightness(0.6) sepia(0.3)`;
    ctx.drawImage(originalImg, 0, 0, width, height);
    ctx.filter = 'none';

    // Apply a radial vignette focus to center
    const gradient = ctx.createRadialGradient(width/2, height/2, Math.min(width, height)*0.3, width/2, height/2, Math.max(width, height)*0.8);
    gradient.addColorStop(0, 'rgba(0,0,0,0)');
    gradient.addColorStop(1, 'rgba(0,0,0,0.8)');
    ctx.fillStyle = gradient;
    ctx.fillRect(0, 0, width, height);

    // Calculate grid logic to ensure the "polaroids" cover the image properly
    const aspect = width / height;
    const cols = Math.max(1, Math.round(Math.sqrt(count * aspect)));
    const rows = Math.max(1, Math.ceil(count / cols));

    const colW = width / cols;
    const rowH = height / rows;

    // Sizes of internal squares and polaroid borders
    const pSize = Math.max(colW, rowH) * 1.25;
    const innerWidth = pSize;
    const innerHeight = pSize;

    const pBorderTop = pSize * 0.05;
    const pBorderSide = pSize * 0.05;
    const pBorderBottom = pSize * 0.25;

    const pw = innerWidth + 2 * pBorderSide;
    const ph = innerHeight + pBorderTop + pBorderBottom;

    // Generate grid positions with random offsets
    const cells = [];
    for (let i = 0; i < count; i++) {
        const r = Math.floor(i / cols);
        const c = i % cols;
        const itemsInRow = (r === rows - 1) ? (count - r * cols) : cols;
        const rowOffset = (cols - itemsInRow) * colW / 2;
        
        const bx = rowOffset + c * colW + colW / 2;
        const by = r * rowH + rowH / 2;
        
        const cx = bx + (Math.random() - 0.5) * colW * 0.6;
        const cy = by + (Math.random() - 0.5) * rowH * 0.6;
        const angle = (Math.random() - 0.5) * 0.45; // roughly ±13 degrees
        
        cells.push({ cx, cy, angle });
    }

    // Shuffle iteration order so Z-index depth is unpredictable
    const indices = Array.from({ length: count }, (_, i) => i);
    for (let i = indices.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [indices[i], indices[j]] = [indices[j], indices[i]];
    }

    // Render the scatter polaroid collage
    for (const idx of indices) {
        const { cx, cy, angle } = cells[idx];
        
        ctx.save();
        
        // --- 1. Polaroid Paper Setup & Shadow ---
        ctx.translate(cx, cy);
        ctx.rotate(angle);
        
        ctx.shadowColor = 'rgba(0,0,0,0.7)';
        ctx.shadowBlur = Math.max(width, height) * 0.012;
        ctx.shadowOffsetX = ctx.shadowBlur * 0.3;
        ctx.shadowOffsetY = ctx.shadowBlur * 0.4;
        
        ctx.fillStyle = '#fafafa';
        ctx.fillRect(-pw/2, -ph/2, pw, ph);
        
        // Clear shadow for next steps
        ctx.shadowColor = 'transparent';
        
        // --- 2. Create the Window to the vibrant background ---
        const ix = -innerWidth / 2;
        const iy = -innerHeight / 2 + pBorderTop / 2 - pBorderBottom / 2;
        
        ctx.beginPath();
        ctx.rect(ix, iy, innerWidth, innerHeight);
        
        // Save state to isolate the clipping mechanism
        ctx.save();
        ctx.clip();
        
        // Apply zoom and inverse transform to map exact world coordinates
        // so the image looks like it perfectly continues from polaroid to polaroid
        ctx.scale(zoom, zoom);
        ctx.rotate(-angle);
        ctx.translate(-cx, -cy);
        
        ctx.drawImage(vibrantCanvas, 0, 0, width, height);
        
        // Drop clip region
        ctx.restore();
        
        // Apply subtle inset stroke (inner shadow border)
        ctx.beginPath();
        ctx.rect(ix, iy, innerWidth, innerHeight);
        ctx.strokeStyle = 'rgba(0,0,0,0.12)';
        ctx.lineWidth = Math.max(1, pSize * 0.005);
        ctx.stroke();
        
        ctx.restore(); // Restore completely out of main polaroid bounds
        
        // --- 3. Draw masking tape ---
        ctx.save();
        ctx.translate(cx, cy);
        ctx.rotate(angle);
        
        // Position tape at top-middle, spanning outer edge
        ctx.translate(0, -ph/2 + pBorderTop * 0.7);
        ctx.rotate((Math.random() - 0.5) * 0.4);
        
        const tw = pw * 0.28;
        const th = pBorderTop * 1.5;
        
        ctx.fillStyle = 'rgba(235, 235, 220, 0.85)';
        ctx.shadowColor = 'rgba(0,0,0,0.2)';
        ctx.shadowBlur = Math.max(width, height) * 0.003;
        ctx.shadowOffsetX = 1;
        ctx.shadowOffsetY = 2;
        
        ctx.fillRect(-tw/2, -th/2, tw, th);
        
        // Minor tape wrinkle lines
        ctx.strokeStyle = 'rgba(0,0,0,0.06)';
        ctx.lineWidth = Math.max(1, pSize * 0.003);
        const margin = th * 0.25;
        
        ctx.beginPath();
        ctx.moveTo(-tw/2 + margin, -th/2 + margin);
        ctx.lineTo(tw/2 - margin, th/2 - margin);
        ctx.stroke();
        
        ctx.restore();
    }

    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

Photo Mania Maker is an image processing tool that transforms a single photo into a dynamic, stylized collage of scattered Polaroid-style snapshots. The tool creates a layered effect by overlaying multiple photographic frames with randomized rotations, shadows, and even decorative masking tape elements over a blurred, darkened version of your original image. This creates a cohesive, ‘scattered’ visual story where the image appears to continue across the different frames. It is ideal for creating creative social media posts, artistic digital scrapbooks, or unique photographic montages for personal and professional design projects.

Leave a Reply

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