You can edit the below JavaScript code to customize the image tool.
Apply Changes
async function processImage(originalImg, maxProcessingWidth = "800") {
// Determine the max dimensions from parameters fallback defaults to 800
const maxWidth = parseInt(maxProcessingWidth) || 800;
// Create main container for the UI
const container = document.createElement('div');
container.style.cssText = `
font-family: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 24px;
background: #ffffff;
border-radius: 12px;
box-shadow: 0 4px 20px rgba(0,0,0,0.05);
display: flex;
flex-direction: column;
gap: 20px;
color: #333;
`;
const header = document.createElement('h2');
header.textContent = 'Image Language & Script Scanner';
header.style.margin = '0';
header.style.color = '#1f2937';
container.appendChild(header);
// Canvas to display user's uploaded image proportionally
const imgCanvas = document.createElement('canvas');
const ctx = imgCanvas.getContext('2d');
let w = originalImg.width;
let h = originalImg.height;
// Scale down for visual presentation if it's too large
if (w > maxWidth || h > maxWidth) {
const ratio = Math.min(maxWidth / w, maxWidth / h);
w *= ratio;
h *= ratio;
}
imgCanvas.width = w;
imgCanvas.height = h;
ctx.drawImage(originalImg, 0, 0, w, h);
imgCanvas.style.cssText = `
max-width: 100%;
border-radius: 8px;
border: 1px solid #e5e7eb;
background: #f9fafb;
align-self: center;
`;
container.appendChild(imgCanvas);
// Feedback and Output Results Box
const resultBox = document.createElement('div');
resultBox.style.cssText = `
padding: 20px;
border-radius: 8px;
background: #f0fdf4;
border: 1px solid #bbf7d0;
color: #166534;
font-size: 15px;
line-height: 1.5;
`;
resultBox.innerHTML = `<strong>Status:</strong> Initializing scanner...`;
container.appendChild(resultBox);
// Maps Tesseract OSD (Optical Script Detection) models to human-readable languages
const scriptMapping = {
'Latin': 'Latin (English, Spanish, French, German, Italian, etc.)',
'Han': 'Han (Chinese)',
'Cyrillic': 'Cyrillic (Russian, Ukrainian, Bulgarian, etc.)',
'Arabic': 'Arabic (Arabic, Persian, Urdu, etc.)',
'Hangul': 'Hangul (Korean)',
'Hiragana': 'Hiragana (Japanese)',
'Katakana': 'Katakana (Japanese)',
'Devanagari': 'Devanagari (Hindi, Marathi, Nepali, Sanskrit)',
'Thai': 'Thai',
'Tamil': 'Tamil',
'Telugu': 'Telugu',
'Bengali': 'Bengali',
'Greek': 'Greek',
'Hebrew': 'Hebrew',
'Vietnamese': 'Vietnamese',
'Khmer': 'Khmer (Cambodian)',
'Myanmar': 'Myanmar (Burmese)',
'Gujarati': 'Gujarati',
'Kannada': 'Kannada',
'Malayalam': 'Malayalam',
'Sinhala': 'Sinhala'
};
// Anonymous async block to handle script loading and OCR detection
(async () => {
try {
// Check if Tesseract.js is already available; load if missing
if (!window.Tesseract) {
resultBox.innerHTML = `<strong>Status:</strong> Loading OCR Engine...`;
await new Promise((resolve, reject) => {
const script = document.createElement('script');
// Tesseract.js v4.1.1 is highly stable for OSD
script.src = 'https://cdn.jsdelivr.net/npm/tesseract.js@4.1.1/dist/tesseract.min.js';
script.onload = resolve;
script.onerror = () => reject(new Error("Failed to load Tesseract.js script"));
document.head.appendChild(script);
});
}
resultBox.innerHTML = `<strong>Status:</strong> Initializing Optical Script Detection worker...`;
// Setup Tesseract worker with progress reporting
const worker = await window.Tesseract.createWorker({
logger: m => {
if (m.status && m.progress != null) {
const pct = Math.floor(m.progress * 100);
resultBox.innerHTML = `<strong>Status:</strong> ${m.status} (${pct}%)`;
}
}
});
// Load and initialize the Orientation and Script Detection (osd) module
await worker.loadLanguage('osd');
await worker.initialize('osd');
resultBox.innerHTML = `<strong>Status:</strong> Scanning image architecture for localized text...`;
// Detect language script from the original full-fidelity image
const { data } = await worker.detect(originalImg);
await worker.terminate(); // Free memory
// Display results
if (data && data.script) {
const detectedScript = data.script;
const humanReadable = scriptMapping[detectedScript] || detectedScript;
const confidence = (data.script_confidence !== undefined && data.script_confidence !== null)
? data.script_confidence.toFixed(2)
: 'Unknown';
resultBox.style.background = '#eff6ff';
resultBox.style.border = '1px solid #bfdbfe';
resultBox.style.color = '#1e388b';
resultBox.innerHTML = `
<h4 style="margin: 0 0 12px 0; font-size: 18px; color: #1e40af;">Scan Complete</h4>
<table style="width: 100%; border-collapse: collapse; text-align: left;">
<tr>
<td style="padding: 6px 0; width: 45%; font-weight: bold;">Identified Language/Script:</td>
<td style="padding: 6px 0;"><span style="background:#dbeafe; padding: 4px 8px; border-radius: 4px; font-weight: 600;">${humanReadable}</span></td>
</tr>
<tr>
<td style="padding: 6px 0; font-weight: bold;">Detection Confidence:</td>
<td style="padding: 6px 0;">${confidence}</td>
</tr>
<tr>
<td style="padding: 6px 0; font-weight: bold;">Text Orientation:</td>
<td style="padding: 6px 0;">${data.orientation_degrees}°</td>
</tr>
</table>
<p style="margin: 12px 0 0 0; font-size: 13px; color: #64748b; font-style: italic;">
Note: This scanner identifies the family of the written characters (e.g. Latin vs. Cyrillic) which encompasses multi-language groups. Identification happens directly in your browser.
</p>
`;
} else {
throw new Error("No script or recognizable language footprint was identified in the image.");
}
} catch (err) {
console.error("OSD Analysis Error:", err);
resultBox.style.background = '#fef2f2';
resultBox.style.border = '1px solid #fecaca';
resultBox.style.color = '#991b1b';
resultBox.innerHTML = `<strong>Scan Failed:</strong> Could not identify a language or script. Make sure the image contains clear, primarily text-based features.<br><br> <span style="font-size:12px; word-break: break-all;">Diagnostic: ${err.message || 'Unknown processing error'}</span>`;
}
})();
// Always immediately return the structural element while inner processes execute.
return container;
}
Apply Changes