You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(
originalImg,
studio = "HOLLYWOOD STUDIOS",
film = "THE GREAT MOVIE",
company = "AWESOME PRODUCTIONS",
year = "2024",
tvFormat = "4K DIGITAL",
directorName = "JOHN DOE"
) {
// Parameter validation and conversion to strings
studio = String(studio);
film = String(film);
company = String(company);
year = String(year);
tvFormat = String(tvFormat);
directorName = String(directorName);
// Create main canvas
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Scale up if image is too small to ensure text is readable
const targetWidth = Math.max(originalImg.width, 1000);
const targetHeight = originalImg.height * (targetWidth / originalImg.width);
canvas.width = targetWidth;
canvas.height = targetHeight;
// Draw the original image
ctx.drawImage(originalImg, 0, 0, targetWidth, targetHeight);
// 1. Apply a cinematic color grade (subtle warm vignette)
const gradient = ctx.createRadialGradient(
targetWidth / 2, targetHeight / 2, targetWidth * 0.3,
targetWidth / 2, targetHeight / 2, targetWidth * 0.8
);
gradient.addColorStop(0, 'rgba(0, 0, 0, 0)');
gradient.addColorStop(1, 'rgba(0, 0, 0, 0.7)');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, targetWidth, targetHeight);
// Subtle warm cinematic wash
ctx.globalCompositeOperation = 'overlay';
ctx.fillStyle = 'rgba(255, 140, 0, 0.08)';
ctx.fillRect(0, 0, targetWidth, targetHeight);
ctx.globalCompositeOperation = 'source-over';
// 2. Cinematic Letterbox (black bars top and bottom)
const barHeight = targetHeight * 0.12;
ctx.fillStyle = '#000000';
ctx.fillRect(0, 0, targetWidth, barHeight);
ctx.fillRect(0, targetHeight - barHeight, targetWidth, barHeight);
const uiScale = targetWidth / 1000;
// 3. REC indicator and Timecode in the top bar
ctx.fillStyle = '#ff0000';
ctx.beginPath();
ctx.arc(targetWidth - 120 * uiScale, barHeight / 2, 8 * uiScale, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = '#ffffff';
ctx.textBaseline = 'middle';
ctx.font = `bold ${20 * uiScale}px Arial, sans-serif`;
ctx.fillText("REC", targetWidth - 100 * uiScale, barHeight / 2 + 2 * uiScale);
ctx.font = `bold ${24 * uiScale}px "Courier New", Courier, monospace`;
ctx.textAlign = 'center';
// Generate Mock Timecode
const d = new Date();
const hh = String(d.getHours()).padStart(2, '0');
const mm = String(d.getMinutes()).padStart(2, '0');
const ss = String(d.getSeconds()).padStart(2, '0');
const ff = String(Math.floor(Math.random() * 24)).padStart(2, '0');
ctx.fillText(`${hh}:${mm}:${ss}:${ff}`, targetWidth / 2, barHeight / 2 + 2 * uiScale);
// 4. Draw Hollywood Clapperboard / Production ID
ctx.textAlign = 'left';
ctx.textBaseline = 'top';
// Clapperboard dimensions
const scale = (targetWidth * 0.35) / 400; // Base width of 400 scaled to 35% of image width
const w = 400 * scale;
const h = 260 * scale;
const stickH = 40 * scale;
// Positioning
const x = targetWidth * 0.05;
const y = targetHeight - barHeight - h + 20 * scale;
// Helper to draw the chevron stripes
const drawStripes = (sx, sy, sw, sh) => {
ctx.save();
ctx.beginPath();
ctx.rect(sx, sy, sw, sh);
ctx.clip();
ctx.fillStyle = '#ffffff';
const stripeW = 40 * scale;
for (let i = -sh; i < sw; i += stripeW * 2) {
ctx.beginPath();
ctx.moveTo(sx + i, sy);
ctx.lineTo(sx + i + stripeW, sy);
ctx.lineTo(sx + i + stripeW + sh, sy + sh);
ctx.lineTo(sx + i + sh, sy + sh);
ctx.fill();
}
ctx.restore();
};
// --- Draw the sticks (top part) ---
const bsY = y - stickH;
// Stationary base stick
ctx.fillStyle = '#111111';
ctx.fillRect(x, bsY, w, stickH);
drawStripes(x, bsY, w, stickH);
ctx.strokeStyle = '#ffffff';
ctx.lineWidth = 3 * scale;
ctx.strokeRect(x, bsY, w, stickH);
// Hinge (golden circle)
ctx.beginPath();
ctx.arc(x + stickH / 2, bsY + stickH / 2, stickH * 0.4, 0, Math.PI * 2);
ctx.fillStyle = '#e6c200';
ctx.fill();
ctx.stroke();
// Moving top stick (tilted open)
ctx.save();
ctx.translate(x + stickH / 2, bsY + stickH / 2);
ctx.rotate(-20 * Math.PI / 180);
const topStickW = w - stickH / 2;
ctx.fillStyle = '#111111';
ctx.fillRect(0, -stickH / 2, topStickW, stickH);
drawStripes(0, -stickH / 2, topStickW, stickH);
ctx.strokeRect(0, -stickH / 2, topStickW, stickH);
ctx.restore();
// --- Draw the Slate (main board) ---
ctx.fillStyle = '#111111';
ctx.fillRect(x, y, w, h);
ctx.strokeRect(x, y, w, h);
// Separating Lines
const drawLine = (x1, y1, x2, y2) => {
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
};
// Horizontal boundaries
drawLine(x, y + 70 * scale, x + w, y + 70 * scale);
drawLine(x, y + 130 * scale, x + w, y + 130 * scale);
drawLine(x, y + 190 * scale, x + w, y + 190 * scale);
// Vertical boundaries
drawLine(x + w * 0.33, y + 70 * scale, x + w * 0.33, y + 130 * scale);
drawLine(x + w * 0.66, y + 70 * scale, x + w * 0.66, y + 130 * scale);
drawLine(x + w * 0.6, y + 130 * scale, x + w * 0.6, y + 190 * scale);
// Text Content on Slate
ctx.fillStyle = '#ffffff';
const drawText = (str, tx, ty, font, maxWidth) => {
ctx.font = font;
ctx.fillText(str, tx, ty, maxWidth);
};
// Row 1: Production / Film
drawText("PROD.", x + 10 * scale, y + 10 * scale, `bold ${14 * scale}px "Courier New"`);
drawText(film.toUpperCase(), x + 10 * scale, y + 28 * scale, `bold ${32 * scale}px "Courier New"`, w * 0.9);
// Row 2: Studio / Year / Format
drawText("STUDIO", x + 10 * scale, y + 75 * scale, `bold ${12 * scale}px "Courier New"`);
drawText(studio.toUpperCase(), x + 10 * scale, y + 95 * scale, `bold ${18 * scale}px "Courier New"`, w * 0.3 - 10 * scale);
drawText("YEAR", x + w * 0.33 + 10 * scale, y + 75 * scale, `bold ${12 * scale}px "Courier New"`);
drawText(year, x + w * 0.33 + 10 * scale, y + 95 * scale, `bold ${22 * scale}px "Courier New"`, w * 0.3 - 10 * scale);
drawText("FORMAT", x + w * 0.66 + 10 * scale, y + 75 * scale, `bold ${12 * scale}px "Courier New"`);
drawText(tvFormat.toUpperCase(), x + w * 0.66 + 10 * scale, y + 95 * scale, `bold ${20 * scale}px "Courier New"`, w * 0.3 - 10 * scale);
// Row 3: Company / Director
drawText("COMPANY", x + 10 * scale, y + 135 * scale, `bold ${12 * scale}px "Courier New"`);
drawText(company.toUpperCase(), x + 10 * scale, y + 155 * scale, `bold ${22 * scale}px "Courier New"`, w * 0.6 - 10 * scale);
drawText("DIRECTOR", x + w * 0.6 + 10 * scale, y + 135 * scale, `bold ${12 * scale}px "Courier New"`);
drawText(directorName.toUpperCase(), x + w * 0.6 + 10 * scale, y + 155 * scale, `bold ${22 * scale}px "Courier New"`, w * 0.4 - 10 * scale);
// Row 4: Bottom Meta details (Date, Scene, Take)
const today = new Date().toLocaleDateString();
drawText(today, x + 10 * scale, y + 210 * scale, `bold ${18 * scale}px "Courier New"`);
drawText("SCENE: 1A TAKE: 3 ROLL: A12", x + w * 0.3 + 10 * scale, y + 210 * scale, `bold ${18 * scale}px "Courier New"`, w * 0.6);
return canvas;
}
Apply Changes