You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, searchText = "", highlightColor = "red", matchCase = 0, exactMatch = 0, language = "eng") {
// Determine canvas dimensions based on the original image
const width = originalImg.naturalWidth || originalImg.width || 800;
const height = originalImg.naturalHeight || originalImg.height || 600;
// Create a container to hold the canvas element
const container = document.createElement('div');
container.style.position = 'relative';
container.style.display = 'inline-block';
container.style.maxWidth = '100%';
// Create and configure the canvas
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
canvas.style.maxWidth = '100%';
canvas.style.height = 'auto';
canvas.style.display = 'block';
const ctx = canvas.getContext('2d');
// Draw the original image onto the canvas
ctx.drawImage(originalImg, 0, 0, width, height);
// Provide a visual loading indicator while OCR runs
ctx.fillStyle = "rgba(0, 0, 0, 0.6)";
ctx.fillRect(0, 0, width, height);
ctx.fillStyle = "white";
ctx.font = `bold ${Math.max(20, width / 25)}px sans-serif`;
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText("Scanning Image for Text...", width / 2, height / 2);
container.appendChild(canvas);
// Asynchronous closure to handle Tesseract OCR dynamically
(async () => {
// Dynamically import Tesseract.js if not already present
if (!window.Tesseract) {
try {
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);
});
} catch (e) {
showError("Failed to load OCR library. Check your internet connection.");
return;
}
}
try {
// Create OCR worker and run recognition
const worker = await window.Tesseract.createWorker(language);
const result = await worker.recognize(originalImg);
await worker.terminate(); // Free memory
// Restore the original image inside canvas without the loading overlay
ctx.clearRect(0, 0, width, height);
ctx.drawImage(originalImg, 0, 0, width, height);
// Process search query
const query = matchCase === 1 ? searchText.trim() : searchText.trim().toLowerCase();
// If the search query contains space, search through lines to match phrases.
// Otherwise, search individual words for tighter bounding boxes.
const hasSpaces = query.includes(' ');
const searchBlocks = (hasSpaces ? result.data.lines : result.data.words) || [];
ctx.strokeStyle = highlightColor;
ctx.lineWidth = Math.max(2, width / 400);
for (const block of searchBlocks) {
const blockTextStr = block.text.trim();
if (!blockTextStr) continue;
const textToCompare = matchCase === 1 ? blockTextStr : blockTextStr.toLowerCase();
let isMatch = false;
if (!query) {
isMatch = true; // Highlight all text if search is empty
} else if (exactMatch === 1) {
isMatch = (textToCompare === query);
} else {
isMatch = textToCompare.includes(query);
}
if (isMatch) {
const { x0, y0, x1, y1 } = block.bbox;
const bWidth = x1 - x0;
const bHeight = y1 - y0;
// Draw bounding box border
ctx.beginPath();
ctx.rect(x0, y0, bWidth, bHeight);
ctx.stroke();
// Fill bounding box with a light transparent color
ctx.fillStyle = highlightColor;
ctx.globalAlpha = 0.3;
ctx.fillRect(x0, y0, bWidth, bHeight);
ctx.globalAlpha = 1.0; // Reset opacity
}
}
} catch (err) {
console.error("OCR Error:", err);
showError("An error occurred while processing text recognition.");
}
})();
// Helper function to display errors visually on the canvas
function showError(msg) {
ctx.clearRect(0, 0, width, height);
ctx.drawImage(originalImg, 0, 0, width, height);
ctx.fillStyle = "rgba(255, 0, 0, 0.85)";
ctx.fillRect(0, 0, width, 60);
ctx.fillStyle = "white";
ctx.font = "bold 18px sans-serif";
ctx.textAlign = "left";
ctx.textBaseline = "top";
ctx.fillText(msg, 10, 20);
}
return container;
}
Apply Changes