You can edit the below JavaScript code to customize the image tool.
async function processImage(
originalImg,
titleText = "Infographic Title",
titleColor = "black",
titleFontSize = 30,
titleFontFamily = "Arial",
descriptionText = "Some insightful facts and details about the displayed image. This text can wrap to multiple lines if it's long enough.",
descriptionColor = "dimgray",
descriptionFontSize = 16,
descriptionFontFamily = "Arial",
backgroundColor = "white",
padding = 20,
infographicContentWidth = 600
) {
// 0. Ensure fonts are loaded (best-effort for non-system fonts)
try {
// Quote font family names to handle spaces correctly
if (titleText.trim() !== "") {
await document.fonts.load(`${titleFontSize}px "${titleFontFamily}"`);
}
if (descriptionText.trim() !== "") {
await document.fonts.load(`${descriptionFontSize}px "${descriptionFontFamily}"`);
}
} catch (err) {
console.warn(`Font loading issue: ${err}. System fallback fonts will be used.`);
// Browser will typically use a fallback font. For simplicity, no explicit fallback change here.
}
// 1. Handle invalid original image (e.g., not loaded or zero dimensions)
if (!originalImg || originalImg.width === 0 || originalImg.height === 0) {
console.error("Original image is invalid or has zero dimensions.");
const errorCanvas = document.createElement('canvas');
const placeholderWidth = infographicContentWidth > 0 ? infographicContentWidth : 200;
const placeholderHeight = 100;
errorCanvas.width = placeholderWidth + 2 * Math.max(0, padding);
errorCanvas.height = placeholderHeight + 2 * Math.max(0, padding);
const errCtx = errorCanvas.getContext('2d');
errCtx.fillStyle = backgroundColor;
errCtx.fillRect(0, 0, errorCanvas.width, errorCanvas.height);
errCtx.fillStyle = "red";
errCtx.font = "16px Arial";
errCtx.textAlign = "center";
errCtx.textBaseline = "middle";
errCtx.fillText("Error: Invalid Image Data", errorCanvas.width / 2, errorCanvas.height / 2);
return errorCanvas;
}
// Ensure padding and content width are reasonable
padding = Math.max(0, padding);
infographicContentWidth = Math.max(10, infographicContentWidth); // Minimum content width
// 2. Determine image scale to fit infographicContentWidth
let scaledImgWidth = originalImg.width;
let scaledImgHeight = originalImg.height;
if (originalImg.width > infographicContentWidth) {
const scaleRatio = infographicContentWidth / originalImg.width;
scaledImgWidth = infographicContentWidth;
scaledImgHeight = originalImg.height * scaleRatio;
}
// If image is narrower than infographicContentWidth, it uses its original width
// and will be centered within the infographicContentWidth area.
// Create a temporary canvas to draw the (potentially scaled) image.
const tempImgCanvas = document.createElement('canvas');
tempImgCanvas.width = scaledImgWidth;
tempImgCanvas.height = scaledImgHeight;
const tempImgCtx = tempImgCanvas.getContext('2d');
tempImgCtx.drawImage(originalImg, 0, 0, scaledImgWidth, scaledImgHeight);
// 3. Create final canvas and context
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// 4. Define text styles and helper for height calculation
const titleFullFont = `${titleFontSize}px "${titleFontFamily}"`;
const descriptionFullFont = `${descriptionFontSize}px "${descriptionFontFamily}"`;
// Helper Function to calculate height of wrapped text
function calculateWrappedTextHeight(context, text, textFont, maxWidth, lineHeight) {
text = String(text); // Ensure text is a string
if (text.trim() === "") return 0;
context.font = textFont;
const words = text.split(' ');
let line = '';
let lines = 0;
if (words.every(word => word === "")) return 0; // Handles text that is only spaces effectively
for (let n = 0; n < words.length; n++) {
const testLine = line + words[n] + ' ';
const metrics = context.measureText(testLine);
if (metrics.width > maxWidth && line.trim() !== '') { // Current line + new word is too long, and current line has content
lines++;
line = words[n] + ' '; // Start new line with current word
} else {
line = testLine; // Word fits, or it's the first word (even if too long by itself)
}
}
if (line.trim() !== '') lines++; // Count any remaining line
return lines * lineHeight;
}
const titleLineHeight = titleFontSize * 1.2;
const titleBlockHeight = titleText.trim() === "" ? 0 : calculateWrappedTextHeight(ctx, titleText, titleFullFont, infographicContentWidth, titleLineHeight);
const descriptionLineHeight = descriptionFontSize * 1.4;
const descriptionBlockHeight = descriptionText.trim() === "" ? 0 : calculateWrappedTextHeight(ctx, descriptionText, descriptionFullFont, infographicContentWidth, descriptionLineHeight);
// 5. Calculate Overall Canvas Dimensions
const canvasFinalWidth = infographicContentWidth + 2 * padding;
let canvasFinalHeight = padding; // Initial top padding
const elementHeights = [];
if (titleBlockHeight > 0) {
elementHeights.push(titleBlockHeight);
}
elementHeights.push(scaledImgHeight); // Image is always part of the height calculation
if (descriptionBlockHeight > 0) {
elementHeights.push(descriptionBlockHeight);
}
if (elementHeights.length === 0) { // Should not happen due to image always being there
canvasFinalHeight += padding; // Only top and bottom padding
} else {
for (let i = 0; i < elementHeights.length; i++) {
canvasFinalHeight += elementHeights[i];
if (i < elementHeights.length - 1) { // If not the last element
canvasFinalHeight += padding; // Add padding between elements
}
}
canvasFinalHeight += padding; // Final bottom padding
}
canvas.width = canvasFinalWidth;
canvas.height = canvasFinalHeight;
// 6. Draw Background
ctx.fillStyle = backgroundColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Helper function to draw wrapped text (centered)
// Returns the Y coordinate at the bottom of the drawn text block.
function drawWrappedText(context, text, textFont, textColor, centerX, startY, maxWidth, lineHeight) {
text = String(text); // Ensure text is a string
if (text.trim() === "") return startY;
context.font = textFont;
context.fillStyle = textColor;
context.textAlign = 'center';
context.textBaseline = 'top';
const words = text.split(' ');
let line = '';
let currentLineY = startY;
if (words.every(word => word === "")) return startY;
for (let n = 0; n < words.length; n++) {
const testLine = line + words[n] + ' ';
const metrics = context.measureText(testLine);
if (metrics.width > maxWidth && line.trim() !== '') {
context.fillText(line.trim(), centerX, currentLineY);
line = words[n] + ' ';
currentLineY += lineHeight;
} else {
line = testLine;
}
}
context.fillText(line.trim(), centerX, currentLineY); // Draw the last line
return currentLineY + lineHeight; // Y right after the last line of text.
}
let currentY = padding; // Y-coordinate for the top of the current element.
const contentXCenter = canvas.width / 2;
// 7. Draw Title
if (titleBlockHeight > 0) {
drawWrappedText(ctx, titleText, titleFullFont, titleColor, contentXCenter, currentY, infographicContentWidth, titleLineHeight);
currentY += titleBlockHeight + padding;
}
// 8. Draw Image
// Image is centered horizontally within the (infographicContentWidth-wide) content area.
const imageDrawX = padding + (infographicContentWidth - scaledImgWidth) / 2;
ctx.drawImage(tempImgCanvas, imageDrawX, currentY, scaledImgWidth, scaledImgHeight);
currentY += scaledImgHeight; // Y is now at the bottom of the image
if (descriptionBlockHeight > 0) { // Add padding only if there's a description following
currentY += padding;
}
// 9. Draw Description
if (descriptionBlockHeight > 0) {
drawWrappedText(ctx, descriptionText, descriptionFullFont, descriptionColor, contentXCenter, currentY, infographicContentWidth, descriptionLineHeight);
// currentY updates not needed after last element as canvas height is fixed
}
// 10. Return canvas
return canvas;
}
Free Image Tool Creator
Can't find the image tool you're looking for? Create one based on your own needs now!
The Image Infographic Creator is a web-based tool that allows users to create visually appealing infographics by combining images with customized titles and descriptions. Users can upload an original image and specify the title text, font styles, colors, and padding. The tool formats the image and associated text into a well-structured infographic suitable for presentations, educational content, social media, and other digital platforms. It’s particularly useful for educators, marketers, and content creators looking to convey information effectively through visual storytelling.