Please bookmark this page to avoid losing your image tool!

Image Op Art Filter Effect 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.
function processImage(originalImg, cellSize = 10, shapeType = "circle", minShapeFactor = 0.1, maxShapeFactor = 0.9, foregroundColor = "black", backgroundColor = "white", invertEffectStr = "false") {
    // Parameter validation and type conversion
    cellSize = Number(cellSize);
    minShapeFactor = Number(minShapeFactor);
    maxShapeFactor = Number(maxShapeFactor);
    const invertEffect = invertEffectStr.toLowerCase() === 'true';

    if (isNaN(cellSize) || cellSize <= 0) {
        cellSize = 10;
    }
    if (isNaN(minShapeFactor) || minShapeFactor < 0 || minShapeFactor > 1) {
        minShapeFactor = 0.1;
    }
    if (isNaN(maxShapeFactor) || maxShapeFactor < 0 || maxShapeFactor > 1) {
        maxShapeFactor = 0.9;
    }
    if (minShapeFactor > maxShapeFactor) {
        [minShapeFactor, maxShapeFactor] = [maxShapeFactor, minShapeFactor]; // Swap if min > max
    }
    if (typeof shapeType !== 'string' || (shapeType !== 'circle' && shapeType !== 'square')) {
        shapeType = 'circle'; // Default to circle if invalid
    }
    if (typeof foregroundColor !== 'string') {
        foregroundColor = 'black';
    }
    if (typeof backgroundColor !== 'string') {
        backgroundColor = 'white';
    }

    const outputCanvas = document.createElement('canvas');
    // Ensure canvas dimensions are integers if originalImg dimensions are not
    outputCanvas.width = Math.floor(originalImg.width);
    outputCanvas.height = Math.floor(originalImg.height);
    
    // Prevent issues if image has 0 width/height
    if (outputCanvas.width === 0 || outputCanvas.height === 0) {
        return outputCanvas; // Return empty canvas
    }

    const ctx = outputCanvas.getContext('2d');

    // Draw background
    ctx.fillStyle = backgroundColor;
    ctx.fillRect(0, 0, outputCanvas.width, outputCanvas.height);

    // Create a temporary canvas to get pixel data from originalImg
    const tempCanvas = document.createElement('canvas');
    tempCanvas.width = outputCanvas.width;
    tempCanvas.height = outputCanvas.height;
    const tempCtx = tempCanvas.getContext('2d', { willReadFrequently: true }); // Optimization hint for frequent getImageData
    
    try {
        tempCtx.drawImage(originalImg, 0, 0, outputCanvas.width, outputCanvas.height);
    } catch (e) {
        // Error drawing original image (e.g., if originalImg is not valid or fully loaded)
        // Return canvas with background only
        return outputCanvas;
    }

    let imageData;
    try {
        imageData = tempCtx.getImageData(0, 0, tempCanvas.width, tempCanvas.height);
    } catch (e) {
        // Error getting image data (e.g., tainted canvas due to CORS issues)
        // Return canvas with background only
        return outputCanvas; 
    }
    
    const data = imageData.data;
    const imageWidth = imageData.width; // This will be tempCanvas.width
    const imageHeight = imageData.height; // This will be tempCanvas.height

    // Helper function to get average brightness (luminance) of a cell
    function getAverageBrightness(cellPixelX, cellPixelY, cellWidth, cellHeight) {
        let totalLuminance = 0;
        let pixelCount = 0;
        
        // Define the actual region to sample pixels from, clamped to image dimensions
        const startX = Math.floor(cellPixelX);
        const startY = Math.floor(cellPixelY);
        const endX = Math.min(startX + Math.floor(cellWidth), imageWidth);
        const endY = Math.min(startY + Math.floor(cellHeight), imageHeight);

        for (let y = startY; y < endY; y++) {
            for (let x = startX; x < endX; x++) {
                const i = (y * imageWidth + x) * 4; // Calculate index in the 1D pixel array
                const r = data[i];
                const g = data[i + 1];
                const b = data[i + 2];
                // Alpha (data[i+3]) is ignored for brightness calculation here
                
                // Luminance formula (perceptual brightness), normalized to 0-1
                const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
                totalLuminance += luminance;
                pixelCount++;
            }
        }
        return pixelCount > 0 ? totalLuminance / pixelCount : 0;
    }

    ctx.fillStyle = foregroundColor;

    // Iterate over cells in a grid
    for (let y = 0; y < imageHeight; y += cellSize) {
        for (let x = 0; x < imageWidth; x += cellSize) {
            // Determine actual width and height of the current cell, handling edges
            const currentCellWidth = Math.min(cellSize, imageWidth - x);
            const currentCellHeight = Math.min(cellSize, imageHeight - y);

            if (currentCellWidth <= 0 || currentCellHeight <= 0) continue; // Skip if cell has no area

            // Calculate average brightness for the current cell
            let normalizedBrightness = getAverageBrightness(x, y, currentCellWidth, currentCellHeight);

            if (invertEffect) {
                normalizedBrightness = 1 - normalizedBrightness;
            }
            
            // Modulate shape size based on brightness
            const shapeSizeFactor = minShapeFactor + normalizedBrightness * (maxShapeFactor - minShapeFactor);
            
            // Determine the base dimension for scaling the shape (use smaller of cell width/height)
            const baseDimensionForShape = Math.min(currentCellWidth, currentCellHeight);
            const actualShapeSize = baseDimensionForShape * shapeSizeFactor;

            // Calculate center of the current cell to draw the shape
            const centerX = x + currentCellWidth / 2;
            const centerY = y + currentCellHeight / 2;

            // Draw the shape
            if (shapeType === "circle") {
                const radius = actualShapeSize / 2;
                if (radius > 0) { // Only draw if radius is positive
                    ctx.beginPath();
                    ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI);
                    ctx.fill();
                }
            } else if (shapeType === "square") {
                if (actualShapeSize > 0) { // Only draw if side length is positive
                    ctx.fillRect(centerX - actualShapeSize / 2, centerY - actualShapeSize / 2, actualShapeSize, actualShapeSize);
                }
            }
        }
    }
    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 Op Art Filter Effect Generator allows users to transform their images into visually striking Op Art patterns using customizable parameters. By processing the original image, this tool creates artworks composed of geometric shapes such as circles or squares, which vary in size based on the average brightness of different areas. Users can adjust aspects like the size of the cells, the type of shape to use, and the color scheme. It is ideal for artists, designers, or anyone looking to create unique visual effects from photos for projects, social media, or personal expression.

Leave a Reply

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