Please bookmark this page to avoid losing your image tool!

Image Maze Pattern Filter Effect

(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.
/**
 * Applies a maze pattern filter effect to an image.
 * The original image is used as the background for the paths of the maze,
 * and walls are drawn on top.
 *
 * @param {Image} originalImg The original JavaScript Image object (should be loaded).
 * @param {number} [cellSize=20] The size of each cell in the maze grid.
 * @param {string} [wallColor="black"] The color of the maze walls.
 * @param {number} [wallThickness=2] The thickness of the maze walls.
 * @returns {HTMLCanvasElement} A canvas element with the maze effect applied.
 */
function processImage(originalImg, cellSize = 20, wallColor = "black", wallThickness = 2) {
    // 1. Canvas setup
    const canvas = document.createElement('canvas');
    const imgWidth = originalImg.naturalWidth || originalImg.width;
    const imgHeight = originalImg.naturalHeight || originalImg.height;

    if (imgWidth === 0 || imgHeight === 0) {
        // Image not loaded or invalid
        console.warn("Image dimensions are zero. Ensure the image is loaded before processing.");
        // Return a small canvas with an error message
        canvas.width = 200;
        canvas.height = 150;
        const ctxError = canvas.getContext('2d');
        if (ctxError) {
            ctxError.fillStyle = 'lightgray';
            ctxError.fillRect(0, 0, canvas.width, canvas.height);
            ctxError.fillStyle = 'red';
            ctxError.textAlign = 'center';
            ctxError.font = '12px Arial';
            ctxError.fillText("Error: Image not loaded or invalid.", canvas.width / 2, canvas.height / 2);
        }
        return canvas;
    }

    canvas.width = imgWidth;
    canvas.height = imgHeight;
    const ctx = canvas.getContext('2d');

    if (!ctx) {
        // Fallback for environments where canvas context might not be available
        console.error("Could not get 2D context from canvas.");
        const errDiv = document.createElement('div');
        errDiv.textContent = "Error: Canvas 2D context not available.";
        return errDiv;
    }

    // 2. Draw original image onto the canvas
    ctx.drawImage(originalImg, 0, 0, imgWidth, imgHeight);

    // Parameter validation and adjustment
    if (cellSize <= 0) cellSize = 20;
    if (wallThickness < 0) wallThickness = 0;

    // 3. Maze grid initialization
    const numCols = Math.floor(imgWidth / cellSize);
    const numRows = Math.floor(imgHeight / cellSize);

    // If maze dimensions are too small (e.g., cellSize larger than image dimensions),
    // no maze can be meaningfully generated. Return the canvas with the original image.
    if (numCols <= 0 || numRows <= 0) {
        return canvas;
    }

    const grid = [];
    for (let r = 0; r < numRows; r++) {
        grid[r] = [];
        for (let c = 0; c < numCols; c++) {
            grid[r][c] = {
                r: r, // Row index
                c: c, // Column index
                walls: [true, true, true, true], // [Top, Right, Bottom, Left] - true if wall exists
                visited: false
            };
        }
    }

    // 4. Maze Generation (Depth-First Search algorithm)
    const stack = [];
    // Start DFS from a random cell for variety
    let currentRow = Math.floor(Math.random() * numRows);
    let currentCol = Math.floor(Math.random() * numCols);
    
    let currentCell = grid[currentRow][currentCol];
    currentCell.visited = true;
    stack.push(currentCell);
    let visitedCells = 1;
    const totalCells = numRows * numCols;

    while (visitedCells < totalCells && stack.length > 0) {
        currentCell = stack[stack.length - 1]; // Peek at the top of the stack (current cell)
        let r = currentCell.r;
        let c = currentCell.c;

        const unvisitedNeighbors = [];
        // Check North neighbor
        if (r > 0 && !grid[r - 1][c].visited) {
            unvisitedNeighbors.push({ cell: grid[r - 1][c], currentWallIndex: 0, neighborWallIndex: 2 }); // Current's Top, Neighbor's Bottom
        }
        // Check East neighbor
        if (c < numCols - 1 && !grid[r][c + 1].visited) {
            unvisitedNeighbors.push({ cell: grid[r][c + 1], currentWallIndex: 1, neighborWallIndex: 3 }); // Current's Right, Neighbor's Left
        }
        // Check South neighbor
        if (r < numRows - 1 && !grid[r + 1][c].visited) {
            unvisitedNeighbors.push({ cell: grid[r + 1][c], currentWallIndex: 2, neighborWallIndex: 0 }); // Current's Bottom, Neighbor's Top
        }
        // Check West neighbor
        if (c > 0 && !grid[r][c - 1].visited) {
            unvisitedNeighbors.push({ cell: grid[r][c - 1], currentWallIndex: 3, neighborWallIndex: 1 }); // Current's Left, Neighbor's Right
        }

        if (unvisitedNeighbors.length > 0) {
            // Choose a random unvisited neighbor
            const randomIndex = Math.floor(Math.random() * unvisitedNeighbors.length);
            const chosenNeighborData = unvisitedNeighbors[randomIndex];
            const nextCell = chosenNeighborData.cell;

            // Remove wall between currentCell and nextCell
            currentCell.walls[chosenNeighborData.currentWallIndex] = false;
            nextCell.walls[chosenNeighborData.neighborWallIndex] = false;

            // Move to the chosen neighbor
            nextCell.visited = true;
            visitedCells++;
            stack.push(nextCell);
        } else {
            // No unvisited neighbors, backtrack
            stack.pop();
        }
    }

    // 5. Draw Maze Walls
    // Only draw walls if wallThickness is greater than 0
    if (wallThickness > 0) {
        ctx.strokeStyle = wallColor;
        ctx.lineWidth = wallThickness;
        // 'square' makes lines extend slightly for better corner connection, 'butt' ends lines exactly at coordinates
        ctx.lineCap = 'square'; 
        ctx.beginPath();

        for (let r = 0; r < numRows; r++) {
            for (let c = 0; c < numCols; c++) {
                const cell = grid[r][c];
                const x = c * cellSize;
                const y = r * cellSize;

                // Draw Top wall of cell (r,c) if it exists
                if (cell.walls[0]) {
                    ctx.moveTo(x, y);
                    ctx.lineTo(x + cellSize, y);
                }
                // Draw Right wall of cell (r,c) if it exists
                if (cell.walls[1]) {
                    ctx.moveTo(x + cellSize, y);
                    ctx.lineTo(x + cellSize, y + cellSize);
                }
                // Draw Bottom wall of cell (r,c) if it exists
                if (cell.walls[2]) {
                    ctx.moveTo(x + cellSize, y + cellSize);
                    ctx.lineTo(x, y + cellSize);
                }
                // Draw Left wall of cell (r,c) if it exists
                if (cell.walls[3]) {
                    ctx.moveTo(x, y + cellSize);
                    ctx.lineTo(x, y);
                }
            }
        }
        ctx.stroke(); // Draw all accumulated line segments
    }

    // 6. Return the canvas with the maze effect
    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 Maze Pattern Filter Effect tool allows users to apply a maze pattern filter to an image. This effect utilizes the original image as the background, overlaying it with maze pathways defined by walls. Users can customize the appearance of the maze by adjusting parameters such as cell size, wall color, and wall thickness. This tool is ideal for adding a creative, playful touch to images, making it suitable for artistic projects, game design, or creating unique backgrounds for digital content.

Leave a Reply

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