Please bookmark this page to avoid losing your image tool!

Image Manga 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.
async function processImage(originalImg, threshold = 128, levels = 2, invert = "false") {
    // Coerce and validate parameters
    let numThreshold = Number(threshold);
    if (isNaN(numThreshold) || numThreshold < 0 || numThreshold > 255) {
        numThreshold = 128; // Default if invalid
    }

    let numLevels = Number(levels);
    // Manga style implies at least 2 levels (black and white).
    // If levels is 1 or invalid, default to 2 levels.
    if (isNaN(numLevels) || numLevels < 2) {
        numLevels = 2;
    }

    const shouldInvert = String(invert).toLowerCase() === "true";

    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d', { willReadFrequently: true }); // Optimization hint
    
    // Use naturalWidth/Height for robustness, fallback to width/height if natural are 0
    const imgWidth = originalImg.naturalWidth || originalImg.width;
    const imgHeight = originalImg.naturalHeight || originalImg.height;

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

    if (imgWidth === 0 || imgHeight === 0) {
        // If image dimensions are zero (e.g., image not loaded properly),
        // return an empty (but correctly sized if possible) canvas.
        // Or one could throw an error. For now, return blank canvas.
        ctx.clearRect(0,0,canvas.width, canvas.height); 
        return canvas;
    }

    ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
    
    let imageData;
    try {
        imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    } catch (e) {
        // This can happen due to cross-origin issues if the image source is external
        // and the server doesn't provide appropriate CORS headers.
        console.error("Failed to get ImageData:", e);
        // Draw an error message on the canvas as a fallback.
        ctx.fillStyle = 'rgba(255, 255, 255, 0.8)'; // Semi-transparent white background for text
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        ctx.font = "bold 16px Arial";
        ctx.fillStyle = "red";
        ctx.textAlign = "center";
        const message = "Error: Cannot process image.";
        const message2 = "(Possibly cross-origin restrictions)";
        ctx.fillText(message, canvas.width / 2, canvas.height / 2 - 10);
        ctx.font = "14px Arial";
        ctx.fillText(message2, canvas.width / 2, canvas.height / 2 + 10);
        return canvas;
    }
    
    const data = imageData.data;

    for (let i = 0; i < data.length; i += 4) {
        const r = data[i];
        const g = data[i + 1];
        const b = data[i + 2];

        // Calculate grayscale value (luminance method)
        // Standard weights: 0.299 R + 0.587 G + 0.114 B
        let gray = 0.299 * r + 0.587 * g + 0.114 * b;
        gray = Math.max(0, Math.min(255, gray)); // Clamp gray value (0-255)

        let finalColor;

        if (numLevels <= 2) {
            // Binary thresholding for 2 levels (or if numLevels was invalidly set to < 2)
            finalColor = (gray > numThreshold) ? 255 : 0;
        } else { 
            // Posterization for numLevels > 2
            // Calculate the size of each color step/band
            const step = 255 / (numLevels - 1);
            // Quantize the gray value to the nearest step
            finalColor = Math.round(gray / step) * step;
            // Round finalColor to ensure it's an integer (e.g., 127.5 becomes 128)
            finalColor = Math.round(finalColor); 
            // Clamp final color to be safe, though calculation should be within range
            finalColor = Math.max(0, Math.min(255, finalColor)); 
        }

        if (shouldInvert) {
            finalColor = 255 - finalColor;
        }

        data[i] = finalColor;     // Red
        data[i + 1] = finalColor; // Green
        data[i + 2] = finalColor; // Blue
        // Alpha (data[i+3]) remains unchanged
    }

    ctx.putImageData(imageData, 0, 0);
    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 Manga Filter Effect Tool allows users to transform their images into a stylized manga or comic book appearance. By processing the image through various adjustments such as thresholding, level quantization, and optional color inversion, users can create striking monochrome visuals. This tool is suitable for artists, graphic designers, and hobbyists looking to produce manga-style artwork, enhance photos for creative projects, or simply experiment with artistic image effects.

Leave a Reply

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