Please bookmark this page to avoid losing your image tool!

Image From Animated Characters 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.
/**
 * Applies a cartoon/comic book effect to an image.
 * This is achieved by reducing the color palette (posterization) and adding outlines around edges.
 *
 * @param {HTMLImageElement} originalImg The original image object.
 * @param {number} posterizationLevels The number of color levels per channel (e.g., 4 gives 4^3 = 64 colors in total). A value between 2 and 255.
 * @param {number} outlineThreshold The sensitivity for edge detection. A lower value means more sensitive (more lines). Range is roughly 0-255.
 * @param {string} outlineColor The color of the outlines (e.g., 'black', '#FF0000', 'rgb(0,0,255)').
 * @param {number} outlineWidth The thickness of the outlines in pixels. A value of 0 means no outlines.
 * @returns {HTMLCanvasElement} A canvas element with the cartoonized image.
 */
function processImage(originalImg, posterizationLevels = 4, outlineThreshold = 80, outlineColor = 'black', outlineWidth = 2) {
    // 0. SETUP
    const width = originalImg.width;
    const height = originalImg.height;
    const canvas = document.createElement('canvas');
    canvas.width = width;
    canvas.height = height;
    // Use { willReadFrequently: true } for performance hint when using getImageData frequently.
    const ctx = canvas.getContext('2d', {
        willReadFrequently: true
    });

    // Draw image to a temporary canvas to read its pixel data
    const tempCanvas = document.createElement('canvas');
    tempCanvas.width = width;
    tempCanvas.height = height;
    const tempCtx = tempCanvas.getContext('2d', {
        willReadFrequently: true
    });
    tempCtx.drawImage(originalImg, 0, 0);
    const originalData = tempCtx.getImageData(0, 0, width, height);

    // Helper to parse the outline color string into an [r, g, b] array
    const outlineRgba = (() => {
        const c = document.createElement('canvas');
        c.width = c.height = 1;
        const cCtx = c.getContext('2d', {
            willReadFrequently: true
        });
        cCtx.fillStyle = outlineColor;
        cCtx.fillRect(0, 0, 1, 1);
        return cCtx.getImageData(0, 0, 1, 1).data;
    })();

    // 1. POSTERIZATION
    // This reduces the number of colors in the image.
    const levels = Math.max(2, Math.min(255, Math.floor(posterizationLevels)));
    const step = 255 / (levels - 1);
    const posterizedData = tempCtx.createImageData(width, height);
    for (let i = 0; i < originalData.data.length; i += 4) {
        posterizedData.data[i] = Math.round(originalData.data[i] / step) * step;
        posterizedData.data[i + 1] = Math.round(originalData.data[i + 1] / step) * step;
        posterizedData.data[i + 2] = Math.round(originalData.data[i + 2] / step) * step;
        posterizedData.data[i + 3] = originalData.data[i + 3];
    }

    if (outlineWidth < 1) {
        // If no outline is needed, just draw the posterized image and return.
        ctx.putImageData(posterizedData, 0, 0);
        return canvas;
    }

    // 2. EDGE DETECTION (SOBEL OPERATOR)
    // First, create a grayscale representation of the image.
    const grayscaleData = new Uint8ClampedArray(width * height);
    for (let i = 0; i < originalData.data.length; i += 4) {
        const r = originalData.data[i];
        const g = originalData.data[i + 1];
        const b = originalData.data[i + 2];
        grayscaleData[i / 4] = 0.299 * r + 0.587 * g + 0.114 * b;
    }

    const sobelX = [
        [-1, 0, 1],
        [-2, 0, 2],
        [-1, 0, 1]
    ];
    const sobelY = [
        [-1, -2, -1],
        [0, 0, 0],
        [1, 2, 1]
    ];
    const isEdge = new Uint8ClampedArray(width * height);

    // Apply Sobel filter to find edges.
    for (let y = 1; y < height - 1; y++) {
        for (let x = 1; x < width - 1; x++) {
            let px = 0;
            let py = 0;
            for (let j = 0; j < 3; j++) {
                for (let i = 0; i < 3; i++) {
                    const gray = grayscaleData[(y + j - 1) * width + (x + i - 1)];
                    px += gray * sobelX[j][i];
                    py += gray * sobelY[j][i];
                }
            }
            const magnitude = Math.sqrt(px * px + py * py);
            if (magnitude > outlineThreshold) {
                isEdge[y * width + x] = 1;
            }
        }
    }

    // 3. COMBINE POSTERIZED IMAGE AND OUTLINES
    const finalData = tempCtx.createImageData(width, height);
    const halfWidth = Math.floor(outlineWidth / 2);

    for (let y = 0; y < height; y++) {
        for (let x = 0; x < width; x++) {
            const index = (y * width + x) * 4;
            let isOutlinePixel = false;

            // Check a square neighborhood for any edge pixels to create thick lines.
            // This is the most computationally expensive part of the function.
            for (let j = -halfWidth; j <= halfWidth; j++) {
                for (let i = -halfWidth; i <= halfWidth; i++) {
                    const checkY = y + j;
                    const checkX = x + i;
                    if (checkY >= 0 && checkY < height && checkX >= 0 && checkX < width) {
                        if (isEdge[checkY * width + checkX] === 1) {
                            isOutlinePixel = true;
                            break;
                        }
                    }
                }
                if (isOutlinePixel) break;
            }

            if (isOutlinePixel) {
                finalData.data[index] = outlineRgba[0];
                finalData.data[index + 1] = outlineRgba[1];
                finalData.data[index + 2] = outlineRgba[2];
                finalData.data[index + 3] = 255;
            } else {
                finalData.data[index] = posterizedData.data[index];
                finalData.data[index + 1] = posterizedData.data[index + 1];
                finalData.data[index + 2] = posterizedData.data[index + 2];
                finalData.data[index + 3] = posterizedData.data[index + 3];
            }
        }
    }

    // 4. DRAW FINAL IMAGE TO CANVAS
    ctx.putImageData(finalData, 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 From Animated Characters Generator’ is an online tool that transforms standard images into cartoon-style visuals. By applying a comic book effect, it simplifies the color palette through posterization and enhances the outlines around objects for a bold, artistic look. This tool can be utilized for various purposes such as creating unique avatars for social media, generating illustrations for comics or animations, and enhancing images for creative projects or marketing materials.

Leave a Reply

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