You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(
originalImg,
projectTitle = "AI Image Project",
projectDescription = "Present your creative vision perfectly with this simple yet versatile project creator. Create impactful and stunning layouts in just seconds.",
themeColor = "#3b82f6",
buttonText = "Explore Project"
) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 1280;
canvas.height = 720;
// Helper to draw rounded rectangle paths
function roundRect(ctx, x, y, width, height, radius) {
ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.lineTo(x + width - radius, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
ctx.lineTo(x + width, y + height - radius);
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
ctx.lineTo(x + radius, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
ctx.lineTo(x, y + radius);
ctx.quadraticCurveTo(x, y, x + radius, y);
ctx.closePath();
}
// 1. Draw Blurred Background based on original image
ctx.filter = 'blur(40px)';
// Draw it slightly larger than canvas to prevent non-blurred edges
ctx.drawImage(originalImg, -50, -50, canvas.width + 100, canvas.height + 100);
ctx.filter = 'none';
// Apply dark overlay to assure text readability
ctx.fillStyle = 'rgba(0, 0, 0, 0.75)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Decorative geometric background elements
ctx.fillStyle = 'rgba(255, 255, 255, 0.03)';
ctx.beginPath();
ctx.arc(200, 150, 250, 0, Math.PI * 2);
ctx.fill();
ctx.beginPath();
ctx.arc(1080, 570, 350, 0, Math.PI * 2);
ctx.fill();
// 2. Image Container on the Left
const imgBox = { x: 80, y: 80, w: 560, h: 560, radius: 32 };
// Container shadow
ctx.save();
roundRect(ctx, imgBox.x, imgBox.y, imgBox.w, imgBox.h, imgBox.radius);
ctx.shadowColor = 'rgba(0, 0, 0, 0.6)';
ctx.shadowBlur = 40;
ctx.shadowOffsetY = 20;
ctx.fillStyle = '#ffffff';
ctx.fill();
ctx.restore();
// Image clipping
ctx.save();
roundRect(ctx, imgBox.x, imgBox.y, imgBox.w, imgBox.h, imgBox.radius);
ctx.clip();
// Scale and center image using "cover" method
const imgRatio = originalImg.width / originalImg.height;
const boxRatio = imgBox.w / imgBox.h;
let drawW, drawH, drawX, drawY;
if (imgRatio > boxRatio) {
drawH = imgBox.h;
drawW = originalImg.width * (imgBox.h / originalImg.height);
drawX = imgBox.x - (drawW - imgBox.w) / 2;
drawY = imgBox.y;
} else {
drawW = imgBox.w;
drawH = originalImg.height * (imgBox.w / originalImg.width);
drawX = imgBox.x;
drawY = imgBox.y - (drawH - imgBox.h) / 2;
}
ctx.drawImage(originalImg, drawX, drawY, drawW, drawH);
ctx.restore();
// 3. Glassmorphism Information Card on the Right
const cardBox = { x: 700, y: 80, w: 500, h: 560, radius: 32 };
ctx.save();
roundRect(ctx, cardBox.x, cardBox.y, cardBox.w, cardBox.h, cardBox.radius);
ctx.fillStyle = 'rgba(255, 255, 255, 0.08)';
ctx.fill();
ctx.lineWidth = 1;
ctx.strokeStyle = 'rgba(255, 255, 255, 0.15)';
ctx.stroke();
// Inner light reflection
ctx.lineWidth = 2;
ctx.strokeStyle = 'rgba(255, 255, 255, 0.05)';
ctx.stroke();
ctx.restore();
// 4. Texts inside the Information Card
ctx.textAlign = 'left';
ctx.textBaseline = 'top';
// Sub-title / Category Tag
ctx.font = '600 14px system-ui, -apple-system, sans-serif';
ctx.fillStyle = themeColor;
ctx.letterSpacing = "2px";
ctx.fillText("FEATURED PROJECT", cardBox.x + 50, cardBox.y + 60);
// Title
ctx.font = '800 48px system-ui, -apple-system, sans-serif';
ctx.fillStyle = '#ffffff';
ctx.letterSpacing = "0px";
// Function to wrap text to the next line without cutting words
function wrapText(ctx, text, x, y, maxWidth, lineHeight) {
const words = text.split(' ');
let line = '';
let startY = y;
for(let n = 0; n < words.length; n++) {
let testLine = line + words[n] + ' ';
let metrics = ctx.measureText(testLine);
let testWidth = metrics.width;
if (testWidth > maxWidth && n > 0) {
ctx.fillText(line.trim(), x, startY);
line = words[n] + ' ';
startY += lineHeight;
} else {
line = testLine;
}
}
ctx.fillText(line.trim(), x, startY);
return startY + lineHeight;
}
let titleEndY = wrapText(ctx, projectTitle, cardBox.x + 50, cardBox.y + 90, 400, 56);
// Separator line
ctx.fillStyle = 'rgba(255, 255, 255, 0.2)';
ctx.fillRect(cardBox.x + 50, titleEndY + 25, 60, 4);
// Description text
ctx.font = '400 20px system-ui, -apple-system, sans-serif';
ctx.fillStyle = 'rgba(255, 255, 255, 0.7)';
// Setting line height for the description
let descEndY = wrapText(ctx, projectDescription, cardBox.x + 50, titleEndY + 55, 400, 32);
// 5. Stylized Call-To-Action Button
const btnW = 220;
const btnH = 55;
const btnX = cardBox.x + 50;
// Align bottom or just below the description
const btnY = Math.max(descEndY + 50, cardBox.y + cardBox.h - 105);
ctx.save();
roundRect(ctx, btnX, btnY, btnW, btnH, 27.5);
ctx.fillStyle = themeColor;
// Colored Shadow based on user theme
ctx.shadowColor = themeColor;
ctx.shadowBlur = 20;
ctx.shadowOffsetY = 8;
ctx.fill();
// Reset shadow for button text
ctx.shadowBlur = 0;
ctx.shadowOffsetY = 0;
ctx.fillStyle = '#ffffff';
ctx.font = '700 18px system-ui, -apple-system, sans-serif';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(buttonText, btnX + btnW / 2, btnY + btnH / 2);
ctx.restore();
return canvas;
}
Apply Changes