Please bookmark this page to avoid losing your image tool!

Image Topic Text Searcher

(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.
function processImage(originalImg, searchText = "", highlightColor = "rgba(255, 255, 0, 0.5)") {
    // 1. Create a responsive container 
    const container = document.createElement('div');
    container.style.display = 'flex';
    container.style.flexDirection = 'column';
    container.style.alignItems = 'center';
    container.style.fontFamily = 'Arial, sans-serif';
    container.style.width = '100%';
    container.style.boxSizing = 'border-box';

    // 2. Setup the canvas for drawing the image and highlights
    const canvas = document.createElement('canvas');
    canvas.width = originalImg.naturalWidth || originalImg.width;
    canvas.height = originalImg.naturalHeight || originalImg.height;
    canvas.style.maxWidth = '100%';
    canvas.style.height = 'auto';
    canvas.style.border = '1px solid #ccc';
    canvas.style.borderRadius = '6px';
    canvas.style.boxShadow = '0 2px 8px rgba(0,0,0,0.1)';
    
    const ctx = canvas.getContext('2d');
    ctx.drawImage(originalImg, 0, 0);

    container.appendChild(canvas);

    // 3. Setup a status/results panel below the canvas
    const statusPanel = document.createElement('div');
    statusPanel.style.marginTop = '20px';
    statusPanel.style.padding = '15px 20px';
    statusPanel.style.borderRadius = '6px';
    statusPanel.style.backgroundColor = '#f8f9fa';
    statusPanel.style.width = '100%';
    statusPanel.style.boxSizing = 'border-box';
    statusPanel.style.border = '1px solid #dee2e6';
    statusPanel.style.boxShadow = '0 1px 3px rgba(0,0,0,0.05)';
    
    const statusText = document.createElement('h4');
    statusText.style.margin = '0 0 10px 0';
    statusText.style.color = '#495057';
    statusText.style.fontWeight = '600';
    statusText.textContent = 'Initializing AI OCR Engine... ⚙️';
    statusPanel.appendChild(statusText);
    
    const resultsList = document.createElement('ul');
    resultsList.style.margin = '0';
    resultsList.style.paddingLeft = '20px';
    resultsList.style.color = '#333';
    resultsList.style.fontSize = '14px';
    resultsList.style.display = 'none'; // Hidden until search yields results
    statusPanel.appendChild(resultsList);

    container.appendChild(statusPanel);

    // 4. Run Optical Character Recognition asynchronously
    (async () => {
        try {
            // Dynamically load Tesseract.js if not available
            if (typeof window.Tesseract === 'undefined') {
                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);
                });
            }
            
            statusText.textContent = 'Scanning image for text... 🔍';
            
            // Execute OCR recognition
            const worker = await window.Tesseract.createWorker('eng');
            const { data } = await worker.recognize(canvas);
            await worker.terminate();

            const lines = data.lines || [];
            const target = searchText.trim().toLowerCase();

            ctx.lineWidth = Math.max(1, Math.floor(canvas.width / 500) * 2);
            ctx.strokeStyle = "rgba(230, 57, 70, 0.9)"; // Red bounding box around matches

            let matchCount = 0;

            // Iterate over all text lines identified by Tesseract
            for (const line of lines) {
                const textLower = line.text.toLowerCase();
                
                // If user provided a search phrase and the line contains it
                if (target.length > 0 && textLower.includes(target)) {
                    matchCount++;
                    
                    // If target contains spaces, highlight the whole matching line bounds
                    if (target.includes(" ")) {
                        ctx.fillStyle = highlightColor;
                        ctx.fillRect(line.bbox.x0, line.bbox.y0, line.bbox.x1 - line.bbox.x0, line.bbox.y1 - line.bbox.y0);
                        ctx.strokeRect(line.bbox.x0, line.bbox.y0, line.bbox.x1 - line.bbox.x0, line.bbox.y1 - line.bbox.y0);
                    } else {
                        // For single words, highlight specific matching words precisely
                        for (const word of line.words) {
                            if (word.text.toLowerCase().includes(target)) {
                                ctx.fillStyle = highlightColor;
                                ctx.fillRect(word.bbox.x0, word.bbox.y0, word.bbox.x1 - word.bbox.x0, word.bbox.y1 - word.bbox.y0);
                                ctx.strokeRect(word.bbox.x0, word.bbox.y0, word.bbox.x1 - word.bbox.x0, word.bbox.y1 - word.bbox.y0);
                            }
                        }
                    }
                    
                    // Append matching text context to the list
                    const li = document.createElement('li');
                    li.style.marginBottom = '6px';
                    li.style.lineHeight = '1.5';
                    
                    // XSS-Safe HTML entity encoding
                    const escapeSpan = document.createElement('span');
                    escapeSpan.textContent = line.text.trim(); 
                    const safeText = escapeSpan.innerHTML; 
                    
                    // Highlight phrase in the text result view
                    const escapedTarget = target.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
                    const regex = new RegExp(`(${escapedTarget})`, 'gi');
                    li.innerHTML = safeText.replace(regex, '<strong style="background-color: #ffeb3b; color: #000; padding: 2px 4px; border-radius: 3px; box-shadow: 0 1px 2px rgba(0,0,0,0.15); font-weight: bold;">$1</strong>');
                    resultsList.appendChild(li);
                    
                } 
                // If search phrase is empty, draw faint highlights over all detected text areas
                else if (target.length === 0) {
                    ctx.fillStyle = "rgba(100, 200, 100, 0.15)"; 
                    ctx.fillRect(line.bbox.x0, line.bbox.y0, line.bbox.x1 - line.bbox.x0, line.bbox.y1 - line.bbox.y0);
                }
            }

            // Update status UI based on results found
            if (target.length > 0) {
                if (matchCount > 0) {
                    statusText.textContent = `Found "${searchText}" in ${matchCount} block(s). ✨`;
                    statusText.style.color = '#28a745'; // Green success color
                    statusPanel.style.borderColor = '#c3e6cb';
                    statusPanel.style.backgroundColor = '#d4edda';
                    resultsList.style.display = 'block';
                } else {
                    statusText.textContent = `No matches found for "${searchText}". ❌`;
                    statusText.style.color = '#dc3545'; // Red error color
                    statusPanel.style.backgroundColor = '#f8d7da';
                    statusPanel.style.borderColor = '#f5c6cb';
                }
            } else {
                if (lines.length > 0) {
                    statusText.textContent = `Scanned ${lines.length} lines of text. Pass a search string via parameters to find topics. ✅`;
                } else {
                    statusText.textContent = `OCR complete. No text detected in this image. ❕`;
                }
            }

        } catch(err) {
            // Handle and display errors properly
            statusText.textContent = 'Error processing image: ' + err.message;
            statusText.style.color = '#dc3545';
            statusPanel.style.backgroundColor = '#f8d7da';
            statusPanel.style.borderColor = '#f5c6cb';
        }
    })();

    // Synchronously return the DOM container (the OCR runs natively in the background)
    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

The Image Topic Text Searcher is an AI-powered utility that uses Optical Character Recognition (OCR) to detect and locate text within any uploaded image. Users can search for specific words or phrases, and the tool will automatically highlight the matching text directly on the image while providing a list of the found text segments in a results panel. This tool is ideal for quickly finding specific information in scanned documents, extracting data from screenshots, or locating key topics within dense images of text, such as infographics or presentations.

Leave a Reply

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