You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, faceCenterXPercent = "50", faceCenterYPercent = "50", faceWidthPercent = "40", meowText = "MEOW!") {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = originalImg.width;
canvas.height = originalImg.height;
// Draw the original image as the background
ctx.drawImage(originalImg, 0, 0);
// Calculate face location and dimensions based on percentages
const xPct = parseFloat(faceCenterXPercent) / 100;
const yPct = parseFloat(faceCenterYPercent) / 100;
const sizePct = parseFloat(faceWidthPercent) / 100;
const cx = canvas.width * xPct;
const cy = canvas.height * yPct;
const r = (canvas.width * sizePct) / 2;
const lw = Math.max(2, r * 0.02);
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
// 1. Draw Cat Ears
// Left Ear Outer
ctx.beginPath();
ctx.moveTo(cx - r * 0.8, cy - r * 0.2);
ctx.lineTo(cx - r * 0.9, cy - r * 1.2);
ctx.lineTo(cx - r * 0.2, cy - r * 0.8);
ctx.fillStyle = '#ffffff';
ctx.fill();
ctx.lineWidth = lw;
ctx.strokeStyle = '#000000';
ctx.stroke();
// Left Ear Inner
ctx.beginPath();
ctx.moveTo(cx - r * 0.7, cy - r * 0.4);
ctx.lineTo(cx - r * 0.8, cy - r * 1.0);
ctx.lineTo(cx - r * 0.4, cy - r * 0.75);
ctx.fillStyle = '#ff80df';
ctx.fill();
// Right Ear Outer
ctx.beginPath();
ctx.moveTo(cx + r * 0.8, cy - r * 0.2);
ctx.lineTo(cx + r * 0.9, cy - r * 1.2);
ctx.lineTo(cx + r * 0.2, cy - r * 0.8);
ctx.fillStyle = '#ffffff';
ctx.fill();
ctx.lineWidth = lw;
ctx.strokeStyle = '#000000';
ctx.stroke();
// Right Ear Inner
ctx.beginPath();
ctx.moveTo(cx + r * 0.7, cy - r * 0.4);
ctx.lineTo(cx + r * 0.8, cy - r * 1.0);
ctx.lineTo(cx + r * 0.4, cy - r * 0.75);
ctx.fillStyle = '#ff80df';
ctx.fill();
// 2. Draw Cat Whiskers
function drawWhisker(x1, y1, x2, y2) {
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.lineWidth = lw * 1.5;
ctx.strokeStyle = '#ffffff';
ctx.stroke();
ctx.lineWidth = lw * 0.5;
ctx.strokeStyle = '#000000';
ctx.stroke();
}
// Left whiskers
drawWhisker(cx - r * 0.4, cy, cx - r * 1.3, cy - r * 0.2);
drawWhisker(cx - r * 0.45, cy + r * 0.15, cx - r * 1.4, cy + r * 0.1);
drawWhisker(cx - r * 0.4, cy + r * 0.3, cx - r * 1.3, cy + r * 0.4);
// Right whiskers
drawWhisker(cx + r * 0.4, cy, cx + r * 1.3, cy - r * 0.2);
drawWhisker(cx + r * 0.45, cy + r * 0.15, cx + r * 1.4, cy + r * 0.1);
drawWhisker(cx + r * 0.4, cy + r * 0.3, cx + r * 1.3, cy + r * 0.4);
// 3. Draw Baby Pacifier
const px = cx;
const py = cy + r * 0.4;
// Pacifier ring
ctx.beginPath();
ctx.arc(px, py + r * 0.25, r * 0.2, 0, Math.PI * 2);
ctx.lineWidth = lw * 3;
ctx.strokeStyle = '#33ccff';
ctx.stroke();
ctx.lineWidth = lw;
ctx.strokeStyle = '#005c99';
ctx.stroke();
// Pacifier shield
ctx.beginPath();
ctx.ellipse(px, py, r * 0.45, r * 0.3, 0, 0, Math.PI * 2);
ctx.fillStyle = '#b3ecff';
ctx.fill();
ctx.lineWidth = lw;
ctx.strokeStyle = '#005c99';
ctx.stroke();
// Pacifier button
ctx.beginPath();
ctx.arc(px, py, r * 0.15, 0, Math.PI * 2);
ctx.fillStyle = '#ffcc99';
ctx.fill();
ctx.stroke();
// 4. Draw Speech Bubble
const bx = cx + r * 0.9;
const by = cy - r * 0.6;
const bw = r * 0.8;
const bh = r * 0.5;
// Speech bubble tail
ctx.beginPath();
ctx.moveTo(px + r * 0.3, py - r * 0.2);
ctx.lineTo(bx - bw * 0.5, by + bh * 0.5);
ctx.lineTo(bx + bw * 0.2, by + bh * 0.8);
ctx.fillStyle = '#ffffff';
ctx.fill();
ctx.lineWidth = lw;
ctx.strokeStyle = '#000000';
ctx.stroke();
// Speech bubble main ellipse
ctx.beginPath();
ctx.ellipse(bx, by, bw, bh, 0, 0, Math.PI * 2);
ctx.fillStyle = '#ffffff';
ctx.fill();
ctx.stroke();
// Clear overlap on the inside of the bubble
ctx.beginPath();
ctx.ellipse(bx, by, bw - lw, bh - lw, 0, 0, Math.PI * 2);
ctx.fillStyle = '#ffffff';
ctx.fill();
// 5. Draw Meow Text
ctx.fillStyle = '#000000';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
let fontSize = Math.max(12, r * 0.3);
ctx.font = `bold ${fontSize}px sans-serif`;
// Scale text if it overlaps
const textWidth = ctx.measureText(meowText).width;
if (textWidth > bw * 1.6) {
fontSize = fontSize * ((bw * 1.6) / textWidth);
ctx.font = `bold ${fontSize}px sans-serif`;
}
ctx.fillText(meowText, bx, by);
return canvas;
}
Apply Changes