You can edit the below JavaScript code to customize the image tool.
/**
* Finds potential logos or watermarks in the corners of an image using a heuristic approach.
* This function analyzes the four corners of the image for a cluster of pixels that
* stand out from the local background color. It then draws a red bounding box
* around any area it identifies as a potential logo.
* Note: This is not a machine learning model and works best for distinct logos/watermarks
* placed near the corners of an image.
*
* @param {Image} originalImg The javascript Image object to process.
* @param {number} [cornerSize=0.3] The fraction of the image's dimensions to consider as a "corner" area.
* For example, 0.3 means it will analyze a region 30% of the image's
* width and height in each corner. Value is clamped between 0.1 and 0.5.
* @param {number} [threshold=35] The color difference sensitivity required to consider a pixel part of a logo.
* A lower value is more sensitive to subtle color changes.
* Value is clamped between 1 and 255.
* @returns {Promise<HTMLCanvasElement>} A Promise that resolves with a new canvas element
* featuring the original image with red boxes drawn around found logos.
*/
async function processImage(originalImg, cornerSize = 0.3, threshold = 35) {
// 1. Parameter validation and clamping to safe/reasonable values.
const safeCornerSize = Math.max(0.1, Math.min(0.5, cornerSize));
const safeThreshold = Math.max(1, Math.min(255, threshold));
// 2. Set up the canvas.
const canvas = document.createElement('canvas');
// The 'willReadFrequently' hint can improve performance for getImageData calls.
const ctx = canvas.getContext('2d', {
willReadFrequently: true
});
canvas.width = originalImg.width;
canvas.height = originalImg.height;
// First, draw the original image onto the canvas, which we will then draw over.
ctx.drawImage(originalImg, 0, 0);
// 3. Define the corner regions to analyze based on the cornerSize parameter.
const w = canvas.width;
const h = canvas.height;
const cornerW = Math.floor(w * safeCornerSize);
const cornerH = Math.floor(h * safeCornerSize);
const regions = [
// Format: [x, y, width, height]
[0, 0, cornerW, cornerH], // Top-left corner
[w - cornerW, 0, cornerW, cornerH], // Top-right corner
[0, h - cornerH, cornerW, cornerH], // Bottom-left corner
[w - cornerW, h - cornerH, cornerW, cornerH] // Bottom-right corner
];
// Helper function to calculate the "distance" between two RGB colors.
const getColorDifference = (r1, g1, b1, r2, g2, b2) => {
return Math.sqrt(Math.pow(r1 - r2, 2) + Math.pow(g1 - g2, 2) + Math.pow(b1 - b2, 2));
};
const foundBoxes = [];
// 4. Analyze each region for a potential logo.
for (const [rx, ry, rw, rh] of regions) {
// Skip analysis if the region is too small to be meaningful.
if (rw < 10 || rh < 10) continue;
const imageData = ctx.getImageData(rx, ry, rw, rh);
const data = imageData.data;
// Determine a representative background color by averaging the four extreme corner pixels of the region.
// This is more robust against noise than sampling a single pixel.
const p1 = 0; // Top-left pixel of the region
const p2 = (rw - 1) * 4; // Top-right
const p3 = (rh - 1) * rw * 4; // Bottom-left
const p4 = ((rh - 1) * rw + (rw - 1)) * 4; // Bottom-right
const bgR = (data[p1] + data[p2] + data[p3] + data[p4]) / 4;
const bgG = (data[p1 + 1] + data[p2 + 1] + data[p3 + 1] + data[p4 + 1]) / 4;
const bgB = (data[p1 + 2] + data[p2 + 2] + data[p3 + 2] + data[p4 + 2]) / 4;
let minX = rw, minY = rh, maxX = -1, maxY = -1;
let hasForegroundPixels = false;
// Iterate through each pixel of the region to find ones that differ from the background.
for (let y = 0; y < rh; y++) {
for (let x = 0; x < rw; x++) {
const i = (y * rw + x) * 4;
const r = data[i];
const g = data[i + 1];
const b = data[i + 2];
const a = data[i + 3];
// A pixel is considered part of the foreground (logo) if it's mostly opaque
// and its color is significantly different from the calculated background color.
if (a > 128 && getColorDifference(r, g, b, bgR, bgG, bgB) > safeThreshold) {
minX = Math.min(minX, x);
minY = Math.min(minY, y);
maxX = Math.max(maxX, x);
maxY = Math.max(maxY, y);
hasForegroundPixels = true;
}
}
}
// If any foreground pixels were found, calculate their bounding box.
if (hasForegroundPixels) {
const boxW = maxX - minX;
const boxH = maxY - minY;
const boxArea = boxW * boxH;
const regionArea = rw * rh;
// Filter out boxes that are too small (likely noise) or too large (likely a failed
// background detection that highlighted most of the region).
if (boxW > 5 && boxH > 5 && boxArea < (regionArea * 0.9)) {
foundBoxes.push({
x: rx + minX,
y: ry + minY,
w: boxW,
h: boxH
});
}
}
}
// 5. Draw the identified bounding boxes onto the canvas.
if (foundBoxes.length > 0) {
ctx.strokeStyle = '#FF0000';
// Use a dynamic line width relative to the image size for better visibility.
ctx.lineWidth = Math.max(2, Math.min(w, h) * 0.005);
ctx.fillStyle = 'rgba(255, 0, 0, 0.2)';
for (const box of foundBoxes) {
ctx.beginPath();
ctx.rect(box.x, box.y, box.w, box.h);
ctx.stroke();
ctx.fill();
}
}
// 6. Return the final canvas with the modifications.
return canvas;
}
Free Image Tool Creator
Can't find the image tool you're looking for? Create one based on your own needs now!
The Image Logo Finder is a tool designed to identify potential logos or watermarks located in the corners of an image. Using a heuristic approach, it analyzes the image’s four corners to detect clusters of pixels that stand out from the surrounding background colors. When a logo or watermark is identified, the tool highlights the area with a red bounding box. This utility is particularly useful for graphic designers, content creators, or anyone needing to detect branding elements in images for copyright enforcement, asset management, or analysis of visual content.