Please bookmark this page to avoid losing your image tool!

ID Document Scanner And Text Editor

(Free & Supports Bulk Upload)

Drag & drop your images here or

The result will appear here...
You can edit the below JavaScript code to customize the image tool.
async function processImage(originalImg, language = 'eng') {
    // Main container
    const container = document.createElement('div');
    container.style.display = 'flex';
    container.style.flexDirection = 'column';
    container.style.gap = '20px';
    container.style.fontFamily = 'system-ui, -apple-system, sans-serif';
    container.style.width = '100%';
    container.style.maxWidth = '1000px';
    container.style.margin = '0 auto';
    container.style.boxSizing = 'border-box';

    // Header & Status
    const header = document.createElement('h3');
    header.textContent = 'ID Document Scanner & Text Editor';
    header.style.margin = '0';
    header.style.color = '#333';
    container.appendChild(header);

    const statusContainer = document.createElement('div');
    statusContainer.style.padding = '10px';
    statusContainer.style.backgroundColor = '#eef6ff';
    statusContainer.style.borderLeft = '4px solid #007bff';
    statusContainer.style.borderRadius = '4px';
    
    const statusLabel = document.createElement('span');
    statusLabel.textContent = 'Status: Initializing Scanner...';
    statusLabel.style.fontWeight = 'bold';
    statusLabel.style.color = '#0056b3';
    statusContainer.appendChild(statusLabel);
    container.appendChild(statusContainer);

    // Working Area (Canvas + Editor side-by-side)
    const workArea = document.createElement('div');
    workArea.style.display = 'flex';
    workArea.style.gap = '20px';
    workArea.style.flexWrap = 'wrap';
    workArea.style.alignItems = 'stretch';

    // 1. Canvas side (Scanner)
    const canvasWrapper = document.createElement('div');
    canvasWrapper.style.flex = '1 1 400px';
    canvasWrapper.style.display = 'flex';
    canvasWrapper.style.flexDirection = 'column';
    canvasWrapper.style.gap = '10px';

    const canvasLabel = document.createElement('label');
    canvasLabel.textContent = 'Scanned Document';
    canvasLabel.style.fontWeight = '600';
    canvasWrapper.appendChild(canvasLabel);

    const canvas = document.createElement('canvas');
    canvas.style.width = '100%';
    canvas.style.height = 'auto';
    canvas.style.border = '1px solid #ccc';
    canvas.style.borderRadius = '4px';
    canvas.style.boxShadow = '0 2px 4px rgba(0,0,0,0.1)';
    canvas.style.backgroundColor = '#000';

    // Scale canvas to a reasonable max dimension for better OCR performance and UI balance
    const MAX_DIM = 1200;
    let scale = 1;
    if (originalImg.width > MAX_DIM || originalImg.height > MAX_DIM) {
        scale = Math.min(MAX_DIM / originalImg.width, MAX_DIM / originalImg.height);
    }
    canvas.width = originalImg.width * scale;
    canvas.height = originalImg.height * scale;
    
    const ctx = canvas.getContext('2d');
    ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
    
    // Simulate scanner enhancement: Increase contrast slightly for better OCR
    const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    const data = imgData.data;
    for (let i = 0; i < data.length; i += 4) {
        for (let j = 0; j < 3; j++) {
            let val = data[i + j];
            // slight contrast boost
            data[i + j] = ((val / 255 - 0.5) * 1.2 + 0.5) * 255; 
        }
    }
    ctx.putImageData(imgData, 0, 0);
    
    canvasWrapper.appendChild(canvas);
    workArea.appendChild(canvasWrapper);

    // 2. Editor side
    const editorWrapper = document.createElement('div');
    editorWrapper.style.flex = '1 1 400px';
    editorWrapper.style.display = 'flex';
    editorWrapper.style.flexDirection = 'column';
    editorWrapper.style.gap = '10px';

    const editorLabel = document.createElement('label');
    editorLabel.textContent = 'Extracted Text Editor';
    editorLabel.style.fontWeight = '600';
    editorWrapper.appendChild(editorLabel);

    const textArea = document.createElement('textarea');
    textArea.style.width = '100%';
    textArea.style.minHeight = '300px';
    textArea.style.flexGrow = '1';
    textArea.style.padding = '12px';
    textArea.style.fontFamily = 'monospace';
    textArea.style.fontSize = '14px';
    textArea.style.lineHeight = '1.5';
    textArea.style.border = '1px solid #ccc';
    textArea.style.borderRadius = '4px';
    textArea.style.boxSizing = 'border-box';
    textArea.style.resize = 'vertical';
    textArea.placeholder = 'Extracted text will appear here. You can manually edit it if the scanner missed something...';
    editorWrapper.appendChild(textArea);

    // Save/Download Button
    const btnContainer = document.createElement('div');
    btnContainer.style.display = 'flex';
    btnContainer.style.justifyContent = 'flex-end';
    
    const downloadBtn = document.createElement('button');
    downloadBtn.textContent = 'Download Text';
    downloadBtn.style.padding = '10px 20px';
    downloadBtn.style.backgroundColor = '#28a745';
    downloadBtn.style.color = '#fff';
    downloadBtn.style.border = 'none';
    downloadBtn.style.borderRadius = '4px';
    downloadBtn.style.cursor = 'pointer';
    downloadBtn.style.fontWeight = 'bold';
    downloadBtn.disabled = true; // Disabled initially until scan is complete
    downloadBtn.style.opacity = '0.5';

    downloadBtn.onclick = () => {
        const blob = new Blob([textArea.value], { type: 'text/plain' });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = 'ID_Document_Extract.txt';
        a.click();
        URL.revokeObjectURL(url);
    };

    btnContainer.appendChild(downloadBtn);
    editorWrapper.appendChild(btnContainer);
    workArea.appendChild(editorWrapper);

    container.appendChild(workArea);

    // Load Tesseract and Run Extraction
    const runScanningTask = async () => {
        try {
            // Load Tesseract dynamically if not available
            if (!window.Tesseract) {
                statusLabel.textContent = 'Status: Loading OCR Engine (Downloading resources, please wait)...';
                await 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 = reject;
                    document.head.appendChild(script);
                });
            }

            statusLabel.textContent = 'Status: Scanning Document...';

            // Start Recognition Process
            const result = await Tesseract.recognize(canvas, language, {
                logger: m => {
                    if (m.status === 'recognizing text') {
                        statusLabel.textContent = `Status: Scanning Document... ${Math.round(m.progress * 100)}%`;
                    } else if(m.status) {
                        statusLabel.textContent = `Status: ${m.status.charAt(0).toUpperCase() + m.status.slice(1)}...`;
                    }
                }
            });

            // Put recognized text into editor
            textArea.value = result.data.text;

            // Draw bounding boxes on canvas to visualize the scanner's successful reads
            ctx.strokeStyle = 'rgba(40, 167, 69, 0.7)'; // Green highlight blocks
            ctx.lineWidth = Math.max(1, 2 * scale);
            result.data.words.forEach(word => {
                const b = word.bbox;
                ctx.strokeRect(b.x0, b.y0, b.x1 - b.x0, b.y1 - b.y0);
            });

            // Update UI success state
            statusLabel.textContent = 'Status: Scanning Complete. You can now edit and save the text.';
            statusLabel.style.color = '#28a745';
            statusContainer.style.borderLeftColor = '#28a745';
            statusContainer.style.backgroundColor = '#e8f7ec';
            
            downloadBtn.disabled = false;
            downloadBtn.style.opacity = '1';

        } catch (error) {
            statusLabel.textContent = 'Status: Error during scanning.';
            statusLabel.style.color = '#dc3545';
            statusContainer.style.borderLeftColor = '#dc3545';
            statusContainer.style.backgroundColor = '#fdf3f4';
            textArea.value = `An error occurred during extraction:\n${error.message}`;
        }
    };

    // Execute async scanner tasks without blocking the UI return
    runScanningTask();

    return container;
}

Free Image Tool Creator

Can't find the image tool you're looking for?
Create one based on your own needs now!

Description

This tool is designed to scan identification documents and extract text from images using OCR technology. It features an image enhancement process to improve readability and provides a side-by-side interface where users can view the scanned document alongside an editable text area. Users can manually correct any extraction errors and then download the final text as a .txt file. This is useful for digitizing information from IDs, driver’s licenses, or other text-heavy documents for easy data entry and record-keeping.

Leave a Reply

Your email address will not be published. Required fields are marked *