You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, title = "КНИГА РЕКОРДОВ", recordName = "ВЫДАЮЩЕЕСЯ ДОСТИЖЕНИЕ", recordText = "Это изображение официально признано уникальным и внесено в глобальный реестр мировых рекордов. Достижение подтверждено независимой комиссией экспертов.", theme = "dark") {
// 1. Create and size the canvas
const canvas = document.createElement('canvas');
canvas.width = 800;
canvas.height = 1000;
const ctx = canvas.getContext('2d');
const isDark = theme.toLowerCase() !== 'light';
// 2. Background Generation
const bgGrad = ctx.createLinearGradient(0, 0, 0, canvas.height); // vertical gradient
bgGrad.addColorStop(0, isDark ? '#081021' : '#FDFBF7'); // Dark slate blue OR cream
bgGrad.addColorStop(1, isDark ? '#1a2a4b' : '#E8DCC4');
ctx.fillStyle = bgGrad;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 3. Gold Gradient for borders and accents
const goldGrad = ctx.createLinearGradient(0, 0, canvas.width, canvas.height);
goldGrad.addColorStop(0, '#BF953F');
goldGrad.addColorStop(0.25, '#FCF6BA');
goldGrad.addColorStop(0.5, '#B38728');
goldGrad.addColorStop(0.75, '#FBF5B7');
goldGrad.addColorStop(1, '#AA771C');
// 4. Draw Borders
ctx.lineWidth = 10;
ctx.strokeStyle = goldGrad;
ctx.strokeRect(40, 40, canvas.width - 80, canvas.height - 80); // Outer thicker border
ctx.lineWidth = 2;
ctx.strokeRect(52, 52, canvas.width - 104, canvas.height - 104); // Inner thinner border
// Decorative corner blocks
const cornerSize = 24;
ctx.fillStyle = goldGrad;
ctx.fillRect(40, 40, cornerSize, cornerSize);
ctx.fillRect(canvas.width - 40 - cornerSize, 40, cornerSize, cornerSize);
ctx.fillRect(40, canvas.height - 40 - cornerSize, cornerSize, cornerSize);
ctx.fillRect(canvas.width - 40 - cornerSize, canvas.height - 40 - cornerSize, cornerSize, cornerSize);
// Color definitions for text
const primaryColor = isDark ? '#FFFFFF' : '#1A1A1A';
const secondaryColor = isDark ? '#D3D3D3' : '#4A4A4A';
// 5. Draw Title
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.font = 'bold 44px "Times New Roman", Times, serif';
ctx.fillStyle = goldGrad;
ctx.fillText(title.toUpperCase(), canvas.width / 2, 110);
// 6. Provide backing frame for the image
const frameX = 95, frameY = 175, frameW = 610, frameH = 430;
ctx.fillStyle = isDark ? '#FFFFFF' : '#1A1A1A';
ctx.fillRect(frameX, frameY, frameW, frameH);
// 7. Calculate cropped representation of the original image
const imgX = 100, imgY = 180, imgW = 600, imgH = 420;
const imgRatio = originalImg.width / originalImg.height;
const boxRatio = imgW / imgH;
let cropWidth, cropHeight;
if (imgRatio > boxRatio) {
// Image is wider than box -> crop sides
cropHeight = originalImg.height;
cropWidth = originalImg.height * boxRatio;
} else {
// Image is taller than box -> crop top/bottom
cropWidth = originalImg.width;
cropHeight = originalImg.width / boxRatio;
}
const cropX = (originalImg.width - cropWidth) / 2;
const cropY = (originalImg.height - cropHeight) / 2;
ctx.drawImage(originalImg, cropX, cropY, cropWidth, cropHeight, imgX, imgY, imgW, imgH);
// 8. Draw Headers & Specific Record Name
ctx.font = 'bold 16px Arial, sans-serif';
ctx.fillStyle = secondaryColor;
ctx.fillText('ОФИЦИАЛЬНО ЗАРЕГИСТРИРОВАНО', canvas.width / 2, 640);
ctx.font = 'italic bold 34px "Times New Roman", Times, serif';
ctx.fillStyle = primaryColor;
ctx.fillText(recordName, canvas.width / 2, 680);
// Decorator Line under the Record Name
ctx.beginPath();
ctx.moveTo(320, 705);
ctx.lineTo(480, 705);
ctx.strokeStyle = goldGrad;
ctx.lineWidth = 2;
ctx.stroke();
// 9. Draw Wrapping Text for the Record Description
ctx.font = '22px Arial, sans-serif';
ctx.fillStyle = primaryColor;
function wrapText(context, text, x, y, maxWidth, lineHeight, maxLines) {
const words = text.split(' ');
let line = '';
let currentY = y;
let linesDrawn = 0;
for (let n = 0; n < words.length; n++) {
const testLine = line + words[n] + ' ';
const metrics = context.measureText(testLine);
const testWidth = metrics.width;
if (testWidth > maxWidth && n > 0) {
if (linesDrawn >= maxLines - 1) {
context.fillText(line + '...', x, currentY);
return;
}
context.fillText(line.trim(), x, currentY);
line = words[n] + ' ';
currentY += lineHeight;
linesDrawn++;
} else {
line = testLine;
}
}
context.fillText(line.trim(), x, currentY);
}
wrapText(ctx, recordText, canvas.width / 2, 750, 600, 32, 4);
// 10. Draw Ribbon & Official Seal
const sealSize = 45;
const sealX = canvas.width / 2;
const sealY = 890;
// Draw dark red ribbons falling down behind the badge
ctx.fillStyle = '#b30000';
// Left ribbon
ctx.beginPath();
ctx.moveTo(sealX - 15, sealY);
ctx.lineTo(sealX - 45, sealY + 70);
ctx.lineTo(sealX - 25, sealY + 60);
ctx.lineTo(sealX - 5, sealY + 75);
ctx.lineTo(sealX, sealY);
ctx.fill();
// Right ribbon
ctx.beginPath();
ctx.moveTo(sealX, sealY);
ctx.lineTo(sealX + 5, sealY + 75);
ctx.lineTo(sealX + 25, sealY + 60);
ctx.lineTo(sealX + 45, sealY + 70);
ctx.lineTo(sealX + 15, sealY);
ctx.fill();
// Outer Gold Badge Base
ctx.beginPath();
ctx.arc(sealX, sealY, sealSize, 0, Math.PI * 2);
ctx.fillStyle = goldGrad;
ctx.fill();
// Fine inner engravings (circles) on the seal
ctx.lineWidth = 1;
ctx.strokeStyle = '#5a3d00'; // Dark gold/brown outline inside
ctx.beginPath();
ctx.arc(sealX, sealY, sealSize - 4, 0, Math.PI * 2);
ctx.stroke();
ctx.lineWidth = 2;
ctx.beginPath();
ctx.arc(sealX, sealY, sealSize - 9, 0, Math.PI * 2);
ctx.stroke();
// Draw central star decoration on the seal
function drawStar(cx, cy, spikes, outerRadius, innerRadius) {
let rot = Math.PI / 2 * 3;
let x = cx;
let y = cy;
let step = Math.PI / spikes;
ctx.beginPath();
ctx.moveTo(cx, cy - outerRadius);
for (let i = 0; i < spikes; i++) {
x = cx + Math.cos(rot) * outerRadius;
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 = '#5a3d00';
drawStar(sealX, sealY, 5, 20, 8);
return canvas;
}
Apply Changes