You can edit the below JavaScript code to customize the image tool.
function processImage(originalImg, colorStr = "255,255,255") {
// Helper function to parse color string (e.g., "r,g,b", "#RRGGBB", "RRGGBB", "#RGB", "RGB")
// Defaults to R=255, G=255, B=255 if parsing fails or input is invalid/empty.
// This default (white as target) will make the monochrome filter produce a grayscale image.
function _parseMonochromeTargetColor(inputColorStr) {
let r = 255, g = 255, b = 255; // Default: white (results in grayscale)
// Handle cases where inputColorStr is not a string or is an empty/whitespace string
if (typeof inputColorStr !== 'string' || inputColorStr.trim() === "") {
// This path is taken if colorStr was not provided to processImage (which means it uses its default "255,255,255"),
// or if it was explicitly null, undefined, or an empty/whitespace string.
// No warning needed here, just use the already set default {r:255, g:255, b:255}.
return { r, g, b };
}
const trimmedStr = inputColorStr.trim().toLowerCase();
// Try parsing "r,g,b" format
if (trimmedStr.includes(',')) {
const parts = trimmedStr.split(',');
if (parts.length === 3) {
const pr = parseInt(parts[0], 10);
const pg = parseInt(parts[1], 10);
const pb = parseInt(parts[2], 10);
// Check if all parts were valid numbers
if (!isNaN(pr) && !isNaN(pg) && !isNaN(pb)) {
// Clamp values to 0-255 range
r = Math.max(0, Math.min(255, pr));
g = Math.max(0, Math.min(255, pg));
b = Math.max(0, Math.min(255, pb));
return { r, g, b };
}
}
} else { // Try parsing hex format
let hex = trimmedStr;
if (hex.startsWith('#')) {
hex = hex.substring(1);
}
// Check if it's a valid hex string (consists of hex characters)
if (/^[0-9a-f]+$/.test(hex)) { // Test against lowercase hex
if (hex.length === 6) { // RRGGBB
r = parseInt(hex.substring(0, 2), 16);
g = parseInt(hex.substring(2, 4), 16);
b = parseInt(hex.substring(4, 6), 16);
return { r, g, b };
} else if (hex.length === 3) { // RGB
r = parseInt(hex.charAt(0) + hex.charAt(0), 16);
g = parseInt(hex.charAt(1) + hex.charAt(1), 16);
b = parseInt(hex.charAt(2) + hex.charAt(2), 16);
return { r, g, b };
}
}
}
// If parsing failed for a non-empty, non-null, string that wasn't recognized
console.warn(`Invalid color string format: "${inputColorStr}". Defaulting to monochrome target R=255,G=255,B=255 (this will result in a grayscale image).`);
return { r: 255, g: 255, b: 255 }; // Return default for parsing failure
}
const targetColor = _parseMonochromeTargetColor(colorStr);
const TR = targetColor.r;
const TG = targetColor.g;
const TB = targetColor.b;
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
if (!ctx) {
// This should not happen in modern browsers that support canvas.
console.error("Canvas 2D context is not available. This tool requires a browser with Canvas support.");
const errorElement = document.createElement('p');
errorElement.textContent = "Error: Canvas 2D context is not supported in your browser.";
return errorElement;
}
// Use naturalWidth/Height for actual image dimensions, fallback to width/height
// This ensures we process the image at its native resolution if available.
const imgWidth = originalImg.naturalWidth || originalImg.width;
const imgHeight = originalImg.naturalHeight || originalImg.height;
// Handle cases where the image might not be loaded or has no dimensions
if (imgWidth === 0 || imgHeight === 0) {
console.warn("Input image has zero width or height. This might be due to the image not being fully loaded or an invalid image source. Returning an empty canvas.");
canvas.width = 0;
canvas.height = 0;
return canvas; // Return an empty but valid canvas
}
canvas.width = imgWidth;
canvas.height = imgHeight;
// Draw the original image onto the canvas
ctx.drawImage(originalImg, 0, 0, imgWidth, imgHeight);
let imageData;
try {
// Get pixel data from the canvas
imageData = ctx.getImageData(0, 0, imgWidth, imgHeight);
} catch (e) {
// This error can occur if the canvas is "tainted", e.g., by drawing a cross-origin image
// without proper CORS headers.
console.error("Failed to get image data from canvas. This may be due to cross-origin restrictions (CORS). Error: ", e.message);
const errorElement = document.createElement('p');
// Provide mildly more informative error message for display.
errorElement.innerHTML = `Error processing image: Could not access pixel data. <br>If you are using an image from another website, please ensure it allows cross-origin access. <br><small>Technical details: ${e.message}</small>`;
return errorElement;
}
const data = imageData.data; // This is a Uint8ClampedArray: [R,G,B,A, R,G,B,A, ...]
// Iterate over each pixel (each pixel is 4 components: R,G,B,A)
for (let i = 0; i < data.length; i += 4) {
const r = data[i]; // Red component of the original pixel
const g = data[i + 1]; // Green component
const b = data[i + 2]; // Blue component
const a = data[i + 3]; // Alpha (opacity) component
// Calculate luminance using the standard Rec. 601 formula (commonly used for NTSC color perception)
// L = 0.299*R + 0.587*G + 0.114*B
// Luminance effectively represents the brightness of the pixel.
const luminance = (0.299 * r + 0.587 * g + 0.114 * b);
// The new color for the pixel will be shades of the targetColor,
// scaled by the luminance of the original pixel.
// (luminance / 255) gives a scaling factor between 0 (for black) and 1 (for white).
data[i] = Math.round((luminance / 255) * TR); // New Red
data[i+1] = Math.round((luminance / 255) * TG); // New Green
data[i+2] = Math.round((luminance / 255) * TB); // New Blue
// Alpha channel is preserved from the original image
data[i+3] = a;
}
// Write the modified pixel data back to 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 Monochrome Color Filter Application allows users to apply a monochrome color filter to images, converting them into shades of a selected color. By specifying a target color, either in RGB format or hex code, users can customize the monochrome effect, which is useful for artistic editing, branding visuals, or creating thematic images. The tool automatically defaults to a grayscale filter if no target color is provided. This can be particularly advantageous for graphic designers, photographers, and content creators looking to enhance their imagery with a distinct monochrome style.