You can edit the below JavaScript code to customize the image tool.
Apply Changes
async function processImage(originalImg, text = "Царевна-лягушка", themeIntensity = 0.6) {
return new Promise((resolve) => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const w = originalImg.width;
const h = originalImg.height;
canvas.width = w;
canvas.height = h;
const scale = Math.min(w, h);
// Draw the original image first
ctx.drawImage(originalImg, 0, 0, w, h);
// 1. Swamp Vignette Overlay (Enchanted Forest feel)
const intensity = Math.max(0, Math.min(1, parseFloat(themeIntensity) || 0.6));
const gradient = ctx.createRadialGradient(w / 2, h / 2, scale * 0.2, w / 2, h / 2, scale * 0.8);
gradient.addColorStop(0, 'rgba(40, 80, 40, 0)'); // Clear inside
gradient.addColorStop(1, `rgba(15, 55, 25, ${intensity})`); // Dark swampy green edges
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, w, h);
// Helper function: Draw Lily Pads
function drawLilyPad(x, y, radius, angle) {
ctx.save();
ctx.translate(x, y);
ctx.rotate(angle);
// Pad shadow
ctx.shadowColor = 'rgba(0,0,0,0.5)';
ctx.shadowBlur = scale * 0.02;
ctx.shadowOffsetX = scale * 0.005;
ctx.shadowOffsetY = scale * 0.005;
ctx.beginPath();
// A circle with a wedge removed (pac-man style)
ctx.arc(0, 0, radius, 0.2, Math.PI * 2 - 0.2);
ctx.lineTo(0, 0);
ctx.closePath();
ctx.fillStyle = '#2E8B57'; // SeaGreen
ctx.fill();
// Turn off shadow for strokes
ctx.shadowColor = 'transparent';
ctx.lineWidth = radius * 0.03;
ctx.strokeStyle = '#006400'; // DarkGreen
ctx.stroke();
// Ribs
ctx.beginPath();
for (let i = 1; i <= 5; i++) {
const ribAngle = (i * (Math.PI * 2 - 0.4)) / 6 + 0.2;
ctx.moveTo(0, 0);
ctx.lineTo(Math.cos(ribAngle) * radius * 0.8, Math.sin(ribAngle) * radius * 0.8);
}
ctx.strokeStyle = '#3CB371';
ctx.stroke();
ctx.restore();
}
// Draw lily pads in the bottom corners
drawLilyPad(w * 0.15, h * 0.85, scale * 0.15, 0.5);
drawLilyPad(w * 0.85, h * 0.9, scale * 0.2, -0.8);
// Helper function: Ivan Tsarevich's Arrow sticking into the pad
function drawArrow(x, y, size) {
ctx.save();
ctx.translate(x, y);
// Angle of arrow stuck in the ground
ctx.rotate(-Math.PI / 3.5);
ctx.shadowColor = 'rgba(0,0,0,0.4)';
ctx.shadowBlur = size * 0.05;
ctx.shadowOffsetX = size * 0.02;
ctx.shadowOffsetY = size * 0.02;
// Shaft
const shaftLength = size * 1.5;
const shaftWidth = size * 0.06;
ctx.fillStyle = '#8B4513'; // SaddleBrown
ctx.fillRect(-shaftLength, -shaftWidth/2, shaftLength, shaftWidth);
// Arrow head
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(-size * 0.3, -size * 0.15);
ctx.lineTo(-size * 0.25, 0);
ctx.lineTo(-size * 0.3, size * 0.15);
ctx.closePath();
ctx.fillStyle = '#E0E0E0';
ctx.fill();
ctx.strokeStyle = '#A9A9A9';
ctx.lineWidth = size * 0.01;
ctx.stroke();
// Fletching (red feathers at the end)
ctx.fillStyle = '#B22222'; // FireBrick
ctx.beginPath();
ctx.moveTo(-shaftLength + size*0.1, 0);
ctx.lineTo(-shaftLength - size*0.1, -size * 0.2);
ctx.lineTo(-shaftLength + size*0.3, 0);
ctx.lineTo(-shaftLength - size*0.1, size * 0.2);
ctx.closePath();
ctx.fill();
// Gold wraps around the feathers
ctx.strokeStyle = '#DAA520';
ctx.lineWidth = size * 0.02;
ctx.beginPath();
ctx.moveTo(-shaftLength + size*0.15, -shaftWidth/2);
ctx.lineTo(-shaftLength + size*0.15, shaftWidth/2);
ctx.moveTo(-shaftLength + size*0.25, -shaftWidth/2);
ctx.lineTo(-shaftLength + size*0.25, shaftWidth/2);
ctx.stroke();
ctx.restore();
}
// Place the arrow deep in the right lily pad
drawArrow(w * 0.82, h * 0.88, scale * 0.15);
// Helper function: Royal Crown
function drawCrown(x, y, width, height) {
ctx.save();
ctx.translate(x, y);
ctx.shadowColor = 'rgba(0,0,0,0.6)';
ctx.shadowBlur = scale * 0.02;
ctx.shadowOffsetY = scale * 0.01;
ctx.beginPath();
// Bottom Base
ctx.moveTo(-width/2, height/2);
ctx.lineTo(width/2, height/2);
// Right outer edge
ctx.lineTo(width/2 + width*0.15, -height/2 + height*0.3);
// Right dip
ctx.lineTo(width/4, height*0.1);
// Center spike
ctx.lineTo(0, -height/2);
// Left dip
ctx.lineTo(-width/4, height*0.1);
// Left outer edge
ctx.lineTo(-width/2 - width*0.15, -height/2 + height*0.3);
ctx.closePath();
// Golden gradient
const grad = ctx.createLinearGradient(0, -height/2, 0, height/2);
grad.addColorStop(0, '#FFF700');
grad.addColorStop(0.5, '#FFD700');
grad.addColorStop(1, '#B8860B');
ctx.fillStyle = grad;
ctx.fill();
ctx.lineWidth = width * 0.02;
ctx.strokeStyle = '#8B6508';
ctx.stroke();
// Base Trim
ctx.beginPath();
ctx.moveTo(-width/2, height/2);
ctx.lineTo(width/2, height/2);
ctx.lineWidth = height * 0.15;
ctx.lineCap = 'round';
ctx.strokeStyle = '#FFF8DC'; // Off-white soft trim
ctx.stroke();
ctx.shadowColor = 'transparent';
// Draw embedded jewels
function drawJewel(jx, jy, cr, color) {
ctx.beginPath();
ctx.arc(jx, jy, cr, 0, Math.PI*2);
ctx.fillStyle = color;
ctx.fill();
ctx.strokeStyle = '#2F4F4F';
ctx.lineWidth = cr * 0.1;
ctx.stroke();
// Shine reflection
ctx.beginPath();
ctx.arc(jx - cr*0.3, jy - cr*0.3, cr*0.2, 0, Math.PI*2);
ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
ctx.fill();
}
drawJewel(0, -height/2, width*0.06, '#DC143C'); // Center Red Sapphire
drawJewel(-width/2 - width*0.15, -height/2 + height*0.3, width*0.04, '#4169E1'); // Left Blue Sapphire
drawJewel(width/2 + width*0.15, -height/2 + height*0.3, width*0.04, '#4169E1'); // Right Blue Sapphire
drawJewel(0, height*0.25, width*0.05, '#32CD32'); // Bottom Emerald Green
ctx.restore();
}
// Draw a crown hovering near the top center
drawCrown(w * 0.5, h * 0.12, scale * 0.2, scale * 0.15);
// Helper function: Enchanted Fairy Tale Golden Text
function drawGoldText(txt, x, y, size) {
ctx.save();
ctx.font = `bold italic ${size}px "Times New Roman", Times, serif`;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
// Dark mystical backdrop glow
ctx.shadowColor = 'rgba(0, 0, 0, 0.85)';
ctx.shadowBlur = size * 0.2;
ctx.shadowOffsetX = size * 0.02;
ctx.shadowOffsetY = size * 0.02;
const grad = ctx.createLinearGradient(0, y - size/2, 0, y + size/2);
grad.addColorStop(0, '#FFF5EE'); // Pure bright top
grad.addColorStop(0.3, '#FFD700'); // Gold
grad.addColorStop(0.7, '#DAA520'); // GoldenRod
grad.addColorStop(1, '#8B6508'); // Dark rich gold
// Text Stroke (creates fairy tale book styling)
ctx.lineWidth = size * 0.06;
ctx.strokeStyle = '#1E3323'; // Dark forest slate
ctx.lineJoin = 'round';
ctx.strokeText(txt, x, y);
// Text Fill
ctx.shadowColor = 'transparent';
ctx.fillStyle = grad;
ctx.fillText(txt, x, y);
ctx.restore();
}
// Draw Title text typically indicating "Царевна-лягушка"
if (text && text.trim() !== '') {
drawGoldText(text, w * 0.5, h * 0.9, scale * 0.09);
}
resolve(canvas);
});
}
Apply Changes