Please bookmark this page to avoid losing your image tool!

Image Pattern Generator

(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,
    outputWidth = 512,
    outputHeight = 512,
    tileScale = 1.0,
    tileRotation = 0, // Rotation in degrees for each tile
    globalOpacity = 1.0,
    patternOffsetX = 0, // Overall pattern X offset
    patternOffsetY = 0  // Overall pattern Y offset
) {
    // Parameter sanitization and type conversion
    const numOutputWidth = Math.max(1, parseInt(String(outputWidth), 10) || 512);
    const numOutputHeight = Math.max(1, parseInt(String(outputHeight), 10) || 512);
    const numTileScale = Math.max(0.001, parseFloat(String(tileScale)) || 1.0); // Avoid zero/negative/too small
    const numTileRotation = parseFloat(String(tileRotation)) || 0;
    const numGlobalOpacity = Math.max(0, Math.min(1, parseFloat(String(globalOpacity)) || 1.0));
    const numPatternOffsetX = parseFloat(String(patternOffsetX)) || 0;
    const numPatternOffsetY = parseFloat(String(patternOffsetY)) || 0;

    const errorCanvas = document.createElement('canvas'); 
    errorCanvas.width = numOutputWidth;
    errorCanvas.height = numOutputHeight;
    const errorCtx = errorCanvas.getContext('2d');

    function drawError(message) {
        if (errorCtx) {
            errorCtx.fillStyle = 'grey';
            errorCtx.fillRect(0, 0, numOutputWidth, numOutputHeight);
            const fontSize = Math.max(12, Math.min(numOutputWidth, numOutputHeight) / 20);
            errorCtx.font = `${fontSize}px Arial`;
            errorCtx.fillStyle = 'white';
            errorCtx.textAlign = 'center';
            errorCtx.textBaseline = 'middle';
            errorCtx.fillText(message, numOutputWidth / 2, numOutputHeight / 2);
        }
        return errorCanvas;
    }

    if (!originalImg || !(originalImg instanceof HTMLImageElement)) {
         return drawError("Invalid image object provided.");
    }

    // Handle image loading
    if (!originalImg.complete) {
        try {
            await new Promise((resolve, reject) => {
                originalImg.onload = resolve;
                originalImg.onerror = () => reject(new Error("Image loading failed."));
                // If src is not set and not already loading/complete, it won't load.
                if (!originalImg.src && !originalImg.complete) {
                     reject(new Error("Image has no src and is not loaded."));
                }
            });
        } catch (e) {
            console.error(e.message);
            return drawError(e.message);
        }
    }

    // After load (or if already complete), check natural dimensions
    if (originalImg.naturalWidth === 0 || originalImg.naturalHeight === 0) {
        return drawError("Image has zero dimensions or is invalid.");
    }

    const tileNativeWidth = originalImg.naturalWidth;
    const tileNativeHeight = originalImg.naturalHeight;

    // Create the main output canvas
    const outputCanvas = document.createElement('canvas');
    outputCanvas.width = numOutputWidth;
    outputCanvas.height = numOutputHeight;
    const ctx = outputCanvas.getContext('2d');
    if (!ctx) {
        return drawError("Could not create output canvas context.");
    }

    if (numGlobalOpacity < 1.0) {
        ctx.globalAlpha = numGlobalOpacity;
    }

    const pattern = ctx.createPattern(originalImg, 'repeat');
    if (!pattern) {
        if (numGlobalOpacity < 1.0) ctx.globalAlpha = 1.0; // Reset alpha
        return drawError("Failed to create pattern from image.");
    }

    if (typeof DOMMatrix !== 'undefined') {
        let finalMatrix = new DOMMatrix(); // Starts as identity matrix

        // 1. Apply overall pattern offset.
        // This translates the entire pattern grid.
        if (numPatternOffsetX !== 0 || numPatternOffsetY !== 0) {
            finalMatrix = finalMatrix.translate(numPatternOffsetX, numPatternOffsetY);
        }
        
        // 2. Create the transformation for individual tiles (scale & rotate around tile center).
        // The matrix M_tile = T_center * R * S * T_invcenter applies these operations.
        // DOMMatrix methods like .translate(), .scale(), .rotate() PRE-MULTIPLY: M_new = Op * M_current.
        // So we build M_tile by applying T_invcenter, then S, then R, then T_center.
        const tileCenterX = tileNativeWidth / 2;
        const tileCenterY = tileNativeHeight / 2;
        
        let tileTransform = new DOMMatrix(); // Identity
        tileTransform = tileTransform.translate(-tileCenterX, -tileCenterY);          // M_tile = T_invcenter
        tileTransform = tileTransform.scale(numTileScale, numTileScale);              // M_tile = S * T_invcenter
        tileTransform = tileTransform.rotate(numTileRotation);                        // M_tile = R * S * T_invcenter
        tileTransform = tileTransform.translate(tileCenterX, tileCenterY);            // M_tile = T_center * R * S * T_invcenter
        
        // 3. Combine: FinalMatrix = OffsetMatrix * TileTransformMatrix
        // This means the tile transformation is applied, and then the result is offset.
        finalMatrix = finalMatrix.multiply(tileTransform);

        try {
            pattern.setTransform(finalMatrix);
        } catch (e) {
            console.warn("Pattern.setTransform failed. Error:", e.message, "Proceeding without tile transformations/offset.");
            // If setTransform fails, the pattern will be drawn without these custom transforms.
        }
    } else {
        console.warn("DOMMatrix not supported. Tile scale/rotation and pattern offset may not be applied.");
    }
    
    ctx.fillStyle = pattern;
    ctx.fillRect(0, 0, numOutputWidth, numOutputHeight);

    if (numGlobalOpacity < 1.0) {
        ctx.globalAlpha = 1.0; // Reset globalAlpha as good practice
    }

    return outputCanvas;
}

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 Pattern Generator is a tool that allows users to create repeating patterns from a selected image. Users can customize the output by adjusting various parameters such as the width and height of the generated pattern, scaling and rotating individual tiles, and modifying the overall opacity of the pattern. This tool is useful for designers, artists, and anyone looking to create unique backgrounds, textiles, wallpapers, or any other graphical elements that require patterned imagery.

Leave a Reply

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