You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, companyName = "YOUR STUDIO", motto = "ARS GRATIA ARTIS") {
const canvas = document.createElement('canvas');
canvas.width = 800;
canvas.height = 640;
const ctx = canvas.getContext('2d');
// 1. Background Settings
let bgGrad = ctx.createRadialGradient(400, 320, 100, 400, 320, 600);
bgGrad.addColorStop(0, '#112222'); // dark teal
bgGrad.addColorStop(1, '#000000'); // black
ctx.fillStyle = bgGrad;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 2. Background Searchlight Rays
function drawRays(cx, cy, startAngle, endAngle, numRays) {
ctx.save();
ctx.translate(cx, cy);
ctx.fillStyle = 'rgba(255, 255, 255, 0.04)';
let angleSpan = endAngle - startAngle;
for (let i = 0; i <= numRays; i++) {
let angle = startAngle + (i * angleSpan / numRays);
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(Math.cos(angle - 0.05) * 1200, Math.sin(angle - 0.05) * 1200);
ctx.lineTo(Math.cos(angle + 0.05) * 1200, Math.sin(angle + 0.05) * 1200);
ctx.fill();
}
ctx.restore();
}
// Searchlights from bottom left and bottom right
drawRays(100, 640, -Math.PI / 2 - 0.6, -0.2, 8);
drawRays(700, 640, -Math.PI + 0.2, -Math.PI / 2 + 0.6, 8);
// 3. Central Setup
let centerX = 400, centerY = 260;
let inR = 140, textInner = 160, textOuter = 210, outR = 230;
// Draw the uploaded image bounded inside the film strip
ctx.save();
ctx.beginPath();
ctx.arc(centerX, centerY, inR, 0, Math.PI * 2);
ctx.clip();
let scale = Math.max((inR * 2) / originalImg.width, (inR * 2) / originalImg.height);
let dw = originalImg.width * scale;
let dh = originalImg.height * scale;
ctx.drawImage(originalImg, centerX - dw / 2, centerY - dh / 2, dw, dh);
ctx.restore();
// 4. Gold Film Ring Geometry
let goldGradient = ctx.createLinearGradient(170, 30, 630, 490);
goldGradient.addColorStop(0, '#eac678');
goldGradient.addColorStop(0.3, '#c59348');
goldGradient.addColorStop(0.5, '#f9e499');
goldGradient.addColorStop(0.7, '#d8a04d');
goldGradient.addColorStop(1, '#875d19');
ctx.beginPath();
ctx.arc(centerX, centerY, outR, 0, Math.PI * 2);
ctx.arc(centerX, centerY, inR, 0, Math.PI * 2, true);
ctx.shadowColor = 'rgba(0, 0, 0, 0.7)';
ctx.shadowBlur = 15;
ctx.fillStyle = goldGradient;
ctx.fill();
ctx.shadowBlur = 0; // reset shadow
// Ring Boundary Lines
ctx.strokeStyle = '#5a3d11';
ctx.lineWidth = 2;
[inR, textInner, textOuter, outR].forEach(r => {
ctx.beginPath();
ctx.arc(centerX, centerY, r, 0, Math.PI * 2);
ctx.stroke();
});
// Outer & Inner Film Holes
ctx.fillStyle = '#111';
for (let rpos of [150, 220]) {
for (let i = 0; i < 72; i++) {
let angle = i * Math.PI * 2 / 72;
let x = centerX + Math.cos(angle) * rpos;
let y = centerY + Math.sin(angle) * rpos;
ctx.save();
ctx.translate(x, y);
ctx.rotate(angle);
ctx.fillRect(-3, -5, 6, 10);
ctx.restore();
}
}
// 5. Motto Arched Text Inside the Band
ctx.fillStyle = '#3a2404';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
let measureRadius = 185;
let topText = motto.toUpperCase();
let tempFont = 26;
// Scale font dynamically to fit top half curve
while(true) {
ctx.font = `bold ${tempFont}px Georgia, serif`;
let w = ctx.measureText(topText).width + (topText.length * 0.03 * measureRadius);
if(w < measureRadius * Math.PI * 0.8 || tempFont <= 12) break;
tempFont--;
}
// Draw rotated text along curve
let totalAngle = 0;
let angles = [];
for (let i = 0; i < topText.length; i++) {
let w = ctx.measureText(topText[i]).width;
let a = (w / measureRadius) + 0.03;
angles.push(a);
totalAngle += a;
}
ctx.save();
ctx.translate(centerX, centerY);
ctx.rotate(-Math.PI / 2 - totalAngle / 2);
for (let i = 0; i < topText.length; i++) {
ctx.rotate(angles[i] / 2);
ctx.save();
ctx.translate(0, -measureRadius);
ctx.fillText(topText[i], 0, 0);
ctx.restore();
ctx.rotate(angles[i] / 2);
}
ctx.restore();
// 6. Stars Along Bottom Arc
function drawStar(ctx, cx, cy, spikes, outerRadius, innerRadius) {
let rot = Math.PI / 2 * 3;
let step = Math.PI / spikes;
ctx.beginPath();
ctx.moveTo(cx, cy - outerRadius);
for (let i = 0; i < spikes; i++) {
let x = cx + Math.cos(rot) * outerRadius;
let y = cy + Math.sin(rot) * outerRadius;
ctx.lineTo(x, y);
rot += step;
x = cx + Math.cos(rot) * innerRadius;
y = cy + Math.sin(rot) * innerRadius;
ctx.lineTo(x, y);
rot += step;
}
ctx.lineTo(cx, cy - outerRadius);
ctx.closePath();
ctx.fill();
}
ctx.fillStyle = '#3a2404';
for (let a of [0, 0.4, -0.4, 0.8, -0.8]) {
let starX = centerX + Math.cos(Math.PI / 2 + a) * measureRadius;
let starY = centerY + Math.sin(Math.PI / 2 + a) * measureRadius;
drawStar(ctx, starX, starY, 5, 8, 3);
}
// 7. Trade Mark Sidebar Text
ctx.fillStyle = '#eac678';
ctx.font = 'bold 15px Georgia, serif';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.shadowColor = 'black';
ctx.shadowBlur = 4;
ctx.fillText('T R A D E', centerX - outR - 50, centerY);
ctx.fillText('M A R K', centerX + outR + 50, centerY);
ctx.shadowBlur = 0;
// 8. Ribbon & Company Name at the Bottom
function drawCompanyRibbon(text, cx, cy) {
ctx.save();
ctx.translate(cx, cy);
let rGrad = ctx.createLinearGradient(-340, -50, 340, 50);
rGrad.addColorStop(0, '#c59348');
rGrad.addColorStop(0.15, '#eac678');
rGrad.addColorStop(0.5, '#f9e499');
rGrad.addColorStop(0.85, '#eac678');
rGrad.addColorStop(1, '#875d19');
ctx.fillStyle = rGrad;
ctx.strokeStyle = '#3a2404';
ctx.lineWidth = 3;
ctx.lineJoin = 'round';
// Ribbon Tails
ctx.beginPath();
ctx.moveTo(-200, 10); ctx.lineTo(-320, 10); ctx.lineTo(-290, 35); ctx.lineTo(-320, 60); ctx.lineTo(-200, 60); ctx.closePath();
ctx.fill(); ctx.stroke();
ctx.beginPath();
ctx.moveTo(200, 10); ctx.lineTo(320, 10); ctx.lineTo(290, 35); ctx.lineTo(320, 60); ctx.lineTo(200, 60); ctx.closePath();
ctx.fill(); ctx.stroke();
// Ribbon Hidden Folds
ctx.fillStyle = '#7a4e0c';
ctx.beginPath(); ctx.moveTo(-240, 40); ctx.lineTo(-200, 60); ctx.lineTo(-200, 40); ctx.closePath(); ctx.fill(); ctx.stroke();
ctx.beginPath(); ctx.moveTo(240, 40); ctx.lineTo(200, 60); ctx.lineTo(200, 40); ctx.closePath(); ctx.fill(); ctx.stroke();
// Main Central Banner
ctx.fillStyle = rGrad;
ctx.shadowColor = 'rgba(0,0,0,0.6)';
ctx.shadowBlur = 10;
ctx.shadowOffsetY = 5;
ctx.beginPath(); ctx.rect(-240, -30, 480, 70); ctx.fill();
ctx.shadowColor = 'transparent'; // Remove shadow for strokes below
ctx.stroke();
// Shiny Box Highlight within Banner
ctx.strokeStyle = 'rgba(255,255,255,0.4)';
ctx.lineWidth = 1.5;
ctx.beginPath(); ctx.rect(-236, -26, 472, 62); ctx.stroke();
// Banner Text Styling
ctx.fillStyle = '#1a0f01';
let fontSize = 34;
ctx.font = `bold ${fontSize}px Georgia, serif`;
while(ctx.measureText(text).width > 420 && fontSize > 14) {
fontSize--;
ctx.font = `bold ${fontSize}px Georgia, serif`;
}
ctx.shadowColor = 'rgba(255, 255, 255, 0.4)';
ctx.shadowBlur = 2;
ctx.shadowOffsetY = 1;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(text.toUpperCase(), 0, 5); // Shifted Y visually
ctx.restore();
}
// Deploying Ribbon
drawCompanyRibbon(companyName, 400, 540);
return canvas;
}
Apply Changes