You can edit the below JavaScript code to customize the image tool.
Apply Changes
async function processImage(originalImg, sourceLang = 'rus', targetLang = 'eng', coverColor = 'white', minConfidence = 65) {
/**
* Dynamically loads the Tesseract.js library from a CDN.
* This function ensures the library is loaded only once.
* @returns {Promise<void>} A promise that resolves when the script is loaded.
*/
const loadTesseract = async () => {
if (typeof Tesseract !== 'undefined') {
return;
}
// Use a window property to prevent multiple loads if the function is called rapidly
if (!window.tesseractLoadingPromise) {
window.tesseractLoadingPromise = new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = 'https://cdn.jsdelivr.net/npm/tesseract.js@5/dist/tesseract.min.js';
script.onload = () => {
resolve();
};
script.onerror = (err) => {
console.error("Failed to load Tesseract.js script.", err);
window.tesseractLoadingPromise = null; // Allow retrying
reject('Failed to load Tesseract.js script.');
};
document.head.appendChild(script);
});
}
await window.tesseractLoadingPromise;
};
// Create a canvas and draw the original image onto it.
const canvas = document.createElement('canvas');
canvas.width = originalImg.naturalWidth;
canvas.height = originalImg.naturalHeight;
const ctx = canvas.getContext('2d');
ctx.drawImage(originalImg, 0, 0);
try {
await loadTesseract();
} catch (error) {
console.error(error);
// If Tesseract fails to load, return the original image on the canvas
return canvas;
}
// Transliteration maps for supported language pairs.
const maps = {
'rus-eng': { 'а':'a', 'б':'b', 'в':'v', 'г':'g', 'д':'d', 'е':'e', 'ё':'yo', 'ж':'zh', 'з':'z', 'и':'i', 'й':'y', 'к':'k', 'л':'l', 'м':'m', 'н':'n', 'о':'o', 'п':'p', 'р':'r', 'с':'s', 'т':'t', 'у':'u', 'ф':'f', 'х':'kh', 'ц':'ts', 'ч':'ch', 'ш':'sh', 'щ':'shch', 'ъ':'', 'ы':'y', 'ь':'', 'э':'e', 'ю':'yu', 'я':'ya', 'А':'A', 'Б':'B', 'В':'V', 'Г':'G', 'Д':'D', 'Е':'E', 'Ё':'Yo', 'Ж':'Zh', 'З':'Z', 'И':'I', 'Й':'Y', 'К':'K', 'Л':'L', 'М':'M', 'Н':'N', 'О':'O', 'П':'P', 'Р':'R', 'С':'S', 'Т':'T', 'У':'U', 'Ф':'F', 'Х':'Kh', 'Ц':'Ts', 'Ч':'Ch', 'Ш':'Sh', 'Щ':'Shch', 'Ъ':'', 'Ы':'Y', 'Ь':'', 'Э':'E', 'Ю':'Yu', 'Я':'Ya' },
'eng-rus': { 'a':'а', 'b':'б', 'v':'в', 'g':'г', 'd':'д', 'e':'е', 'z':'з', 'i':'и', 'k':'к', 'l':'л', 'm':'м', 'n':'н', 'o':'о', 'p':'п', 'r':'р', 's':'с', 't':'т', 'u':'у', 'f':'ф', 'h':'х', 'c':'ц', 'A':'А', 'B':'Б', 'V':'В', 'G':'Г', 'D':'Д', 'E':'Е', 'Z':'З', 'I':'И', 'K':'К', 'L':'Л', 'M':'М', 'N':'Н', 'O':'О', 'P':'П', 'R':'Р', 'S':'С', 'T':'Т', 'U':'У', 'F':'Ф', 'H':'Х', 'C':'Ц' }
};
const mapKey = `${sourceLang}-${targetLang}`;
const translationMap = maps[mapKey];
if (!translationMap) {
console.error(`Translation from "${sourceLang}" to "${targetLang}" is not supported.`);
return canvas; // Return original image if map is not found
}
const transliterate = (text) => {
return text.split('').map(char => translationMap[char] || char).join('');
};
let worker;
try {
worker = await Tesseract.createWorker(sourceLang);
const { data: { words } } = await worker.recognize(originalImg);
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
for (const word of words) {
if (word.confidence > minConfidence) {
const bbox = word.bbox;
const boxWidth = bbox.x1 - bbox.x0;
const boxHeight = bbox.y1 - bbox.y0;
// Cover up the original text on the canvas
ctx.fillStyle = coverColor;
ctx.fillRect(bbox.x0, bbox.y0, boxWidth, boxHeight);
// Translate the recognized text
const translatedText = transliterate(word.text);
ctx.fillStyle = 'black'; // A sensible default for the new text color
// Heuristically determine font size and fit text into the original bounding box
let fontSize = Math.floor(boxHeight * 0.9);
ctx.font = `${fontSize}px Arial`;
// Reduce font size until the text fits horizontally
while (ctx.measureText(translatedText).width > boxWidth && fontSize > 5) {
fontSize--;
ctx.font = `${fontSize}px Arial`;
}
// Calculate the center of the bounding box to draw the new text
const centerX = bbox.x0 + boxWidth / 2;
const centerY = bbox.y0 + boxHeight / 2;
ctx.fillText(translatedText, centerX, centerY);
}
}
} catch (error) {
console.error("Error during the OCR process:", error);
} finally {
if (worker) {
await worker.terminate();
}
}
return canvas;
}
Apply Changes