Please bookmark this page to avoid losing your image tool!

Image Collage Filter 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.
async function processImage(originalImg, gridSizeX = 4, gridSizeY = 4, maxRotation = 5, maxOffset = 5, gap = 2, borderColor = 'white', borderWidth = 1) {
    // Parameter parsing with defaults
    let pGridSizeX = parseInt(String(gridSizeX), 10);
    const _gridSizeX = (Number.isFinite(pGridSizeX) && pGridSizeX > 0) ? pGridSizeX : 4;

    let pGridSizeY = parseInt(String(gridSizeY), 10);
    const _gridSizeY = (Number.isFinite(pGridSizeY) && pGridSizeY > 0) ? pGridSizeY : 4;

    let pMaxRotationDeg = parseFloat(String(maxRotation));
    const _maxRotationDeg = Number.isFinite(pMaxRotationDeg) ? pMaxRotationDeg : 5.0;

    let pMaxOffset = parseFloat(String(maxOffset));
    // Math.abs ensures _maxOffset is a positive magnitude for spread calculation.
    // The actual offset applied will be random in [-pMaxOffset, +pMaxOffset].
    const _maxOffset = Number.isFinite(pMaxOffset) ? Math.abs(pMaxOffset) : 5.0;

    let pGap = parseFloat(String(gap));
    const _gap = Number.isFinite(pGap) ? pGap : 2.0; // Gap can be negative for overlap

    const _borderColor = (borderColor === undefined || borderColor === null || String(borderColor).trim() === "") ? 'white' : String(borderColor);

    let pBorderWidth = parseFloat(String(borderWidth));
    const _borderWidth = (Number.isFinite(pBorderWidth) && pBorderWidth >= 0) ? pBorderWidth : 1.0;

    // Validate image object
    if (!originalImg || typeof originalImg.width !== 'number' || typeof originalImg.height !== 'number' || originalImg.width === 0 || originalImg.height === 0) {
        console.error("Invalid image object provided or image not loaded.");
        const errCanvas = document.createElement('canvas');
        errCanvas.width = 200; errCanvas.height = 50;
        const errCtx = errCanvas.getContext('2d');
        if (errCtx) {
          errCtx.fillStyle = 'rgba(255,0,0,0.7)';
          errCtx.fillRect(0,0,errCanvas.width, errCanvas.height);
          errCtx.fillStyle = 'white';
          errCtx.font = '16px Arial';
          errCtx.textAlign = 'center';
          errCtx.textBaseline = 'middle';
          errCtx.fillText("Invalid Image Data", errCanvas.width/2, errCanvas.height/2);
        }
        return errCanvas;
    }

    const pieceWidth = originalImg.width / _gridSizeX;
    const pieceHeight = originalImg.height / _gridSizeY;

    // Calculate canvas dimensions
    // Base width/height from pieces: originalImg.width and originalImg.height
    // Add space for borders around each piece: _gridSizeX * 2 * _borderWidth
    // Add space for gaps between pieces: (_gridSizeX - 1) * _gap
    // Add padding for random offsets: 2 * _maxOffset (allows pieces to shift by +/-_maxOffset)
    
    const totalContentWidth = (originalImg.width) + 
                              (_gridSizeX * 2 * _borderWidth) + 
                              (Math.max(0, _gridSizeX - 1) * _gap);
    
    const canvasWidth = totalContentWidth + 2 * _maxOffset;

    const totalContentHeight = (originalImg.height) +
                               (_gridSizeY * 2 * _borderWidth) +
                               (Math.max(0, _gridSizeY - 1) * _gap);
    
    const canvasHeight = totalContentHeight + 2 * _maxOffset;
    
    const canvas = document.createElement('canvas');
    canvas.width = Math.max(1, Math.round(canvasWidth)); // Ensure canvas dimensions are at least 1 and integer
    canvas.height = Math.max(1, Math.round(canvasHeight));
    
    const ctx = canvas.getContext('2d');
    if (!ctx) {
        console.error("Could not get canvas 2D context.");
        // Return a placeholder element or throw an error
        const div = document.createElement('div');
        div.innerText = "Error: Canvas context not available.";
        return div;
    }

    // The actual drawable content area starts after accounting for potential negative offsets.
    const contentOriginX = _maxOffset;
    const contentOriginY = _maxOffset;

    for (let row = 0; row < _gridSizeY; row++) {
        for (let col = 0; col < _gridSizeX; col++) {
            const sx = col * pieceWidth;
            const sy = row * pieceHeight;

            // Calculate the an chor position (center) an d an image piece in the grid structure,
            // including its border and gap, before random transformations.
            // This position is relative to the canvas origin.
            const cellBaseX = contentOriginX + col * (pieceWidth + 2 * _borderWidth + _gap);
            const cellBaseY = contentOriginY + row * (pieceHeight + 2 * _borderWidth + _gap);
            
            // Center of the image part of the cell (pivot for rotation)
            const cellImageCenterX = cellBaseX + _borderWidth + pieceWidth / 2;
            const cellImageCenterY = cellBaseY + _borderWidth + pieceHeight / 2;
            
            // Apply random transformations
            const currentRotationRad = (Math.random() * 2 - 1) * _maxRotationDeg * Math.PI / 180;
            const currentOffsetX = (Math.random() * 2 - 1) * _maxOffset;
            const currentOffsetY = (Math.random() * 2 - 1) * _maxOffset;
            
            const finalDrawCenterX = cellImageCenterX + currentOffsetX;
            const finalDrawCenterY = cellImageCenterY + currentOffsetY;

            ctx.save();
            ctx.translate(finalDrawCenterX, finalDrawCenterY);
            ctx.rotate(currentRotationRad);

            // Draw border (if any)
            if (_borderWidth > 0) {
                ctx.fillStyle = _borderColor;
                ctx.fillRect(
                    -pieceWidth / 2 - _borderWidth,
                    -pieceHeight / 2 - _borderWidth,
                    pieceWidth + 2 * _borderWidth,
                    pieceHeight + 2 * _borderWidth
                );
            }

            // Draw the image piece, centered at the new (0,0) after transformations
            ctx.drawImage(
                originalImg,
                sx, sy, pieceWidth, pieceHeight,             // Source rectangle (from original image)
                -pieceWidth / 2, -pieceHeight / 2, pieceWidth, pieceHeight // Destination rectangle (drawn centered)
            );

            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

The Image Collage Filter Tool allows users to create artistic collages from a single image by dividing it into a customizable grid. Users can specify the number of rows and columns, apply random rotation and offsets to each piece, and add gaps and borders between them. This tool is ideal for creating unique visuals for social media posts, art projects, and personal photo presentations, bringing a playful and dynamic style to standard images.

Leave a Reply

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