You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, searchTopic = "1C", gridCols = 3, gridRows = 3, highlightColor = "rgba(255, 204, 0, 0.4)") {
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
const barHeight = 60;
canvas.width = originalImg.width;
canvas.height = originalImg.height + barHeight;
// Draw the original image onto the canvas
ctx.drawImage(originalImg, 0, 0);
// Parse the grid configuration
const topic = String(searchTopic).trim();
let cols = parseInt(gridCols) || 3;
let rows = parseInt(gridRows) || 3;
cols = Math.max(1, cols);
rows = Math.max(1, rows);
// Determine if the search topic is a grid reference (e.g., "1C", "A3")
const match = topic.toUpperCase().match(/^([A-Z]+)([0-9]+)$|^([0-9]+)([A-Z]+)$/);
let isGridSearch = false;
let targetRow = -1;
let targetCol = -1;
if (match) {
const cStr = match[1] || match[4];
const rStr = match[2] || match[3];
let cIdx = 0;
for (let i = 0; i < cStr.length; i++) {
cIdx = cIdx * 26 + (cStr.charCodeAt(i) - 64);
}
cIdx -= 1; // 0-based column index
const rIdx = parseInt(rStr) - 1; // 0-based row index
if (cIdx >= 0 && cIdx < cols && rIdx >= 0 && rIdx < rows) {
isGridSearch = true;
targetCol = cIdx;
targetRow = rIdx;
}
}
// Helper function to draw a scanning reticle (corners)
function drawReticle(x, y, cw, ch) {
let len = Math.min(cw, ch) * 0.15;
if (len < 10) len = 10;
if (len > 40) len = 40;
ctx.strokeStyle = "#FFCC00";
ctx.lineWidth = Math.max(2, Math.min(cw, ch) * 0.02);
if (ctx.lineWidth > 6) ctx.lineWidth = 6;
// Top-Left
ctx.beginPath(); ctx.moveTo(x, y + len); ctx.lineTo(x, y); ctx.lineTo(x + len, y); ctx.stroke();
// Top-Right
ctx.beginPath(); ctx.moveTo(x + cw - len, y); ctx.lineTo(x + cw, y); ctx.lineTo(x + cw, y + len); ctx.stroke();
// Bottom-Right
ctx.beginPath(); ctx.moveTo(x + cw, y + ch - len); ctx.lineTo(x + cw, y + ch); ctx.lineTo(x + cw - len, y + ch); ctx.stroke();
// Bottom-Left
ctx.beginPath(); ctx.moveTo(x + len, y + ch); ctx.lineTo(x, y + ch); ctx.lineTo(x, y + ch - len); ctx.stroke();
}
// Helper function to get alphabetical column labels (A, B, C...)
function getColName(index) {
let name = "";
let temp = index;
while (temp >= 0) {
name = String.fromCharCode((temp % 26) + 65) + name;
temp = Math.floor(temp / 26) - 1;
}
return name;
}
// Apply visual processing overlay based on the selected "Topic" interpretation
if (isGridSearch) {
const cellW = originalImg.width / cols;
const cellH = originalImg.height / rows;
// Draw Full Analytical Grid
ctx.strokeStyle = "rgba(255, 255, 255, 0.4)";
ctx.lineWidth = 1;
for (let c = 1; c < cols; c++) {
ctx.beginPath(); ctx.moveTo(c * cellW, 0); ctx.lineTo(c * cellW, originalImg.height); ctx.stroke();
}
for (let r = 1; r < rows; r++) {
ctx.beginPath(); ctx.moveTo(0, r * cellH); ctx.lineTo(originalImg.width, r * cellH); ctx.stroke();
}
// Add Grid Labels
ctx.save();
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.font = `bold ${Math.max(12, Math.min(24, cellH * 0.2))}px Arial, sans-serif`;
ctx.fillStyle = "rgba(255, 255, 255, 0.9)";
ctx.shadowColor = "#000000";
ctx.shadowBlur = 4;
ctx.shadowOffsetX = 1;
ctx.shadowOffsetY = 1;
for (let c = 0; c < cols; c++) {
ctx.fillText(getColName(c), c * cellW + cellW / 2, Math.min(20, cellH * 0.3));
}
for (let r = 0; r < rows; r++) {
ctx.fillText(r + 1, Math.min(20, cellW * 0.3), r * cellH + cellH / 2);
}
ctx.restore();
// Highlight targeted grid cell
const cX = targetCol * cellW;
const cY = targetRow * cellH;
ctx.fillStyle = highlightColor;
ctx.fillRect(cX, cY, cellW, cellH);
drawReticle(cX, cY, cellW, cellH);
} else {
// Fallback: Treat as a general Image Search Topic and highlight the structural center
const bW = originalImg.width * 0.5;
const bH = originalImg.height * 0.5;
const bX = (originalImg.width - bW) / 2;
const bY = (originalImg.height - bH) / 2;
ctx.fillStyle = highlightColor;
ctx.fillRect(bX, bY, bW, bH);
drawReticle(bX, bY, bW, bH);
ctx.save();
ctx.fillStyle = "#fff";
ctx.font = `bold ${Math.max(14, Math.min(30, bH * 0.1))}px Arial, sans-serif`;
ctx.shadowColor = "#000";
ctx.shadowBlur = 5;
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(topic.toUpperCase(), bX + bW / 2, bY + bH / 2);
ctx.restore();
}
// Render Bottom UI Header (The Search Tool interface bar)
ctx.fillStyle = "#1e1e1e";
ctx.fillRect(0, originalImg.height, canvas.width, barHeight);
// Draw Vector Magnifying Glass
const iconX = 30;
const iconY = originalImg.height + 30;
ctx.strokeStyle = "#FFCC00";
ctx.lineWidth = 3;
ctx.beginPath();
ctx.arc(iconX, iconY - 3, 9, 0, Math.PI * 2);
ctx.moveTo(iconX + 6, iconY + 3);
ctx.lineTo(iconX + 15, iconY + 12);
ctx.stroke();
// Contextual Text
ctx.fillStyle = "#ffffff";
ctx.font = "bold 20px Arial, sans-serif";
ctx.textBaseline = "middle";
ctx.textAlign = "left";
ctx.fillText("Topic Search: " + topic, iconX + 30, iconY);
const statusText = isGridSearch ? "[ Sector Focused ]" : "[ Subject Analyzed ]";
ctx.font = "16px Arial, monospace";
ctx.fillStyle = "#4CAF50";
ctx.textAlign = "right";
ctx.fillText(statusText, canvas.width - 20, iconY);
return canvas;
}
Apply Changes