You can edit the below JavaScript code to customize the image tool.
Apply Changes
async function processImage(originalImg, callerName = "Unknown Caller", callType = "Skype incoming call") {
// Canvas dimensions representing a typical portrait smartphone screen
const width = 1080;
const height = 1920;
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
// 1. Draw Heavily Blurred Background to match VoIP app style
const scale = Math.max(width / originalImg.width, height / originalImg.height);
const drawW = originalImg.width * scale;
const drawH = originalImg.height * scale;
const drawX = (width - drawW) / 2;
const drawY = (height - drawH) / 2;
ctx.filter = 'blur(45px)';
// Scale up original slightly more than necessary to avoid unblurred edges creeping in
ctx.drawImage(originalImg, drawX - 50, drawY - 50, drawW + 100, drawH + 100);
ctx.filter = 'none';
// 2. Dark Overlay for readability
const gradient = ctx.createLinearGradient(0, 0, 0, height);
gradient.addColorStop(0, 'rgba(0, 0, 0, 0.4)');
gradient.addColorStop(1, 'rgba(0, 0, 0, 0.75)');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, width, height);
// 3. Draw Skype Mini Logo at Top
const logoY = 160;
ctx.beginPath();
ctx.arc(width / 2, logoY, 45, 0, Math.PI * 2);
ctx.fillStyle = '#00AFF0'; // Skype Blue
ctx.fill();
ctx.fillStyle = '#ffffff';
ctx.font = 'bold 50px "Segoe UI", "Helvetica Neue", Arial, sans-serif';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText("S", width / 2, logoY + 4);
// 4. Draw Avatar with Pulsating Rings
const avatarSize = 380;
const avatarX = width / 2;
const avatarY = 620;
// Rings
ctx.beginPath();
ctx.arc(avatarX, avatarY, avatarSize / 2 + 140, 0, Math.PI * 2);
ctx.fillStyle = 'rgba(255, 255, 255, 0.04)';
ctx.fill();
ctx.beginPath();
ctx.arc(avatarX, avatarY, avatarSize / 2 + 60, 0, Math.PI * 2);
ctx.fillStyle = 'rgba(255, 255, 255, 0.08)';
ctx.fill();
// Clipped Avatar Drawing
ctx.save();
ctx.beginPath();
ctx.arc(avatarX, avatarY, avatarSize / 2, 0, Math.PI * 2);
ctx.closePath();
ctx.clip();
const avScale = Math.max(avatarSize / originalImg.width, avatarSize / originalImg.height);
const avW = originalImg.width * avScale;
const avH = originalImg.height * avScale;
const avX = avatarX - avW / 2;
const avY = avatarY - avH / 2;
ctx.drawImage(originalImg, avX, avY, avW, avH);
ctx.restore();
// 5. Draw Caller Info Text
ctx.fillStyle = '#ffffff';
ctx.font = 'bold 75px "Segoe UI", "Helvetica Neue", Arial, sans-serif';
ctx.fillText(callerName, width / 2, 980, 940);
ctx.fillStyle = '#d1d1d1';
ctx.font = '45px "Segoe UI", "Helvetica Neue", Arial, sans-serif';
ctx.fillText(callType, width / 2, 1070, 940);
// 6. Draw Call Buttons (Decline / Accept)
const btnY = 1600;
const declineX = 300;
const acceptX = width - 300;
const btnRadius = 85;
// Decline Button
ctx.beginPath();
ctx.arc(declineX, btnY, btnRadius, 0, Math.PI * 2);
ctx.fillStyle = '#E53935'; // Red
ctx.fill();
// Accept Button
ctx.beginPath();
ctx.arc(acceptX, btnY, btnRadius, 0, Math.PI * 2);
ctx.fillStyle = '#43B581'; // Green
ctx.fill();
// Button Labels
ctx.fillStyle = '#ffffff';
ctx.font = '35px "Segoe UI", "Helvetica Neue", Arial, sans-serif';
ctx.fillText("Decline", declineX, btnY + 145);
ctx.fillText("Accept", acceptX, btnY + 145);
// 7. Load and Draw Vector Phone Icons from Material Symbols
const callEndSvg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="white" d="M12 9c-1.6 0-3.15.25-4.6.72v3.1c0 .39-.23.74-.56.9-.98.49-1.87 1.12-2.66 1.85-.18.18-.43.28-.7.28-.28 0-.53-.11-.71-.29L.29 13.08c-.18-.17-.29-.42-.29-.7 0-.28.11-.53.29-.71C3.34 8.78 7.46 7 12 7s8.66 1.78 11.71 4.67c.18.18.29.43.29.71 0 .28-.11.52-.29.71l-2.48 2.48c-.18.18-.43.29-.71.29-.27 0-.52-.11-.7-.28-.79-.74-1.69-1.36-2.67-1.85-.33-.16-.56-.5-.56-.9v-3.1C15.15 9.25 13.6 9 12 9z"/></svg>`;
const callSvg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="white" d="M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z"/></svg>`;
const loadSvg = (svgString) => {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = reject;
img.src = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(svgString);
});
};
try {
const imgCallEnd = await loadSvg(callEndSvg);
const imgCall = await loadSvg(callSvg);
const iconSize = 80;
ctx.drawImage(imgCallEnd, declineX - iconSize / 2, btnY - iconSize / 2, iconSize, iconSize);
ctx.drawImage(imgCall, acceptX - iconSize / 2, btnY - iconSize / 2, iconSize, iconSize);
} catch (e) {
console.error("Failed to load SVG icons into canvas", e);
}
return canvas;
}
Apply Changes