Please bookmark this page to avoid losing your image tool!

Image Magazine Collage 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, numPieces = 10, maxRotationDeg = 15, maxPieceOffset = 20, pieceBorderColor = "black", pieceBorderWidth = 2) {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    // Use naturalWidth/Height for intrinsic image dimensions if available
    const imgWidth = originalImg.naturalWidth || originalImg.width;
    const imgHeight = originalImg.naturalHeight || originalImg.height;

    if (imgWidth === 0 || imgHeight === 0) {
        // Handle placeholder, unloaded, or broken images
        console.warn("Image has zero width or height. Returning a 1x1 canvas.");
        canvas.width = 1; 
        canvas.height = 1;
        // Optionally draw a small indicator or leave it blank
        // ctx.fillStyle = 'red';
        // ctx.fillRect(0,0,1,1);
        return canvas;
    }

    canvas.width = imgWidth;
    canvas.height = imgHeight;

    // Helper function for random numbers in a range
    function getRandom(min, max) {
        // Ensure min <= max, otherwise swap them
        if (min > max) {
            let temp = min;
            min = max;
            max = temp;
        }
        return Math.random() * (max - min) + min;
    }

    // Jitter factor for piece shape irregularity (percentage of half-dimension)
    const jitterFactor = 0.15; // Adjust for more/less irregular shapes

    for (let i = 0; i < numPieces; i++) {
        // 1. Define the piece's approximate source dimensions from the original image
        // These dimensions define the bounding box of the image content to be used for the piece.
        const pieceMinDimFactor = 0.1;  // Min piece dimension as factor of image's smaller side
        const pieceMaxDimFactor = 0.6;  // Max piece dimension as factor of image's corresponding side

        let minAllowedSize = Math.min(imgWidth, imgHeight) * pieceMinDimFactor;
        minAllowedSize = Math.max(10, minAllowedSize); // Absolute minimum size of 10px for sanity

        let srcW = getRandom(imgWidth * pieceMinDimFactor, imgWidth * pieceMaxDimFactor);
        let srcH = getRandom(imgHeight * pieceMinDimFactor, imgHeight * pieceMaxDimFactor);
        
        // Ensure pieces are not excessively small or too large
        srcW = Math.max(minAllowedSize, srcW);
        srcH = Math.max(minAllowedSize, srcH);
        srcW = Math.min(srcW, imgWidth); // Cannot be wider than the image
        srcH = Math.min(srcH, imgHeight); // Cannot be taller than the image
        
        // Determine source position (top-left corner of the piece in the original image)
        let srcX = getRandom(0, imgWidth - srcW);
        let srcY = getRandom(0, imgHeight - srcH);

        // 2. Determine where to place the center of this piece on the canvas
        // The piece (of nominal size srcW, srcH) is centered here before final offset and rotation.
        // Range for center: [half piece dim, img dim - half piece dim]
        // This strategy aims to keep the nominal piece (before offset) mostly inside canvas bounds.
        const targetCenterXRangeMin = srcW / 2;
        const targetCenterXRangeMax = imgWidth - srcW / 2;
        const targetCenterYRangeMin = srcH / 2;
        const targetCenterYRangeMax = imgHeight - srcH / 2;
        
        let targetCenterX = getRandom(targetCenterXRangeMin, targetCenterXRangeMax);
        let targetCenterY = getRandom(targetCenterYRangeMin, targetCenterYRangeMax);
        
        // Apply final random offset and rotation
        const finalOffsetX = getRandom(-maxPieceOffset, maxPieceOffset);
        const finalOffsetY = getRandom(-maxPieceOffset, maxPieceOffset);
        const rotationAngleRad = getRandom(-maxRotationDeg, maxRotationDeg) * (Math.PI / 180);

        ctx.save(); // Outer save: preserves state before this piece's transformations
        
        // Translate to the piece's target center and apply offset, then rotate
        ctx.translate(targetCenterX + finalOffsetX, targetCenterY + finalOffsetY);
        ctx.rotate(rotationAngleRad);

        // 3. Define an irregular quadrilateral path, centered at the current (0,0)
        // The path's extents will roughly match srcW, srcH.
        const halfW = srcW / 2;
        const halfH = srcH / 2;

        // Path points for the quadrilateral (TopLeft, TopRight, BottomRight, BottomLeft)
        // Jitter is applied to each vertex to make the shape irregular.
        const points = [
            {x: -halfW + getRandom(-halfW * jitterFactor, halfW * jitterFactor), y: -halfH + getRandom(-halfH * jitterFactor, halfH * jitterFactor)},
            {x:  halfW + getRandom(-halfW * jitterFactor, halfW * jitterFactor), y: -halfH + getRandom(-halfH * jitterFactor, halfH * jitterFactor)},
            {x:  halfW + getRandom(-halfW * jitterFactor, halfW * jitterFactor), y:  halfH + getRandom(-halfH * jitterFactor, halfH * jitterFactor)},
            {x: -halfW + getRandom(-halfW * jitterFactor, halfW * jitterFactor), y:  halfH + getRandom(-halfH * jitterFactor, halfH * jitterFactor)}
        ];

        // Helper function to build the path from an array of points
        function buildPath(pointsArray) {
            ctx.beginPath();
            if (pointsArray.length === 0) return;
            ctx.moveTo(pointsArray[0].x, pointsArray[0].y);
            for (let k = 1; k < pointsArray.length; k++) {
                ctx.lineTo(pointsArray[k].x, pointsArray[k].y);
            }
            ctx.closePath();
        }
        
        // 4. Apply clipping mask and draw the image segment
        ctx.save(); // Inner save: preserves state before clipping (transformations are active)
        buildPath(points); // Define the path for clipping
        ctx.clip();        // Apply the clipping mask
        
        // Draw the selected part of the original image (srcX, srcY, srcW, srcH)
        // into a rectangle defined by (-halfW, -halfH, srcW, srcH) in the current transformed space.
        // This rectangle is aligned with where the clipping path was defined.
        ctx.drawImage(originalImg, 
                      srcX, srcY, srcW, srcH,    // Source rectangle from original image
                      -halfW, -halfH, srcW, srcH // Destination rectangle in current transformed space
                     );
        ctx.restore(); // Inner restore: removes clip, transformations are still active

        // 5. Draw border (if any) along the same path
        // The border is drawn after restoring from the clip, so it's not clipped itself.
        if (pieceBorderWidth > 0 && pieceBorderColor && pieceBorderColor !== "transparent") {
            buildPath(points); // Rebuild the path (Path2D could optimize this if needed)
            ctx.strokeStyle = pieceBorderColor;
            ctx.lineWidth = pieceBorderWidth;
            ctx.stroke();
        }
        
        ctx.restore(); // Outer restore: removes transformations for this piece, back to canvas base state
    }

    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 Magazine Collage Filter Effect Tool allows users to create unique collage-like effects from images. By randomly selecting and transforming pieces of an original image, this tool can generate visually appealing compositions with irregular shapes. Users can specify the number of pieces, rotation angles, offsets, and border properties for each piece, making it a useful resource for graphic designers, artists, and anyone looking to add a creative touch to their images. Ideal for creating layouts for magazines, social media posts, or artistic presentations, it enhances visual storytelling by combining multiple aspects of an image into a single artwork.

Leave a Reply

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