You can edit the below JavaScript code to customize the image tool.
Apply Changes
async function processImage(originalImg, ocrLanguage = 'eng+rus', maxImageWidth = '800') {
// Determine dimensions to fit maxImageWidth while maintaining aspect ratio
const maxWidth = Number(maxImageWidth) || 800;
let scale = 1;
if (originalImg.width > maxWidth) {
scale = maxWidth / originalImg.width;
}
const canvasWidth = originalImg.width * scale;
const canvasHeight = originalImg.height * scale;
// Create the main container element
const container = document.createElement('div');
container.style.fontFamily = 'system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif';
container.style.maxWidth = '900px';
container.style.margin = '0 auto';
container.style.padding = '20px';
container.style.backgroundColor = '#f4f4f9';
container.style.borderRadius = '12px';
container.style.boxShadow = '0 8px 16px rgba(0,0,0,0.1)';
container.style.textAlign = 'center';
// Title
const title = document.createElement('h2');
title.textContent = 'Image Address Scanner & Identifier';
title.style.marginTop = '0';
title.style.color = '#333';
container.appendChild(title);
// Image viewer wrapper (for relative positioning of the scanner line)
const wrapper = document.createElement('div');
wrapper.style.position = 'relative';
wrapper.style.display = 'inline-block';
wrapper.style.overflow = 'hidden';
wrapper.style.borderRadius = '8px';
wrapper.style.boxShadow = '0 4px 8px rgba(0,0,0,0.2)';
wrapper.style.backgroundColor = '#000';
// Set up canvas and draw scaled image
const canvas = document.createElement('canvas');
canvas.width = canvasWidth;
canvas.height = canvasHeight;
canvas.style.display = 'block';
canvas.style.maxWidth = '100%';
canvas.style.height = 'auto';
const ctx = canvas.getContext('2d');
ctx.drawImage(originalImg, 0, 0, canvasWidth, canvasHeight);
wrapper.appendChild(canvas);
// Animated scanner line
const scannerLine = document.createElement('div');
scannerLine.style.position = 'absolute';
scannerLine.style.left = '0';
scannerLine.style.top = '0';
scannerLine.style.width = '100%';
scannerLine.style.height = '3px';
scannerLine.style.backgroundColor = 'rgba(0, 255, 0, 0.8)';
scannerLine.style.boxShadow = '0 0 10px #00ff00, 0 0 20px #00ff00';
scannerLine.style.zIndex = '10';
wrapper.appendChild(scannerLine);
container.appendChild(wrapper);
// Status / Progress Message
const statusText = document.createElement('p');
statusText.style.margin = '20px 0 10px 0';
statusText.style.fontWeight = 'bold';
statusText.style.fontSize = '1.1em';
statusText.style.color = '#0056b3';
statusText.textContent = 'Initializing Scanner Engine...';
container.appendChild(statusText);
// Extract Result Output Box
const resultDiv = document.createElement('div');
resultDiv.style.textAlign = 'left';
resultDiv.style.backgroundColor = '#fff';
resultDiv.style.padding = '15px';
resultDiv.style.border = '1px solid #ddd';
resultDiv.style.borderRadius = '8px';
resultDiv.style.minHeight = '120px';
resultDiv.style.whiteSpace = 'pre-wrap';
resultDiv.style.wordBreak = 'break-word';
resultDiv.style.fontSize = '14px';
resultDiv.style.color = '#444';
container.appendChild(resultDiv);
// Provide generic loading sequence before we fetch Tesseract.js payload
let scanning = true;
let scanPos = 0;
let scanDir = 1;
function animateScan() {
if (!scanning) return;
scanPos += scanDir * 3;
if (scanPos > canvasHeight) {
scanPos = canvasHeight;
scanDir = -1;
} else if (scanPos < 0) {
scanPos = 0;
scanDir = 1;
}
scannerLine.style.top = `${scanPos}px`;
requestAnimationFrame(animateScan);
}
requestAnimationFrame(animateScan);
// Dynamically load Tesseract and process OCR
try {
if (typeof window.Tesseract === 'undefined') {
await new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = 'https://cdn.jsdelivr.net/npm/tesseract.js@4/dist/tesseract.min.js';
script.onload = resolve;
script.onerror = reject;
document.head.appendChild(script);
});
}
const { data: { text, words } } = await window.Tesseract.recognize(canvas, ocrLanguage, {
logger: m => {
if (m.status === 'recognizing text') {
statusText.textContent = `Scanning Image for Identifiers... ${Math.round(m.progress * 100)}%`;
} else if (m.status === 'loading tesseract core' || m.status === 'loading language traineddata') {
statusText.textContent = `Downloading recognition models (${ocrLanguage})...`;
} else {
statusText.textContent = `Status: ${m.status}...`;
}
}
});
// Processing finished
scanning = false;
scannerLine.style.display = 'none';
statusText.textContent = 'Scan Complete! Review Identifier Results:';
statusText.style.color = '#28a745';
// Draw bounding boxes around identified elements on the canvas
ctx.strokeStyle = 'rgba(0, 255, 0, 0.8)';
ctx.lineWidth = 2;
ctx.fillStyle = 'rgba(0, 255, 0, 0.15)';
if (words && words.length > 0) {
words.forEach(w => {
const bbox = w.bbox;
ctx.strokeRect(bbox.x0, bbox.y0, bbox.x1 - bbox.x0, bbox.y1 - bbox.y0);
ctx.fillRect(bbox.x0, bbox.y0, bbox.x1 - bbox.x0, bbox.y1 - bbox.y0);
});
}
// Post-process the extracted text to identify likely addresses / core identifiers
const lines = text.split('\n').map(l => l.trim()).filter(l => l.length > 0);
// Basic heuristic arrays to check for English or Russian Address terms
const addressKeywords = [
'улица', 'ул', 'дом', 'д.', 'квартира', 'кв', 'проспект', 'пр', 'бульвар', 'переулок', 'область',
'street', 'st', 'avenue', 'ave', 'road', 'rd', 'boulevard', 'blvd', 'lane', 'ln', 'apartment', 'apt'
];
const possibleAddresses = lines.filter(l => {
const lower = l.toLowerCase();
// Starts with a number followed by word character, OR contains a common address keyword.
return /^\d+\s+[a-zA-Zа-яА-Я]/.test(l) || addressKeywords.some(key => lower.includes(key));
});
let outputText = "=== Scanner Identifier Results ===\n\n";
if (possibleAddresses.length > 0) {
outputText += "[📍 Possible Addresses / Properties Identified]\n" + possibleAddresses.map(a => ` • ${a}`).join('\n') + "\n\n";
}
outputText += "[📄 Raw Extracted Text Data]\n" + (text.trim() || 'No clear text or identifiers found in the image.');
resultDiv.textContent = outputText;
} catch (err) {
scanning = false;
scannerLine.style.display = 'none';
statusText.style.color = '#dc3545';
statusText.textContent = 'Scanner Initialization Failed';
resultDiv.textContent = `Error details: \n${err.message || err.toString()}`;
}
return container;
}
Apply Changes