You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, movieDescription = "A cinematic masterpiece that redefines the genre.", textBy = "John Doe", textColor = "#FFFFFF", letterboxRatio = 0.12) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const width = originalImg.width;
const height = originalImg.height;
canvas.width = width;
canvas.height = height;
// Draw original image
ctx.drawImage(originalImg, 0, 0, width, height);
const ratio = parseFloat(letterboxRatio);
let barHeight = 0;
if (!isNaN(ratio) && ratio > 0 && ratio < 0.5) {
barHeight = Math.floor(height * ratio);
// Draw cinematic black bars (letterboxing)
ctx.fillStyle = "#000000";
ctx.fillRect(0, 0, width, barHeight); // Top bar
ctx.fillRect(0, height - barHeight, width, barHeight); // Bottom bar
}
// Draw gradient over the bottom part of the image for better text readability
const gradientStart = height - barHeight - (height * 0.5);
const gradientEnd = height - barHeight;
if (gradientEnd > gradientStart) {
const gradient = ctx.createLinearGradient(0, gradientStart, 0, gradientEnd);
gradient.addColorStop(0, 'rgba(0,0,0,0)');
gradient.addColorStop(1, 'rgba(0,0,0,0.85)');
ctx.fillStyle = gradient;
ctx.fillRect(0, gradientStart, width, gradientEnd - gradientStart);
}
// Text settings
ctx.textAlign = "center";
ctx.textBaseline = "top";
let descFontSize = Math.max(16, width * 0.045);
const textByFontSize = Math.max(10, width * 0.025);
// Text wrap helper
function wrapText(context, text, maxWidth) {
const words = text.split(' ');
let line = '';
const lines = [];
for (let n = 0; n < words.length; n++) {
const testLine = line + words[n] + ' ';
const metrics = context.measureText(testLine);
if (metrics.width > maxWidth && n > 0) {
lines.push(line.trim());
line = words[n] + ' ';
} else {
line = testLine;
}
}
if (line.trim() !== '') lines.push(line.trim());
return lines;
}
const maxWidth = width * 0.85;
let descLineHeight = descFontSize * 1.3;
ctx.font = `italic ${descFontSize}px "Georgia", "Times New Roman", serif`;
let descLines = wrapText(ctx, movieDescription, maxWidth);
let totalTextHeight = (descLines.length * descLineHeight) + textByFontSize + (descFontSize * 0.8);
const maxAllowedHeight = height - (barHeight * 2) - (height * 0.05);
// Auto-scale font size if text is too tall for the frame
while (totalTextHeight > maxAllowedHeight && descFontSize > 12) {
descFontSize -= 2;
descLineHeight = descFontSize * 1.3;
ctx.font = `italic ${descFontSize}px "Georgia", "Times New Roman", serif`;
descLines = wrapText(ctx, movieDescription, maxWidth);
totalTextHeight = (descLines.length * descLineHeight) + textByFontSize + (descFontSize * 0.8);
}
// Position text block at bottom, just above black bar
let startY = height - barHeight - totalTextHeight - (height * 0.03);
if (startY < barHeight) {
startY = barHeight + 10;
}
// Add shadow for better text visibility
ctx.shadowColor = 'rgba(0, 0, 0, 0.9)';
ctx.shadowBlur = 8;
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
ctx.fillStyle = textColor;
// Render movie description
ctx.font = `italic ${descFontSize}px "Georgia", "Times New Roman", serif`;
for (let i = 0; i < descLines.length; i++) {
ctx.fillText(descLines[i], width / 2, startY + (i * descLineHeight));
}
// Render "Text By" element
if (textBy && textBy.trim().length > 0) {
const textByY = startY + (descLines.length * descLineHeight) + (descFontSize * 0.4);
ctx.font = `bold ${textByFontSize}px "Arial", sans-serif`;
// Add cinematic tracking (letter spacing) if supported by browser
if ('letterSpacing' in ctx) {
ctx.letterSpacing = "3px";
}
// Slightly dim the attribution text if the main text is white
if (textColor.trim().toLowerCase() === '#ffffff' || textColor.trim().toLowerCase() === 'white') {
ctx.fillStyle = "rgba(255, 255, 255, 0.75)";
}
const fullTextBy = `TEXT BY ${textBy.toUpperCase()}`;
ctx.fillText(fullTextBy, width / 2, textByY);
}
return canvas;
}
Apply Changes