You can edit the below JavaScript code to customize the image tool.
function processImage(originalImg, threshold = 128) {
// It's recommended that originalImg is fully loaded before calling this function.
// For example, by using it inside originalImg.onload = () => { ... }
// or checking if originalImg.complete is true. If the image is not loaded,
// its dimensions might be 0, and an error canvas will be returned.
const canvas = document.createElement('canvas');
// Optimization hint for frequent read/write, standard in modern browsers.
// Error if context cannot be obtained is not handled here, highly unlikely for '2d'.
const ctx = canvas.getContext('2d', { willReadFrequently: true });
// Use naturalWidth/Height for intrinsic dimensions if available (typical for HTMLImageElement after loading).
// Fallback to width/height for other CanvasImageSource types or if natural dimensions aren't set.
canvas.width = originalImg.naturalWidth || originalImg.width;
canvas.height = originalImg.naturalHeight || originalImg.height;
// Check for valid dimensions.
if (canvas.width === 0 || canvas.height === 0) {
console.error("Image has zero dimensions. Ensure it is loaded and valid before processing.");
// Return a small canvas with an error message.
const errCanvas = document.createElement('canvas');
// Use Math.max to ensure a minimum size for the error message, even if canvas.width/height are 0.
errCanvas.width = Math.max(250, canvas.width);
errCanvas.height = Math.max(50, canvas.height);
const errCtx = errCanvas.getContext('2d');
errCtx.fillStyle = 'lightgray';
errCtx.fillRect(0, 0, errCanvas.width, errCanvas.height);
errCtx.fillStyle = 'red';
errCtx.font = '12px Arial';
errCtx.textAlign = 'center';
errCtx.textBaseline = 'middle';
errCtx.fillText('Error: Image has 0 dimensions or is not loaded.', errCanvas.width / 2, errCanvas.height / 2);
return errCanvas;
}
try {
ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
} catch (e) {
// This can happen if originalImg is unloadable, corrupt, or an invalid CanvasImageSource.
console.error("Error drawing image to canvas:", e);
const errCanvas = document.createElement('canvas');
// Use actual canvas dimensions if they were determined, otherwise a default size.
errCanvas.width = canvas.width || 200;
errCanvas.height = canvas.height || 50;
const errCtx = errCanvas.getContext('2d');
errCtx.fillStyle = 'lightgray';
errCtx.fillRect(0, 0, errCanvas.width, errCanvas.height);
errCtx.fillStyle = 'red';
// Responsive font size for the error message.
const fontSize = Math.max(12, Math.min(errCanvas.width / 15, errCanvas.height / 3));
errCtx.font = `bold ${fontSize}px Arial`;
errCtx.textAlign = 'center';
errCtx.textBaseline = 'middle';
errCtx.fillText('Error drawing source image.', errCanvas.width / 2, errCanvas.height / 2);
return errCanvas;
}
let imageData;
try {
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
} catch (e) {
// This typically occurs due to security restrictions (CORS) for cross-origin images.
console.warn("Could not get ImageData (e.g., due to CORS policy):", e.message);
// Draw an error message on the canvas itself, over the original image.
// The original image is displayed, but the filter cannot be applied.
ctx.fillStyle = 'rgba(0, 0, 0, 0.7)'; // Semi-transparent dark overlay
const rectHeight = Math.min(canvas.height, Math.max(60, canvas.height * 0.2)); // Dynamic height for the message box
ctx.fillRect(0, canvas.height / 2 - rectHeight / 2, canvas.width, rectHeight);
ctx.fillStyle = 'white';
const fontSize = Math.max(12, Math.min(canvas.width / 20, rectHeight / 3)); // Responsive font size
ctx.font = `bold ${fontSize}px Arial`;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
const textLine1 = "Filter not applied due to security restrictions (CORS).";
const textLine2 = "Original image shown.";
if (rectHeight < fontSize * 2.5 && canvas.width < ctx.measureText(textLine1).width * 1.1) {
ctx.fillText("Filter disabled (CORS).", canvas.width / 2, canvas.height / 2);
} else if (rectHeight < fontSize * 2.5) {
ctx.fillText(textLine1, canvas.width / 2, canvas.height / 2);
}
else {
ctx.fillText(textLine1, canvas.width / 2, canvas.height / 2 - fontSize * 0.7);
ctx.fillText(textLine2, canvas.width / 2, canvas.height / 2 + fontSize * 0.7);
}
return canvas; // Return the canvas with the original image and an error message
}
const data = imageData.data;
// Ensure threshold is a number.
let parsedThreshold = Number(threshold);
// Handle specific cases for threshold input:
// If threshold is an empty string, Number("") results in 0. User might intend default.
if (typeof threshold === 'string' && threshold.trim() === "") {
parsedThreshold = 128;
} else if (isNaN(parsedThreshold)) { // Catches non-numeric strings like "abc"
parsedThreshold = 128;
}
// Clamp threshold to the valid 0-255 range.
parsedThreshold = Math.max(0, Math.min(255, parsedThreshold));
for (let i = 0; i < data.length; i += 4) {
const r = data[i];
const g = data[i+1];
const b = data[i+2];
const a = data[i+3];
// If the pixel is fully transparent, preserve its original color and transparency.
if (a === 0) {
continue;
}
// Calculate luminance using the standard BT.601 formula.
// L = 0.299*R + 0.587*G + 0.114*B
const luminance = 0.299 * r + 0.587 * g + 0.114 * b;
// Apply threshold: if luminance is above or equal, set to white (255), else black (0).
const outputValue = (luminance >= parsedThreshold) ? 255 : 0;
data[i] = outputValue; // Red channel
data[i+1] = outputValue; // Green channel
data[i+2] = outputValue; // Blue channel
// data[i+3] = a; // Alpha channel is preserved implicitly (or explicitly if a === 0 condition is removed)
}
// Put the modified pixel data back onto the canvas.
ctx.putImageData(imageData, 0, 0);
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 Threshold Dither Filter is a tool that applies a thresholding effect to images, converting them to black and white based on luminance levels. Users can adjust the threshold level to determine which parts of the image become black or white. This tool is useful for creating high-contrast images, preparing images for printing, enhancing visibility for certain applications, or generating unique artistic effects. Potential use cases include graphic design, document preparation, or simply for creating interesting visual content.