You can edit the below JavaScript code to customize the image tool.
Apply Changes
async function processImage(originalImg, titleText = "ANNABELLE", taglineText = "BEFORE THE CONJURING, THERE WAS", dateText = "OCTOBER 3") {
// Dynamically load the 'Cinzel' font for the authentic horror movie typography
const fontUrl = "https://fonts.googleapis.com/css2?family=Cinzel:wght@600;700&display=swap";
if (!document.querySelector(`link[href="${fontUrl}"]`)) {
const link = document.createElement("link");
link.rel = "stylesheet";
link.href = fontUrl;
document.head.appendChild(link);
}
// Attempt to wait for the font to load so it renders correctly on the first pass
try {
await document.fonts.load("700 24px Cinzel");
} catch(e) {
console.warn("Font 'Cinzel' loading timed out, falling back to default styling.");
}
const canvas = document.createElement("canvas");
const w = originalImg.width;
const h = originalImg.height;
canvas.width = w;
canvas.height = h;
const ctx = canvas.getContext("2d");
// 1. Base Image with Creepy Cinematic Filters (Sickly Doll Aesthetic)
// Decreased brightness, high contrast, heavy desaturation, and a slight green-amber tint
ctx.filter = "grayscale(75%) sepia(30%) contrast(165%) brightness(65%) hue-rotate(-10deg)";
ctx.drawImage(originalImg, 0, 0, w, h);
ctx.filter = "none";
// 2. Heavy Claustrophobic Vignette / Shadow Overlay
const vignetteGrad = ctx.createRadialGradient(w / 2, h * 0.4, h * 0.1, w / 2, h * 0.5, h * 0.85);
vignetteGrad.addColorStop(0, "rgba(5, 3, 0, 0)");
vignetteGrad.addColorStop(0.5, "rgba(8, 5, 3, 0.6)");
vignetteGrad.addColorStop(1, "rgba(3, 1, 0, 0.98)");
ctx.fillStyle = vignetteGrad;
ctx.fillRect(0, 0, w, h);
// 3. Subtle Bloody / Deep Red Corner Tint
const cornerGrad = ctx.createLinearGradient(0, h, w, 0);
cornerGrad.addColorStop(0, "rgba(60, 5, 5, 0.35)");
cornerGrad.addColorStop(0.5, "rgba(0, 0, 0, 0)");
cornerGrad.addColorStop(1, "rgba(20, 20, 10, 0.2)");
ctx.fillStyle = cornerGrad;
ctx.fillRect(0, 0, w, h);
// 4. Background Scratches (Vertical Distressed Lines)
ctx.lineWidth = Math.max(1, w * 0.0015);
ctx.strokeStyle = "rgba(0, 0, 0, 0.5)";
for (let i = 0; i < h; i += h * 0.02) {
ctx.beginPath();
let x = Math.random() * w;
ctx.moveTo(x, i);
ctx.lineTo(x + (Math.random() * w * 0.04 - w * 0.02), i + h * 0.3);
ctx.stroke();
}
// 5. Film Grain Overlay (Safe from cross-origin tainting)
const grainCanvas = document.createElement("canvas");
grainCanvas.width = 120;
grainCanvas.height = 120;
const grainCtx = grainCanvas.getContext("2d");
const grainData = grainCtx.createImageData(120, 120);
for (let i = 0; i < grainData.data.length; i += 4) {
const v = Math.random() * 255;
grainData.data[i] = v;
grainData.data[i+1] = v;
grainData.data[i+2] = v;
grainData.data[i+3] = 12; // Very subtle noise opacity
}
grainCtx.putImageData(grainData, 0, 0);
ctx.fillStyle = ctx.createPattern(grainCanvas, "repeat");
ctx.fillRect(0, 0, w, h);
// 6. Typography Formatting
ctx.textAlign = "center";
ctx.textBaseline = "middle";
// Draw Tagline ("BEFORE THE CONJURING, THERE WAS")
ctx.font = `600 ${h * 0.025}px 'Trebuchet MS', 'Arial', sans-serif`;
ctx.fillStyle = "#c2baa3"; // Dirty light bone tone
if ('letterSpacing' in ctx) ctx.letterSpacing = `${w * 0.006}px`;
ctx.shadowColor = "rgba(0, 0, 0, 0.8)";
ctx.shadowBlur = h * 0.01;
ctx.fillText(taglineText.toUpperCase(), w / 2, h * 0.72);
// Draw Title ("ANNABELLE")
// Base large title
ctx.font = `700 ${h * 0.11}px 'Cinzel', serif`;
ctx.fillStyle = "#f5f5f5";
if ('letterSpacing' in ctx) ctx.letterSpacing = `${w * 0.025}px`;
// Add sinister red glow/shadow behind the title text
ctx.shadowColor = "#8a0303";
ctx.shadowBlur = h * 0.035;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.fillText(titleText.toUpperCase(), w / 2, h * 0.82);
// Re-draw text with tighter shadow to make the core sharp and bright
ctx.shadowBlur = h * 0.01;
ctx.fillText(titleText.toUpperCase(), w / 2, h * 0.82);
// Reset shadow properties for date
ctx.shadowBlur = 0;
ctx.shadowColor = "transparent";
// Draw Date ("OCTOBER 3")
ctx.font = `700 ${h * 0.03}px 'Cinzel', serif`;
ctx.fillStyle = "#9e2a2b"; // Subdued blood red
if ('letterSpacing' in ctx) ctx.letterSpacing = `${w * 0.01}px`;
ctx.fillText(dateText.toUpperCase(), w / 2, h * 0.93);
// Clean up contextual letter spacing
if ('letterSpacing' in ctx) ctx.letterSpacing = "0px";
// 7. Text Distressing Overlay (Destructive scratches masking the text itself)
// Makes the letters appear chipped and weathered
ctx.globalCompositeOperation = "destination-out";
ctx.strokeStyle = "rgba(0, 0, 0, 0.8)";
ctx.lineWidth = h * 0.003;
for (let i = 0; i < w; i += w * 0.01) {
if (Math.random() > 0.6) {
ctx.beginPath();
ctx.moveTo(i + Math.random() * w * 0.05, h * 0.65);
ctx.lineTo(i - Math.random() * w * 0.05, h);
ctx.stroke();
}
}
ctx.globalCompositeOperation = "source-over";
return canvas;
}
Apply Changes