You can edit the below JavaScript code to customize the image tool.
Apply Changes
/**
* 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;
}
Apply Changes