You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, helmetColor = '#E63946', suitColor = '#F1FAEE', visorColor = '#A8DADC', skinTone = '#E0AC69', hairColor = '#6A381F', size = 500) {
const canvas = document.createElement('canvas');
canvas.width = size;
canvas.height = size;
const ctx = canvas.getContext('2d');
const centerX = size / 2;
const defaultStroke = '#1D3557';
const defaultLineWidth = Math.max(1, size * 0.01);
// 1. Background
function drawCheckeredBackground(ctx, size, gridSize = size / 20) {
const color1 = '#FFFFFF';
const color2 = '#d9d9d9';
const numBoxes = Math.ceil(size / gridSize);
for (let i = 0; i < numBoxes; i++) {
for (let j = 0; j < numBoxes; j++) {
ctx.fillStyle = (i + j) % 2 === 0 ? color1 : color2;
ctx.fillRect(i * gridSize, j * gridSize, gridSize, gridSize);
}
}
}
drawCheckeredBackground(ctx, size);
// Define main coordinates & dimensions
const headRadius = size * 0.22;
const helmetRadius = headRadius * 1.2;
const suitTopY = size * 0.65;
const neckHeight = size * 0.05;
const neckTopY = suitTopY - neckHeight;
const headCenterY = neckTopY - headRadius * 0.8;
const neckWidth = size * 0.1;
// 2. Hair (drawn first to be in the back)
ctx.fillStyle = hairColor;
ctx.strokeStyle = defaultStroke;
ctx.lineWidth = defaultLineWidth;
ctx.beginPath();
ctx.moveTo(centerX - headRadius * 0.5, headCenterY + headRadius * 0.5);
ctx.bezierCurveTo(
centerX - size * 0.4, headCenterY + headRadius * 2, // control 1
centerX - size * 0.1, size * 1.1, // control 2
centerX + size * 0.05, size * 1.1 // end point
);
ctx.lineTo(centerX + size * 0.15, size * 1.1); // Widen the base at the bottom
ctx.bezierCurveTo(
centerX + size * 0.1, size * 1.1, // control 2
centerX + size * 0.4, headCenterY + headRadius * 2, // control 1
centerX + headRadius * 0.5, headCenterY + headRadius * 0.5 // start point match
);
ctx.closePath();
ctx.fill();
ctx.stroke();
// 3. Body/Suit
ctx.fillStyle = suitColor;
ctx.beginPath();
ctx.moveTo(centerX - neckWidth * 3.5, size);
ctx.lineTo(centerX - neckWidth * 2.5, suitTopY + neckHeight * 1.5);
ctx.quadraticCurveTo(centerX, suitTopY, centerX + neckWidth * 2.5, suitTopY + neckHeight * 1.5);
ctx.lineTo(centerX + neckWidth * 3.5, size);
ctx.closePath();
ctx.fill();
ctx.stroke();
// Collar
ctx.fillStyle = suitColor;
ctx.beginPath();
ctx.moveTo(centerX - neckWidth * 0.8, suitTopY);
ctx.quadraticCurveTo(centerX, suitTopY + neckHeight * 0.6, centerX + neckWidth * 0.8, suitTopY);
ctx.quadraticCurveTo(centerX, suitTopY - neckHeight * 0.4, centerX - neckWidth * 0.8, suitTopY);
ctx.closePath();
ctx.fill();
ctx.stroke();
// 4. Neck
ctx.fillStyle = skinTone;
ctx.beginPath();
ctx.rect(centerX - neckWidth / 2, neckTopY, neckWidth, neckHeight);
ctx.fill();
ctx.stroke();
// 5. Helmet
ctx.fillStyle = helmetColor;
ctx.beginPath();
ctx.arc(centerX, headCenterY, helmetRadius, Math.PI * 1.05, Math.PI * -0.05);
ctx.bezierCurveTo(
centerX + helmetRadius, headCenterY + helmetRadius * 1, // cp1
centerX, headCenterY + helmetRadius * 1.4, // cp2
centerX - helmetRadius, headCenterY + helmetRadius * 1 // end
);
ctx.closePath();
ctx.fill();
ctx.stroke();
// Helmet Highlight
ctx.fillStyle = 'rgba(255, 255, 255, 0.5)';
ctx.beginPath();
ctx.arc(centerX - helmetRadius * 0.4, headCenterY - helmetRadius * 0.4, helmetRadius * 0.6, Math.PI * 1.3, Math.PI * 1.8);
ctx.fill();
// 6. Face Opening
const openingOffsetY = headRadius * 0.1;
const openingRadiusX = headRadius * 0.9;
const openingRadiusY = headRadius * 0.75;
ctx.fillStyle = skinTone;
ctx.beginPath();
ctx.ellipse(centerX, headCenterY + openingOffsetY, openingRadiusX, openingRadiusY, 0, 0, Math.PI * 2);
ctx.fill();
ctx.stroke();
// 7. Facial Features
ctx.save();
ctx.translate(centerX, headCenterY + openingOffsetY);
const eyeOffsetX = openingRadiusX * 0.4;
const eyeOffsetY = -openingRadiusY * 0.1;
const eyeRadiusX = openingRadiusX * 0.15;
const eyeRadiusY = openingRadiusY * 0.2;
function drawEye(offsetX) {
// Sclera
ctx.fillStyle = 'white';
ctx.beginPath();
ctx.ellipse(offsetX, eyeOffsetY, eyeRadiusX, eyeRadiusY, 0, 0, Math.PI * 2);
ctx.fill();
ctx.strokeStyle = defaultStroke;
ctx.lineWidth = defaultLineWidth;
ctx.stroke();
// Eyelash
ctx.beginPath();
ctx.arc(offsetX, eyeOffsetY, eyeRadiusX * 1.05, Math.PI, Math.PI * 2);
ctx.arc(offsetX, eyeOffsetY, eyeRadiusX * 0.95, Math.PI * 2, Math.PI, true);
ctx.closePath();
ctx.fillStyle = defaultStroke;
ctx.fill();
// Pupil
ctx.fillStyle = '#000';
ctx.beginPath();
ctx.arc(offsetX, eyeOffsetY + eyeRadiusY * 0.1, eyeRadiusX * 0.6, 0, Math.PI * 2);
ctx.fill();
}
drawEye(-eyeOffsetX);
drawEye(eyeOffsetX);
// Mouth
ctx.beginPath();
ctx.arc(0, openingRadiusY * 0.35, openingRadiusX * 0.25, Math.PI * 0.1, Math.PI * 0.9);
ctx.lineWidth = defaultLineWidth;
ctx.strokeStyle = defaultStroke;
ctx.stroke();
ctx.restore();
// 8. Visor (decorative stripe)
ctx.strokeStyle = visorColor;
ctx.lineWidth = defaultLineWidth * 4;
ctx.beginPath();
ctx.arc(centerX, headCenterY, helmetRadius * 0.9, -Math.PI * 0.35, -Math.PI * 0.65, true);
ctx.stroke();
return canvas;
}
Apply Changes