You can edit the below JavaScript code to customize the image tool.
Apply Changes
/**
* Applies an MRI Scan Filter Effect to an image.
* @param {Image} originalImg - The original JavaScript Image object.
* @param {number} [contrastLevel=85] - Contrast level (0-100). 50 is neutral, >50 increases contrast, <50 decreases.
* @param {number} [brightnessShift=5] - Brightness adjustment (-50 to 50). Positive values brighten, negative darken.
* @param {number} [noiseIntensity=20] - Intensity of random noise (0-50). 0 means no noise.
* @param {number} [scanlineOpacity=0] - Opacity of scanlines (0-1). 0 disables scanlines.
* @param {number} [scanlineWidth=1] - Width of individual scanlines in pixels (1-5).
* @param {string} [tint="6090C0"] - Hex color string for tint (e.g., "6090C0" or "RRGGBB" or "RGB"). Empty string or null for no tint.
* @param {number} [tintStrength=0.2] - Strength of the tint (0-1). 0 means no tint effect.
* @returns {HTMLCanvasElement} A canvas element with the MRI effect applied.
*/
function processImage(originalImg, contrastLevel = 85, brightnessShift = 5, noiseIntensity = 20, scanlineOpacity = 0, scanlineWidth = 1, tint = "6090C0", tintStrength = 0.2) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d', { willReadFrequently: true }); // Optimization hint
const imgWidth = originalImg.naturalWidth || originalImg.width;
const imgHeight = originalImg.naturalHeight || originalImg.height;
if (imgWidth === 0 || imgHeight === 0) {
console.warn("Image dimensions are zero. Ensure the image is loaded before processing.");
// Return a minimal, possibly error-indicating canvas
canvas.width = 100;
canvas.height = 50;
ctx.fillStyle = "gray";
ctx.fillRect(0,0,canvas.width, canvas.height);
ctx.fillStyle = "white";
ctx.font = "10px Arial";
ctx.textAlign = "center";
ctx.fillText("Invalid Image", canvas.width/2, canvas.height/2);
return canvas;
}
canvas.width = imgWidth;
canvas.height = imgHeight;
try {
ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
} catch (e) {
console.error("Error drawing image to canvas. Ensure image is valid and loaded, and not cross-origin restricted.", e);
ctx.clearRect(0,0,canvas.width, canvas.height);
ctx.fillStyle = "red";
ctx.fillRect(0,0,canvas.width, canvas.height);
ctx.fillStyle = "white";
ctx.font = "12px Arial";
ctx.textAlign = "center";
ctx.fillText("Error: Could not draw image.", canvas.width/2, canvas.height/2 - 10);
ctx.fillText("Check CORS policy if loading remote image.", canvas.width/2, canvas.height/2 + 10);
return canvas;
}
let imageData;
try {
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
} catch (e) {
console.error("Error getting image data. Canvas might be tainted (cross-origin image without CORS).", e);
ctx.clearRect(0,0,canvas.width, canvas.height);
ctx.fillStyle = "orange";
ctx.fillRect(0,0,canvas.width, canvas.height);
ctx.fillStyle = "black";
ctx.font = "12px Arial";
ctx.textAlign = "center";
ctx.fillText("Error: Tainted Canvas", canvas.width/2, canvas.height/2 - 10);
ctx.fillText("Cannot process cross-origin image.", canvas.width/2, canvas.height/2 + 10);
return canvas;
}
const data = imageData.data;
function hexToRgb(hexStr) {
if (!hexStr || typeof hexStr !== 'string' || hexStr.trim() === "") return null;
let hex = hexStr.replace(/^#/, '');
if (!/^[0-9A-Fa-f]{3}$|^[0-9A-Fa-f]{6}$/.test(hex)) {
return null;
}
if (hex.length === 3) {
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
}
const bigint = parseInt(hex, 16);
return {
r: (bigint >> 16) & 255,
g: (bigint >> 8) & 255,
b: bigint & 255
};
}
const tintRgb = (tint && String(tint).trim() !== "") ? hexToRgb(String(tint)) : null;
const C_level = Math.max(0, Math.min(100, Number(contrastLevel)));
let C_param = (C_level - 50) * 2.55;
const F_contrast = (259 * (C_param + 255)) / (255 * (259 - C_param));
const B_shift = Math.max(-50, Math.min(50, Number(brightnessShift)));
const N_intensity = Math.max(0, Math.min(50, Number(noiseIntensity)));
const T_strength = Math.max(0, Math.min(1, Number(tintStrength)));
for (let i = 0; i < data.length; i += 4) {
const r = data[i];
const g = data[i + 1];
const b = data[i + 2];
let gray = 0.299 * r + 0.587 * g + 0.114 * b;
gray += B_shift;
gray = Math.max(0, Math.min(255, gray));
gray = F_contrast * (gray - 128) + 128;
gray = Math.max(0, Math.min(255, gray));
if (N_intensity > 0) {
const noise = (Math.random() - 0.5) * N_intensity;
gray += noise;
gray = Math.max(0, Math.min(255, gray));
}
let finalR = gray;
let finalG = gray;
let finalB = gray;
if (tintRgb && T_strength > 0) {
finalR = (1 - T_strength) * gray + T_strength * tintRgb.r;
finalG = (1 - T_strength) * gray + T_strength * tintRgb.g;
finalB = (1 - T_strength) * gray + T_strength * tintRgb.b;
}
data[i] = Math.max(0, Math.min(255, Math.round(finalR)));
data[i + 1] = Math.max(0, Math.min(255, Math.round(finalG)));
data[i + 2] = Math.max(0, Math.min(255, Math.round(finalB)));
}
ctx.putImageData(imageData, 0, 0);
const SL_opacity = Math.max(0, Math.min(1, Number(scanlineOpacity)));
const SL_width = Math.max(1, Math.min(5, Math.round(Number(scanlineWidth))));
if (SL_opacity > 0 && SL_width > 0) {
ctx.fillStyle = `rgba(0, 0, 0, ${SL_opacity})`;
for (let y = 0; y < canvas.height; y += SL_width * 2) {
ctx.fillRect(0, y, canvas.width, SL_width);
}
}
return canvas;
}
Apply Changes