You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, boxLevel = "paragraphs", boxColor = "#00d2ff", lineWidth = 3) {
// Create the main visible canvas
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = originalImg.width;
canvas.height = originalImg.height;
// Draw original image first
ctx.drawImage(originalImg, 0, 0);
// Draw a responsive "Scanning" overlay to provide immediate user feedback
ctx.save();
ctx.fillStyle = "rgba(0, 0, 0, 0.6)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "white";
ctx.font = "bold " + Math.max(16, canvas.width / 25) + "px Arial, sans-serif";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText("Scanning image for text boxes...", canvas.width / 2, canvas.height / 2);
ctx.restore();
// Perform asynchronously while returning the canvas immediately
(async () => {
try {
// Dynamically load Tesseract.js if it isn't already 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);
});
}
// Using Tesseract to detect text areas
const result = await window.Tesseract.recognize(originalImg, 'eng');
// Clear the "Scanning" overlay and redraw the pristine image
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(originalImg, 0, 0);
// Determine which hierarchical level to frame (blocks, paragraphs, lines, words)
const validLevels = ['blocks', 'paragraphs', 'lines', 'words'];
const level = validLevels.includes(boxLevel) ? boxLevel : 'paragraphs';
const items = result.data[level] || [];
// Styling for the bounding boxes
ctx.strokeStyle = boxColor;
ctx.lineWidth = Number(lineWidth);
// Iterate through detected text items and draw boundary boxes
for (const item of items) {
const bbox = item.bbox;
if (bbox) {
const x = bbox.x0;
const y = bbox.y0;
const w = bbox.x1 - bbox.x0;
const h = bbox.y1 - bbox.y0;
// Draw Stroke
ctx.beginPath();
ctx.rect(x, y, w, h);
ctx.stroke();
// Draw semi-transparent highlighter fill
ctx.save();
ctx.globalAlpha = 0.15;
ctx.fillStyle = boxColor;
ctx.fill();
ctx.restore();
}
}
} catch (err) {
console.error("Text scanning error:", err);
// Draw error state onto canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(originalImg, 0, 0);
ctx.save();
ctx.fillStyle = "rgba(255, 0, 0, 0.7)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "white";
ctx.font = "bold " + Math.max(16, canvas.width / 25) + "px Arial, sans-serif";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText("Failed to scan for text boxes.", canvas.width / 2, canvas.height / 2);
ctx.restore();
}
})();
// Returns a canvas that actively updates as soon as processing completes
return canvas;
}
Apply Changes