You can edit the below JavaScript code to customize the image tool.
Apply Changes
async function processImage(
originalImg,
classificationText = "TOP SECRET",
headerDetails = "FOR OFFICIAL USE ONLY",
footerLeftText = "", // Auto-generates if empty
footerRightText = "", // Auto-generates if empty
stampColor = "rgb(200, 0, 0)",
docTextColor = "black",
pageColor = "#F0E68C" // Khaki/Manila like color
) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const img = originalImg;
// --- Calculate dynamic sizes ---
const outerMargin = 30;
const elementSpacing = 15;
const stampRotation = -0.03; // Radians, approx -1.7 degrees
// Base size for font calculation, capped to prevent excessively large fonts for huge images
const referenceDim = Math.min(img.width, img.height); // Use smaller dimension of image
const baseSizeForFontCalc = Math.min(referenceDim, 800); // Cap this reference to 800px
const stampAreaNominalHeight = Math.max(40, baseSizeForFontCalc * 0.12 + img.height * 0.03);
const detailsAreaNominalHeight = Math.max(25, baseSizeForFontCalc * 0.06 + img.height * 0.015);
const stampFontPixels = Math.floor(stampAreaNominalHeight * 0.75);
const detailsFontPixels = Math.floor(detailsAreaNominalHeight * 0.70);
// --- Determine canvas dimensions ---
canvas.width = img.width + 2 * outerMargin;
let currentProjectedHeight = 0;
currentProjectedHeight += outerMargin; // Top margin
if (classificationText) {
currentProjectedHeight += stampAreaNominalHeight;
currentProjectedHeight += elementSpacing;
}
if (headerDetails) {
currentProjectedHeight += detailsAreaNominalHeight;
currentProjectedHeight += elementSpacing;
}
currentProjectedHeight += img.height; // Image
currentProjectedHeight += elementSpacing;
currentProjectedHeight += detailsAreaNominalHeight; // Footer details area (always present due to defaults)
if (classificationText) {
currentProjectedHeight += elementSpacing;
currentProjectedHeight += stampAreaNominalHeight; // Bottom stamp
}
currentProjectedHeight += outerMargin; // Bottom margin
canvas.height = currentProjectedHeight;
// --- Fill background ---
ctx.fillStyle = pageColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
let currentY = outerMargin;
// --- Helper function to draw rotated stamp text ---
function drawStampText(text, yPos, height, fontSize) {
if (!text) return;
const centerX = canvas.width / 2;
const centerY = yPos + height / 2;
ctx.save();
ctx.translate(centerX, centerY);
ctx.rotate(stampRotation);
ctx.font = `bold ${fontSize}px Impact, Arial Black, sans-serif`;
ctx.fillStyle = stampColor;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(text, 0, 0);
ctx.restore();
}
// --- Draw Top Stamp (classificationText) ---
if (classificationText) {
drawStampText(classificationText, currentY, stampAreaNominalHeight, stampFontPixels);
currentY += stampAreaNominalHeight + elementSpacing;
}
// --- Draw Header Details (headerDetails) ---
if (headerDetails) {
ctx.font = `${detailsFontPixels}px 'Courier New', Courier, monospace`;
ctx.fillStyle = docTextColor;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(headerDetails, canvas.width / 2, currentY + detailsAreaNominalHeight / 2);
currentY += detailsAreaNominalHeight + elementSpacing;
}
// --- Draw Original Image ---
ctx.drawImage(img, outerMargin, currentY, img.width, img.height);
// Add a thin border around the image
ctx.strokeStyle = docTextColor;
ctx.lineWidth = 1;
ctx.strokeRect(outerMargin, currentY, img.width, img.height);
currentY += img.height + elementSpacing;
// --- Draw Footer Details (footerLeftText, footerRightText) ---
const randomFileSuffix = Math.random().toString(36).substring(2, 7).toUpperCase();
const randomNumber = Math.floor(Math.random() * 899 + 100); // 100-999
const finalFooterLeft = footerLeftText || `FILE REF: ${randomFileSuffix}-${randomNumber}`;
const finalFooterRight = footerRightText || `DATE: ${new Date().toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' }).toUpperCase()}`;
ctx.font = `${detailsFontPixels}px 'Courier New', Courier, monospace`;
ctx.fillStyle = docTextColor;
ctx.textBaseline = 'middle';
const footerY = currentY + detailsAreaNominalHeight / 2;
ctx.textAlign = 'left';
ctx.fillText(finalFooterLeft, outerMargin, footerY);
ctx.textAlign = 'right';
ctx.fillText(finalFooterRight, canvas.width - outerMargin, footerY);
currentY += detailsAreaNominalHeight; // Spacing added only if bottom stamp exists
// --- Draw Bottom Stamp (classificationText) ---
if (classificationText) {
currentY += elementSpacing; // Add spacing before bottom stamp
drawStampText(classificationText, currentY, stampAreaNominalHeight, stampFontPixels);
// currentY += stampAreaNominalHeight; // Not needed as it's the last element before bottom margin
}
return canvas;
}
Apply Changes