You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, titleText = "РЫЦАРЬ ОРДЕНА ЗАКОЛКИ", subtitleText = "За доблесть и безупречный стиль") {
// Determine dimensions and prevent memory blowups for gigantic images
const maxDimension = 1200;
let scale = 1;
if (originalImg.width > maxDimension || originalImg.height > maxDimension) {
scale = Math.min(maxDimension / originalImg.width, maxDimension / originalImg.height);
}
// Safety fallback
const w = Math.max(100, originalImg.width * scale);
const h = Math.max(100, originalImg.height * scale);
// Calculate layout sizing based on image width
const gap = Math.max(4, w * 0.015);
const borderW = Math.max(2, w * 0.005);
const r = Math.max(30, w * 0.08); // seal radius
let titleSize = Math.max(28, w * 0.08);
let subtitleSize = Math.max(16, titleSize * 0.4);
const padX = Math.max(60, w * 0.12);
const padTop = Math.max(60, w * 0.12);
// Allocate space under the image for the gap, the seal ribbon, texts, and margins
const requiredBottomPadding = gap + r * 1.8 + 20 + titleSize + 15 + subtitleSize + 50;
const padBottom = Math.max(requiredBottomPadding, w * 0.35);
// Set up standard canvas
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
canvas.width = w + padX * 2;
canvas.height = h + padTop + padBottom;
// 1. Demotivator Background
ctx.fillStyle = "#000000";
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 2. Draw Original Image
ctx.drawImage(originalImg, padX, padTop, w, h);
// 3. Draw Demotivator White Frame Border
ctx.strokeStyle = "#ffffff";
ctx.lineWidth = borderW;
ctx.strokeRect(padX - gap, padTop - gap, w + gap * 2, h + gap * 2);
// 4. Draw Seal of the "Order of the Brooch"
const cx = padX + w / 2;
const cy = padTop + h + gap;
ctx.save();
// Shadow gives a classic 3D wax-seal effect to the layers
ctx.shadowColor = "rgba(0, 0, 0, 0.8)";
ctx.shadowBlur = Math.max(5, w * 0.01);
ctx.shadowOffsetY = Math.max(2, w * 0.005);
// Red Ribbons
ctx.fillStyle = "#8B0000";
// Left ribbon tail
ctx.beginPath();
ctx.moveTo(cx, cy);
ctx.lineTo(cx - r * 0.6, cy + r * 1.7);
ctx.lineTo(cx - r * 0.3, cy + r * 1.4);
ctx.lineTo(cx - r * 0.1, cy + r * 1.7);
ctx.fill();
// Right ribbon tail
ctx.beginPath();
ctx.moveTo(cx, cy);
ctx.lineTo(cx + r * 0.6, cy + r * 1.7);
ctx.lineTo(cx + r * 0.3, cy + r * 1.4);
ctx.lineTo(cx + r * 0.1, cy + r * 1.7);
ctx.fill();
// Golden Sunburst Base
ctx.fillStyle = "#DAA520";
ctx.beginPath();
for (let i = 0; i < 32; i++) {
let ang = i * Math.PI / 16;
let radius = (i % 2 === 0) ? r : r * 0.85;
if (i === 0) ctx.moveTo(cx + radius, cy);
else ctx.lineTo(cx + Math.cos(ang) * radius, cy + Math.sin(ang) * radius);
}
ctx.closePath();
ctx.fill();
// Inner Ruby Red Wax Center
ctx.fillStyle = "#B22222";
ctx.beginPath();
ctx.arc(cx, cy, r * 0.7, 0, Math.PI * 2);
ctx.fill();
// The Brooch / Hairpin (Bobby Pin) Visual Crest Overlay
ctx.strokeStyle = "#FFD700"; // Golden crest
ctx.lineWidth = r * 0.05;
ctx.lineCap = "round";
ctx.lineJoin = "round";
ctx.beginPath();
// Bobby Pin Top Straight Leg
ctx.moveTo(cx - r * 0.25, cy - r * 0.15);
ctx.lineTo(cx + r * 0.15, cy - r * 0.15);
// Loop
ctx.arc(cx + r * 0.15, cy - r * 0.03, r * 0.12, -Math.PI / 2, Math.PI / 2);
// Zigzag Bottom Wavy Leg
ctx.lineTo(cx + r * 0.05, cy + r * 0.09);
ctx.lineTo(cx - r * 0.025, cy + r * 0.18);
ctx.lineTo(cx - r * 0.1, cy + r * 0.09);
ctx.lineTo(cx - r * 0.175, cy + r * 0.18);
ctx.lineTo(cx - r * 0.25, cy + r * 0.09);
ctx.lineTo(cx - r * 0.28, cy + r * 0.12); // Slightly open tip
ctx.stroke();
ctx.restore(); // Drop shadow off for text rendering
// 5. Calculate and Shrink Texts (If too long for image width)
let maxTextW = canvas.width - padX * 0.5;
ctx.font = `${titleSize}px "Times New Roman", Times, serif`;
while (ctx.measureText(titleText).width > maxTextW && titleSize > 14) {
titleSize--;
ctx.font = `${titleSize}px "Times New Roman", Times, serif`;
}
ctx.font = `${subtitleSize}px Arial, sans-serif`;
while (ctx.measureText(subtitleText).width > maxTextW && subtitleSize > 10) {
subtitleSize--;
ctx.font = `${subtitleSize}px Arial, sans-serif`;
}
// 6. Draw Captions
const sealBottom = cy + r * 1.7;
const titleY = sealBottom + Math.max(15, w * 0.02);
ctx.fillStyle = "#ffffff";
ctx.textAlign = "center";
ctx.textBaseline = "top";
// Draw Title
ctx.font = `${titleSize}px "Times New Roman", Times, serif`;
ctx.fillText(titleText, canvas.width / 2, titleY);
// Draw Subtitle
const subtitleY = titleY + titleSize + Math.max(10, w * 0.015);
ctx.font = `${subtitleSize}px Arial, sans-serif`;
ctx.fillText(subtitleText, canvas.width / 2, subtitleY);
return canvas;
}
Apply Changes