You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg) {
const canvas = document.createElement('canvas');
const width = originalImg.width || 800;
const height = originalImg.height || 800;
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
// Draw original image as blurred background
ctx.drawImage(originalImg, 0, 0, width, height);
// Add semi-transparent dark overlay to make the character pop
ctx.fillStyle = 'rgba(0, 0, 0, 0.65)';
ctx.fillRect(0, 0, width, height);
const cx = width / 2;
const cy = height * 0.4;
const size = Math.min(width, height) * 0.9;
// Character Colors
const skinTone = '#3e2723';
const darkSkinTone = '#271816';
const lipColor = '#4e342e';
const shirtColor = '#d84315';
// 1. Neck
ctx.fillStyle = skinTone;
ctx.fillRect(cx - size * 0.1, cy + size * 0.1, size * 0.2, size * 0.25);
// Neck shadow from chin
ctx.fillStyle = darkSkinTone;
ctx.fillRect(cx - size * 0.1, cy + size * 0.1, size * 0.2, size * 0.08);
// 2. Torso (Shirt)
ctx.fillStyle = shirtColor;
ctx.beginPath();
const shoulderBase = height;
const shoulderTop = cy + size * 0.28;
ctx.moveTo(cx - size * 0.45, shoulderBase);
ctx.bezierCurveTo(
cx - size * 0.45, shoulderTop,
cx + size * 0.45, shoulderTop,
cx + size * 0.45, shoulderBase
);
ctx.fill();
// Shirt collar
ctx.fillStyle = darkSkinTone;
ctx.beginPath();
ctx.ellipse(cx, shoulderTop, size * 0.15, size * 0.05, 0, 0, Math.PI);
ctx.fill();
// 3. Ears
ctx.fillStyle = skinTone;
ctx.beginPath();
ctx.ellipse(cx - size * 0.16, cy + size * 0.02, size * 0.035, size * 0.055, -Math.PI/12, 0, Math.PI * 2);
ctx.fill();
ctx.beginPath();
ctx.ellipse(cx + size * 0.16, cy + size * 0.02, size * 0.035, size * 0.055, Math.PI/12, 0, Math.PI * 2);
ctx.fill();
// Ear inner shadow
ctx.fillStyle = darkSkinTone;
ctx.beginPath();
ctx.ellipse(cx - size * 0.17, cy + size * 0.02, size * 0.015, size * 0.035, -Math.PI/12, 0, Math.PI * 2);
ctx.fill();
ctx.beginPath();
ctx.ellipse(cx + size * 0.17, cy + size * 0.02, size * 0.015, size * 0.035, Math.PI/12, 0, Math.PI * 2);
ctx.fill();
// 4. Head (Bald)
const headGradient = ctx.createRadialGradient(cx - size * 0.05, cy - size * 0.05, size * 0.02, cx, cy, size * 0.2);
headGradient.addColorStop(0, '#5d4037');
headGradient.addColorStop(0.6, skinTone);
headGradient.addColorStop(1, darkSkinTone);
ctx.fillStyle = headGradient;
ctx.beginPath();
ctx.ellipse(cx, cy, size * 0.17, size * 0.23, 0, 0, Math.PI * 2);
ctx.fill();
// 5. Eyes
const eyeY = cy - size * 0.01;
const eyeSpacing = size * 0.07;
// Eye whites
ctx.fillStyle = '#f5f5f5';
ctx.beginPath();
ctx.ellipse(cx - eyeSpacing, eyeY, size * 0.028, size * 0.014, 0, 0, Math.PI * 2);
ctx.fill();
ctx.beginPath();
ctx.ellipse(cx + eyeSpacing, eyeY, size * 0.028, size * 0.014, 0, 0, Math.PI * 2);
ctx.fill();
// Irises (Dark Brown)
ctx.fillStyle = '#110a08';
ctx.beginPath();
ctx.ellipse(cx - eyeSpacing, eyeY, size * 0.014, size * 0.014, 0, 0, Math.PI * 2);
ctx.fill();
ctx.beginPath();
ctx.ellipse(cx + eyeSpacing, eyeY, size * 0.014, size * 0.014, 0, 0, Math.PI * 2);
ctx.fill();
// Eye catchlights (Reflection)
ctx.fillStyle = '#ffffff';
ctx.beginPath();
ctx.arc(cx - eyeSpacing + size*0.004, eyeY - size*0.004, size*0.004, 0, Math.PI*2);
ctx.fill();
ctx.beginPath();
ctx.arc(cx + eyeSpacing + size*0.004, eyeY - size*0.004, size*0.004, 0, Math.PI*2);
ctx.fill();
// 6. Eyebrows
ctx.strokeStyle = '#111';
ctx.lineWidth = size * 0.018;
ctx.lineCap = 'round';
// Left eyebrow
ctx.beginPath();
ctx.moveTo(cx - eyeSpacing - size * 0.035, eyeY - size * 0.035);
ctx.quadraticCurveTo(cx - eyeSpacing, eyeY - size * 0.05, cx - eyeSpacing + size * 0.035, eyeY - size * 0.035);
ctx.stroke();
// Right eyebrow
ctx.beginPath();
ctx.moveTo(cx + eyeSpacing - size * 0.035, eyeY - size * 0.035);
ctx.quadraticCurveTo(cx + eyeSpacing, eyeY - size * 0.05, cx + eyeSpacing + size * 0.035, eyeY - size * 0.035);
ctx.stroke();
// 7. Nose
const noseY = cy + size * 0.07;
ctx.fillStyle = darkSkinTone;
ctx.beginPath();
ctx.moveTo(cx, eyeY + size * 0.02);
ctx.lineTo(cx - size * 0.028, noseY);
ctx.lineTo(cx + size * 0.028, noseY);
ctx.fill();
// Nostrils
ctx.fillStyle = '#111';
ctx.beginPath();
ctx.ellipse(cx - size * 0.018, noseY, size * 0.012, size * 0.007, -Math.PI/8, 0, Math.PI * 2);
ctx.fill();
ctx.beginPath();
ctx.ellipse(cx + size * 0.018, noseY, size * 0.012, size * 0.007, Math.PI/8, 0, Math.PI * 2);
ctx.fill();
// 8. Goatee / Beard (Adds classic style)
ctx.fillStyle = '#1a0f0e';
ctx.beginPath();
ctx.moveTo(cx - size * 0.06, noseY + size * 0.03);
ctx.lineTo(cx + size * 0.06, noseY + size * 0.03);
ctx.lineTo(cx + size * 0.045, cy + size * 0.20);
ctx.quadraticCurveTo(cx, cy + size * 0.25, cx - size * 0.045, cy + size * 0.20);
ctx.fill();
// 9. Mouth (Smiling)
const mouthY = cy + size * 0.12;
ctx.fillStyle = lipColor;
ctx.beginPath();
ctx.ellipse(cx, mouthY, size * 0.045, size * 0.02, 0, 0, Math.PI * 2);
ctx.fill();
// Teeth line
ctx.fillStyle = '#ffffff';
ctx.beginPath();
ctx.ellipse(cx, mouthY, size * 0.035, size * 0.007, 0, 0, Math.PI * 2);
ctx.fill();
// Inner mouth shadow / Lip split
ctx.strokeStyle = '#110a08';
ctx.lineWidth = size * 0.003;
ctx.beginPath();
ctx.moveTo(cx - size * 0.045, mouthY);
ctx.quadraticCurveTo(cx, mouthY + size * 0.006, cx + size * 0.045, mouthY);
ctx.stroke();
// 10. Bald head shine (Highlight top of the dome)
ctx.fillStyle = 'rgba(255, 255, 255, 0.12)';
ctx.beginPath();
ctx.ellipse(cx - size * 0.06, cy - size * 0.15, size * 0.07, size * 0.035, Math.PI / 5, 0, Math.PI * 2);
ctx.fill();
// 11. Sunglasses (Optional Cool Factor! Drawing shades over the eyes)
ctx.fillStyle = 'rgba(15, 15, 15, 0.9)';
function drawLens(x, y, lx, ly) {
const r = size * 0.015;
ctx.beginPath();
ctx.moveTo(x + r, y);
ctx.lineTo(x + lx - r, y);
ctx.quadraticCurveTo(x + lx, y, x + lx, y + r);
ctx.lineTo(x + lx, y + ly - r);
ctx.quadraticCurveTo(x + lx, y + ly, x + lx - r, y + ly);
ctx.lineTo(x + r, y + ly);
ctx.quadraticCurveTo(x, y + ly, x, y + ly - r);
ctx.lineTo(x, y + r);
ctx.quadraticCurveTo(x, y, x + r, y);
ctx.closePath();
ctx.fill();
}
const lensW = size * 0.1;
const lensH = size * 0.06;
drawLens(cx - eyeSpacing - lensW/2, eyeY - lensH/2, lensW, lensH);
drawLens(cx + eyeSpacing - lensW/2, eyeY - lensH/2, lensW, lensH);
// Glasses bridge
ctx.strokeStyle = '#ffd700'; // Gold frames
ctx.lineWidth = size * 0.005;
ctx.beginPath();
ctx.moveTo(cx - eyeSpacing + lensW/2, eyeY - size*0.01);
ctx.quadraticCurveTo(cx, eyeY - size*0.02, cx + eyeSpacing - lensW/2, eyeY - size*0.01);
ctx.stroke();
// Glasses arms
ctx.beginPath();
ctx.moveTo(cx - eyeSpacing - lensW/2, eyeY - size*0.01);
ctx.lineTo(cx - size*0.17, eyeY - size*0.02);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(cx + eyeSpacing + lensW/2, eyeY - size*0.01);
ctx.lineTo(cx + size*0.17, eyeY - size*0.02);
ctx.stroke();
// Lens shine reflection
ctx.fillStyle = 'rgba(255, 255, 255, 0.15)';
ctx.beginPath();
ctx.moveTo(cx - eyeSpacing - lensW/2 + size*0.01, eyeY - lensH/2);
ctx.lineTo(cx - eyeSpacing + size*0.02, eyeY - lensH/2);
ctx.lineTo(cx - eyeSpacing - lensW/2, eyeY + size*0.02);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.moveTo(cx + eyeSpacing - lensW/2 + size*0.01, eyeY - lensH/2);
ctx.lineTo(cx + eyeSpacing + size*0.02, eyeY - lensH/2);
ctx.lineTo(cx + eyeSpacing - lensW/2, eyeY + size*0.02);
ctx.closePath();
ctx.fill();
return canvas;
}
Apply Changes