You can edit the below JavaScript code to customize the image tool.
function processImage(originalImg, contrast = 2.0, brightness = 0, invertColors = 0, tintColor = "none") {
// Helper function to parse color strings (hex, named, rgb, etc.)
// Returns an object {r, g, b} or null if parsing fails or color is "none".
function _parseColor(colorStr) {
// Ensure colorStr is a string and not "none" or empty/whitespace.
if (!colorStr || typeof colorStr !== 'string' || String(colorStr).trim().toLowerCase() === 'none' || String(colorStr).trim() === '') {
return null;
}
// Coerce to string, useful if, for example, a number like 0xff0000 was passed (though parameters are typed by default values).
colorStr = String(colorStr);
// Use a dummy element to leverage the browser's CSS color parsing.
// This is a common and fairly robust method.
const el = document.createElement('div');
el.style.color = colorStr;
// The element must be in the document for getComputedStyle to work reliably across all browsers/scenarios.
document.body.appendChild(el);
const computedColor = window.getComputedStyle(el).color;
document.body.removeChild(el);
// getComputedStyle returns colors in 'rgb(r, g, b)' or 'rgba(r, g, b, a)' format.
// Example: "blue" -> "rgb(0, 0, 255)"; "#FF0000" -> "rgb(255, 0, 0)"; "invalid-color" -> often "rgba(0, 0, 0, 0)" or parent's color.
const match = computedColor.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*[\d\.]+)?\)/);
if (match) {
const r = parseInt(match[1]);
const g = parseInt(match[2]);
const b = parseInt(match[3]);
// If an invalid color string results in transparent black (rgba(0,0,0,0)),
// this will effectively be treated as a black tint ({r:0, g:0, b:0}), which is acceptable.
return { r: r, g: g, b: b };
}
return null; // Color string could not be parsed by the browser.
}
const canvas = document.createElement('canvas');
// Use naturalWidth/Height for the original image dimensions.
// Assumes originalImg is a loaded HTMLImageElement.
canvas.width = originalImg.naturalWidth;
canvas.height = originalImg.naturalHeight;
const ctx = canvas.getContext('2d');
if (!ctx) {
// Fallback or error if context cannot be retrieved (e.g. unsupported environment)
console.error("Unable to get 2D context");
return canvas; // Return an empty canvas
}
ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
let imageData;
try {
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
} catch (e) {
// This can happen if the canvas is tainted (e.g., drawing a cross-origin image without CORS)
console.error("Error getting imageData, canvas may be tainted: ", e);
ctx.font = "12px Arial";
ctx.fillStyle = "red";
ctx.textAlign = "center";
ctx.fillText("Error: Cannot process cross-origin image.", canvas.width / 2, canvas.height / 2);
return canvas; // Return canvas with error message
}
const data = imageData.data;
const parsedTint = _parseColor(tintColor);
// Ensure numeric types for parameters, applying defaults if needed.
const numContrast = Number(contrast);
const numBrightness = Number(brightness);
const doInvert = Number(invertColors) === 1;
for (let i = 0; i < data.length; i += 4) {
const r = data[i];
const g = data[i + 1];
const b = data[i + 2];
// 1. Convert to grayscale (luminosity method for perceptual brightness)
let gray = 0.299 * r + 0.587 * g + 0.114 * b;
// 2. Apply contrast and brightness
// Formula: newValue = factor * (oldValue - 128) + 128 + brightnessOffset
// This centers the contrast adjustment around mid-gray (128).
gray = numContrast * (gray - 128) + 128 + numBrightness;
// Clip values to the valid 0-255 range
gray = Math.max(0, Math.min(255, gray));
// 3. Invert colors if specified
if (doInvert) {
gray = 255 - gray;
}
// 4. Apply tint color if specified and parsed successfully
if (parsedTint) {
// Colorize: The grayscale value scales the tint color.
// Bright areas of the (potentially inverted) grayscale image become the tint color.
// Dark areas become black.
data[i] = (gray / 255) * parsedTint.r;
data[i + 1] = (gray / 255) * parsedTint.g;
data[i + 2] = (gray / 255) * parsedTint.b;
} else {
// No tint or invalid tint color: apply the calculated grayscale value to R, G, B channels.
data[i] = gray;
data[i + 1] = gray;
data[i + 2] = gray;
}
// Alpha channel (data[i + 3]) remains unchanged.
}
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 Medical Chart Filter Effect Tool allows users to apply a medical chart-style filter effect to their images. This includes converting the images to grayscale, adjusting contrast and brightness, inverting colors, and adding a tint color. This tool can be useful for medical professionals who wish to create visually distinct medical charts, presentations, or informative graphics from standard images, enhancing visual communication in medical documentation and education.