You can edit the below JavaScript code to customize the image tool.
async function processImage(originalImg, toLang = 'en', fromLang = 'auto') {
/**
* Translates text found within an image using the experimental TextDetector API
* and a free translation service. The original text is replaced with the
* translated text on a new canvas.
*
* @param {Image} originalImg - The source Javascript Image object.
* @param {string} toLang - The target language code (e.g., 'en', 'es', 'fr').
* @param {string} fromLang - The source language code ('auto' for autodetection).
* @returns {Promise<HTMLCanvasElement>} A canvas with the translated text.
*/
const canvas = document.createElement('canvas');
canvas.width = originalImg.naturalWidth;
canvas.height = originalImg.naturalHeight;
// The 'willReadFrequently' hint can optimize performance for APIs like TextDetector.
const ctx = canvas.getContext('2d', {
willReadFrequently: true
});
// Start by drawing the original image onto the canvas.
// This canvas will be returned as is if no text is found or if APIs are unsupported.
ctx.drawImage(originalImg, 0, 0);
// --- Helper function for making translation API calls ---
const translateText = async (text, to, from) => {
// This tool uses the MyMemory API, which is free for limited, anonymous use.
// For a production application, a more robust service with an API key is recommended.
const url = `https://api.mymemory.translated.net/get?q=${encodeURIComponent(text)}&langpair=${from}|${to}`;
try {
const response = await fetch(url);
if (!response.ok) {
console.error("Translation API request failed:", response.status);
return `[ERR: ${text}]`; // Return original text on HTTP error
}
const data = await response.json();
if (data.responseStatus === 200) {
return data.responseData.translatedText;
} else {
console.warn("Translation service returned an error:", data.responseDetails);
return `[${text}]`; // Return original text on API-level error
}
} catch (error) {
console.error("Translation fetch failed:", error);
return `[FAILED: ${text}]`; // Return original text on network failure
}
};
// --- Helper function to find the best font size to fit text in a bounding box ---
const calculateFittingFontSize = (ctx, text, fontFamily, maxWidth, maxHeight) => {
// Start with a font size that fills the height of the box
let fontSize = Math.floor(maxHeight);
if (fontSize <= 0) return 1;
// Iteratively reduce font size until the text fits within the given width
do {
ctx.font = `${fontSize}px ${fontFamily}`;
if (ctx.measureText(text).width <= maxWidth) {
return fontSize;
}
fontSize--;
} while (fontSize > 5); // Don't allow font size to be smaller than 5px
return 5; // Return a minimum readable size if it still doesn't fit
};
// 1. Check if the TextDetector API is supported by the browser.
if (!('TextDetector' in window)) {
console.error('Text Detection API is not supported in this browser.');
// Draw an error message on the canvas if the API is missing.
ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';
ctx.fillRect(0, canvas.height - 60, canvas.width, 60);
ctx.font = '24px Arial';
ctx.fillStyle = 'white';
ctx.textAlign = 'center';
ctx.fillText('Text Detection API not supported in your browser.', canvas.width / 2, canvas.height - 25);
return canvas;
}
try {
// 2. Detect text blocks in the source image.
const textDetector = new TextDetector();
const detectedTexts = await textDetector.detect(originalImg);
if (!detectedTexts || detectedTexts.length === 0) {
console.log("No text was detected in the image.");
return canvas; // Return the original image if no text is found.
}
const fontFamily = 'Arial, sans-serif'; // Use a web-safe font stack.
// 3. Translate all detected text blocks concurrently for better performance.
const translationPromises = detectedTexts.map(textItem =>
translateText(textItem.rawValue, toLang, fromLang).then(translatedText => ({
bbox: textItem.boundingBox,
translated: translatedText,
}))
);
const translatedItems = await Promise.all(translationPromises);
// 4. Draw the translated text over the original text locations.
for (const item of translatedItems) {
const {
bbox,
translated
} = item;
// Erase the original text by drawing a simple white rectangle.
ctx.fillStyle = 'white';
ctx.fillRect(bbox.x, bbox.y, bbox.width, bbox.height);
// Calculate the best font size to make the translated text fit.
// A small padding is used to prevent text touching the edges.
const padding = bbox.width * 0.05;
const fontSize = calculateFittingFontSize(ctx, translated, fontFamily, bbox.width - padding, bbox.height - padding);
ctx.font = `${fontSize}px ${fontFamily}`;
// Set text properties for drawing.
ctx.fillStyle = 'black';
ctx.textAlign = 'left';
ctx.textBaseline = 'middle';
// Calculate the position to center the text vertically in the box.
const textX = bbox.x + padding / 2;
const textY = bbox.y + bbox.height / 2;
// Draw the translated text.
ctx.fillText(translated, textX, textY, bbox.width - padding);
}
} catch (error) {
console.error("An error occurred during the text detection process:", error);
// Draw an error message on the canvas if detection fails.
ctx.fillStyle = 'rgba(255, 0, 0, 0.7)';
ctx.fillRect(0, canvas.height - 60, canvas.width, 60);
ctx.font = '24px Arial';
ctx.fillStyle = 'white';
ctx.textAlign = 'center';
ctx.fillText('Could not process image for text.', canvas.width / 2, canvas.height - 25);
}
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 Title Translator Tool allows users to translate text found within an image into a different language. By utilizing advanced text detection technology, this tool can identify text within images and replace it with translated text, creating a new image that retains the original’s background. This tool is useful for individuals and businesses needing to localize images for various audiences, enhance accessibility, or repurpose visual content for diverse languages. Common use cases include translating signs, menus, educational materials, and marketing images.