You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(
originalImg,
desaturationLevel = 0.9, // Number: 0.0 (original color) to 1.0 (full grayscale)
contrastLevel = 1.8, // Number: Multiplier. 1.0 means no change. >1 increases contrast. Sensible range e.g. 0 to 3.
brightnessOffset = -10, // Number: Additive brightness. E.g. -255 to 255. 0 means no change.
tintEffect = "steel", // String: "none", "steel", "bronze", "rust"
tintStrengthLevel = 0.2 // Number: 0.0 (no tint) to 1.0 (full tint color influence)
) {
// 1. Canvas setup
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Ensure the image is loaded, otherwise width/height might be 0
const imgWidth = originalImg.naturalWidth || originalImg.width;
const imgHeight = originalImg.naturalHeight || originalImg.height;
canvas.width = imgWidth;
canvas.height = imgHeight;
// Draw the original image onto the canvas
ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
// If canvas is 0x0, return empty canvas
if (canvas.width === 0 || canvas.height === 0) {
return canvas;
}
// 2. Get image data
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;
// 3. Define tint colors (RGB 0-255)
const tintColors = {
steel: { r: 150, g: 160, b: 170 }, // Cool, slightly bluish light gray
bronze: { r: 170, g: 130, b: 100 }, // Warm, brownish-yellowish
rust: { r: 180, g: 70, b: 30 } // Orangey-brown, like oxidized iron
};
const selectedTintColor = tintColors[tintEffect];
// Ensure parameters are within sensible bounds for stability if needed, though defaults are fine.
// desaturationLevel should be [0, 1]
desaturationLevel = Math.max(0, Math.min(1, desaturationLevel));
// tintStrengthLevel should be [0, 1]
tintStrengthLevel = Math.max(0, Math.min(1, tintStrengthLevel));
// contrastLevel should be >= 0
contrastLevel = Math.max(0, contrastLevel);
// 4. Pixel loop
for (let i = 0; i < data.length; i += 4) {
let r = data[i];
let g = data[i+1];
let b = data[i+2];
// a. Brightness adjustment
if (brightnessOffset !== 0) {
r += brightnessOffset;
g += brightnessOffset;
b += brightnessOffset;
// Clamp to 0-255
r = Math.max(0, Math.min(255, r));
g = Math.max(0, Math.min(255, g));
b = Math.max(0, Math.min(255, b));
}
// b. Desaturation
if (desaturationLevel > 0) {
// Standard luminance calculation
const gray = 0.299 * r + 0.587 * g + 0.114 * b;
// Interpolate between original color and grayscale
r = r * (1 - desaturationLevel) + gray * desaturationLevel;
g = g * (1 - desaturationLevel) + gray * desaturationLevel;
b = b * (1 - desaturationLevel) + gray * desaturationLevel;
// No clamping needed here as r,g,b,gray are 0-255 and it's a weighted average.
// Ensure integer values for next steps
r = Math.round(r);
g = Math.round(g);
b = Math.round(b);
}
// c. Contrast adjustment
if (contrastLevel !== 1.0) {
r = (r - 128) * contrastLevel + 128;
g = (g - 128) * contrastLevel + 128;
b = (b - 128) * contrastLevel + 128;
// Clamp to 0-255
r = Math.max(0, Math.min(255, Math.round(r)));
g = Math.max(0, Math.min(255, Math.round(g)));
b = Math.max(0, Math.min(255, Math.round(b)));
}
// d. Metallic Tint
if (tintEffect !== "none" && selectedTintColor && tintStrengthLevel > 0) {
r = r * (1 - tintStrengthLevel) + selectedTintColor.r * tintStrengthLevel;
g = g * (1 - tintStrengthLevel) + selectedTintColor.g * tintStrengthLevel;
b = b * (1 - tintStrengthLevel) + selectedTintColor.b * tintStrengthLevel;
// Clamp and round to 0-255
r = Math.max(0, Math.min(255, Math.round(r)));
g = Math.max(0, Math.min(255, Math.round(g)));
b = Math.max(0, Math.min(255, Math.round(b)));
}
// Assign new values
data[i] = r;
data[i+1] = g;
data[i+2] = b;
// Alpha (data[i+3]) remains unchanged
}
// 5. Put modified image data back to canvas
ctx.putImageData(imageData, 0, 0);
// 6. Return canvas
return canvas;
}
Apply Changes