Please bookmark this page to avoid losing your image tool!

Image Character Design 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.
/**
 * Adds character-like features such as eyes, a mustache, a hat, or a bowtie to an image.
 * This function takes an image and draws various "character" accessories on top of it,
 * returning a new canvas with the result.
 *
 * @param {Image} originalImg - The original JavaScript Image object to process.
 * @param {string} features - A comma-separated string of features to add. Options: 'eyes', 'mustache', 'hat', 'bowtie'. Default: 'eyes,mustache'.
 * @param {number} eyeSize - The size of the eyes, relative to the image width. Default: 0.1.
 * @param {number} eyeYPosition - The vertical position of the eyes (0 = top, 1 = bottom). Default: 0.4.
 * @param {string} hatType - The type of hat to draw. Options: 'tophat', 'partyhat'. Default: 'tophat'.
 * @param {string} accessoryColor1 - The primary color for accessories like the mustache and main hat part. Can be any valid CSS color. Default: 'black'.
 * @param {string} accessoryColor2 - The secondary color for accessories like the bowtie and hatband. Can be any valid CSS color. Default: 'red'.
 * @returns {HTMLCanvasElement} A canvas element with the original image and the character features drawn on it.
 */
async function processImage(originalImg, features = 'eyes,mustache', eyeSize = 0.1, eyeYPosition = 0.4, hatType = 'tophat', accessoryColor1 = 'black', accessoryColor2 = 'red') {

    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    // Set canvas dimensions to match the image
    const w = originalImg.naturalWidth;
    const h = originalImg.naturalHeight;
    canvas.width = w;
    canvas.height = h;

    // Draw the original image onto the canvas
    ctx.drawImage(originalImg, 0, 0, w, h);

    const featureList = features.split(',').map(f => f.trim().toLowerCase());
    const centerX = w / 2;
    // Use eyeSize to define a base unit for sizing other features proportionally
    const baseUnit = w * eyeSize;

    const drawEyes = () => {
        const scleraRadius = baseUnit / 2;
        const pupilRadius = scleraRadius * 0.5;
        const eyeSeparation = scleraRadius * 1.5;
        const eyeCenterY = h * eyeYPosition;
        const leftEyeX = centerX - eyeSeparation;
        const rightEyeX = centerX + eyeSeparation;
        const pupilOffsetX = scleraRadius * 0.25;
        const pupilOffsetY = scleraRadius * 0.1;

        ctx.fillStyle = 'white';
        ctx.strokeStyle = 'black';
        ctx.lineWidth = Math.max(1, baseUnit * 0.05);

        // Draw left eye
        ctx.beginPath();
        ctx.arc(leftEyeX, eyeCenterY, scleraRadius, 0, Math.PI * 2);
        ctx.fill();
        ctx.stroke();
        ctx.fillStyle = 'black';
        ctx.beginPath();
        ctx.arc(leftEyeX + pupilOffsetX, eyeCenterY + pupilOffsetY, pupilRadius, 0, Math.PI * 2);
        ctx.fill();

        // Draw right eye
        ctx.fillStyle = 'white';
        ctx.beginPath();
        ctx.arc(rightEyeX, eyeCenterY, scleraRadius, 0, Math.PI * 2);
        ctx.fill();
        ctx.stroke();
        ctx.fillStyle = 'black';
        ctx.beginPath();
        ctx.arc(rightEyeX + pupilOffsetX, eyeCenterY + pupilOffsetY, pupilRadius, 0, Math.PI * 2);
        ctx.fill();
    };
    
    const drawMustache = () => {
        const mustacheY = (h * eyeYPosition) + (baseUnit * 0.8);
        const mustacheWidth = baseUnit * 2.5;
        const mustacheHeight = baseUnit * 0.5;

        ctx.fillStyle = accessoryColor1;
        ctx.strokeStyle = 'rgba(0,0,0,0.5)';
        ctx.lineWidth = Math.max(1, baseUnit * 0.04);
        
        ctx.beginPath();
        ctx.moveTo(centerX - mustacheWidth/2, mustacheY);
        ctx.quadraticCurveTo(centerX - mustacheWidth/4, mustacheY - mustacheHeight, centerX, mustacheY);
        ctx.quadraticCurveTo(centerX + mustacheWidth/4, mustacheY - mustacheHeight, centerX + mustacheWidth/2, mustacheY);
        ctx.quadraticCurveTo(centerX + mustacheWidth/4, mustacheY + mustacheHeight/2, centerX, mustacheY);
        ctx.quadraticCurveTo(centerX - mustacheWidth/4, mustacheY + mustacheHeight/2, centerX - mustacheWidth/2, mustacheY);
        ctx.closePath();
        ctx.fill();
        ctx.stroke();
    };
    
    const drawHat = () => {
        if (hatType.toLowerCase() === 'tophat') {
            const hatHeight = h * 0.2;
            const hatWidth = w * 0.35;
            const brimHeight = hatHeight * 0.2;
            const crownHeight = hatHeight * 0.8;
            const crownWidth = hatWidth * 0.7;
            const hatTopY = h * 0.05;

            ctx.fillStyle = accessoryColor1;
            ctx.fillRect(centerX - hatWidth / 2, hatTopY + crownHeight, hatWidth, brimHeight);
            ctx.fillRect(centerX - crownWidth / 2, hatTopY, crownWidth, crownHeight);
            
            ctx.fillStyle = accessoryColor2;
            const bandHeight = crownHeight * 0.2;
            ctx.fillRect(centerX - crownWidth / 2, hatTopY + crownHeight - bandHeight, crownWidth, bandHeight);

        } else if (hatType.toLowerCase() === 'partyhat') {
            const hatHeight = h * 0.25;
            const hatWidth = w * 0.25;
            const hatBaseY = h * 0.25;
            const hatTopY = hatBaseY - hatHeight;

            ctx.fillStyle = accessoryColor2;
            ctx.beginPath();
            ctx.moveTo(centerX, hatTopY);
            ctx.lineTo(centerX - hatWidth / 2, hatBaseY);
            ctx.lineTo(centerX + hatWidth / 2, hatBaseY);
            ctx.closePath();
            ctx.fill();
            
            ctx.fillStyle = accessoryColor1;
            const dotRadius = hatWidth * 0.08;
            for (let i = 0; i < 7; i++) {
                const y = hatTopY + dotRadius + Math.random() * (hatHeight - dotRadius * 2);
                const progress = (y - hatTopY) / hatHeight;
                const currentWidth = hatWidth * progress;
                const x = centerX + (Math.random() * 2 - 1) * (currentWidth / 2 - dotRadius);
                ctx.beginPath();
                ctx.arc(x, y, dotRadius, 0, 2 * Math.PI);
                ctx.fill();
            }

            ctx.beginPath();
            ctx.arc(centerX, hatTopY, baseUnit * 0.1, 0, Math.PI * 2);
            ctx.fill();
        }
    };
    
    const drawBowtie = () => {
        const bowtieY = h * 0.75;
        const bowtieWidth = baseUnit * 2;
        const bowtieHeight = bowtieWidth * 0.6;
        const knotSize = bowtieWidth * 0.2;

        ctx.fillStyle = accessoryColor2;
        ctx.beginPath();
        ctx.moveTo(centerX - knotSize/2, bowtieY);
        ctx.lineTo(centerX - bowtieWidth/2, bowtieY - bowtieHeight/2);
        ctx.lineTo(centerX - bowtieWidth/2, bowtieY + bowtieHeight/2);
        ctx.closePath();
        ctx.fill();
        
        ctx.beginPath();
        ctx.moveTo(centerX + knotSize/2, bowtieY);
        ctx.lineTo(centerX + bowtieWidth/2, bowtieY - bowtieHeight/2);
        ctx.lineTo(centerX + bowtieWidth/2, bowtieY + bowtieHeight/2);
        ctx.closePath();
        ctx.fill();
        
        ctx.fillStyle = accessoryColor1;
        ctx.fillRect(centerX - knotSize/2, bowtieY - knotSize/2, knotSize, knotSize);
    };

    // Draw enabled features in a logical order (back to front)
    if (featureList.includes('hat')) drawHat();
    if (featureList.includes('bowtie')) drawBowtie();
    if (featureList.includes('eyes')) drawEyes();
    if (featureList.includes('mustache')) drawMustache();
    
    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 Character Design Tool allows users to add whimsical character-like features to their images. By selecting from various accessories such as eyes, mustaches, hats, and bowties, users can transform their photos into playful caricatures. This tool is perfect for creating unique avatars, fun social media posts, or personalized gifts. Users can customize the appearance by adjusting eye size, position, and accessory colors, making it a versatile option for enhancing images with a creative touch.

Leave a Reply

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