You can edit the below JavaScript code to customize the image tool.
Apply Changes
async function processImage(originalImg, titleText = "AWESOME VIDEO TITLE", duration = "10:35", showPlayButton = 1, fontSize = 110, fontColor = "#FFFFFF", outlineColor = "#000000", outlineWidth = 8) {
const THUMB_WIDTH = 1280;
const THUMB_HEIGHT = 720;
const canvas = document.createElement('canvas');
canvas.width = THUMB_WIDTH;
canvas.height = THUMB_HEIGHT;
const ctx = canvas.getContext('2d');
// Dynamically load an impactful font like Anton from Google Fonts
const fontName = 'Anton';
try {
const fontStyleId = 'google-font-anton-style';
if (!document.getElementById(fontStyleId)) {
const fontStyle = document.createElement('style');
fontStyle.id = fontStyleId;
fontStyle.innerHTML = `@import url('https://fonts.googleapis.com/css2?family=Anton&display=swap');`;
document.head.appendChild(fontStyle);
}
await document.fonts.load(`${fontSize}px ${fontName}`);
} catch (e) {
console.warn(`Font '${fontName}' could not be loaded. Falling back to a system font.`);
}
// --- 1. Draw background image (cover mode) ---
// Ensure the image covers the 16:9 aspect ratio without distortion
ctx.clearRect(0, 0, THUMB_WIDTH, THUMB_HEIGHT);
const imgRatio = originalImg.width / originalImg.height;
const canvasRatio = THUMB_WIDTH / THUMB_HEIGHT;
let sx, sy, sWidth, sHeight;
if (imgRatio > canvasRatio) { // Image is wider than canvas
sHeight = originalImg.height;
sWidth = sHeight * canvasRatio;
sx = (originalImg.width - sWidth) / 2;
sy = 0;
} else { // Image is taller than or same ratio as canvas
sWidth = originalImg.width;
sHeight = sWidth / canvasRatio;
sx = 0;
sy = (originalImg.height - sHeight) / 2;
}
ctx.drawImage(originalImg, sx, sy, sWidth, sHeight, 0, 0, THUMB_WIDTH, THUMB_HEIGHT);
// --- 2. Draw Title Text ---
if (titleText && titleText.trim() !== "") {
ctx.font = `bold ${Number(fontSize)}px ${fontName}, Arial Black, sans-serif`;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
const lines = titleText.split('\n');
const lineHeight = Number(fontSize) * 1.1;
const totalTextHeight = lines.length * lineHeight;
const startY = (THUMB_HEIGHT - totalTextHeight) / 2 + lineHeight / 2;
// Draw outline then fill
lines.forEach((line, index) => {
const y = startY + (index * lineHeight);
ctx.strokeStyle = outlineColor;
ctx.lineWidth = Number(outlineWidth) * 2; // Needs to be thicker for stroke
ctx.lineJoin = 'round'; // For smooth corners
ctx.miterLimit = 2;
ctx.strokeText(line.toUpperCase(), THUMB_WIDTH / 2, y);
ctx.fillStyle = fontColor;
ctx.fillText(line.toUpperCase(), THUMB_WIDTH / 2, y);
});
}
// --- 3. Draw Duration Stamp ---
if (duration && duration.trim() !== "") {
const padding = 12;
const rectHeight = 40;
ctx.font = 'bold 28px "YouTube Sans", Arial, sans-serif';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
const textMetrics = ctx.measureText(duration);
const rectWidth = textMetrics.width + padding * 2;
const rectX = THUMB_WIDTH - rectWidth - padding;
const rectY = THUMB_HEIGHT - rectHeight - padding;
ctx.fillStyle = 'rgba(0, 0, 0, 0.75)';
ctx.beginPath();
ctx.roundRect(rectX, rectY, rectWidth, rectHeight, 8);
ctx.fill();
ctx.fillStyle = '#FFFFFF';
ctx.fillText(duration, rectX + rectWidth / 2, rectY + rectHeight / 2 + 1);
}
// --- 4. Draw Play Button ---
if (Number(showPlayButton) === 1) {
const buttonWidth = 180;
const buttonHeight = 126;
const centerX = THUMB_WIDTH / 2;
const centerY = THUMB_HEIGHT / 2;
// Draw red rounded rectangle
ctx.fillStyle = 'rgba(255, 0, 0, 0.9)';
ctx.beginPath();
ctx.roundRect(centerX - buttonWidth / 2, centerY - buttonHeight / 2, buttonWidth, buttonHeight, 28);
ctx.fill();
// Draw white play triangle
const triangleHeight = 60;
const triangleBase = triangleHeight * Math.sqrt(3) / 2; // For equilateral look
const tipX = centerX + triangleBase / 2.5;
const tipY = centerY;
const leftX = centerX - triangleBase / 1.5;
const leftY = centerY - triangleHeight / 2;
const rightX = leftX;
const rightY = centerY + triangleHeight / 2;
ctx.fillStyle = 'white';
ctx.beginPath();
ctx.moveTo(tipX, tipY);
ctx.lineTo(leftX, leftY);
ctx.lineTo(rightX, rightY);
ctx.closePath();
ctx.fill();
}
return canvas;
}
Apply Changes