You can edit the below JavaScript code to customize the image tool.
Apply Changes
async function processImage(originalImg, desaturationAmount = 0.3, contrastAdjust = 0.8, brightnessAdjust = 1.05, sereneColorTintStr = "200,220,240", tintStrength = 0.15) {
// 1. Parse sereneColorTintStr into R, G, B values
let R_tint = 200, G_tint = 220, B_tint = 240; // Default serene color
if (typeof sereneColorTintStr === 'string') {
const parsedRGB = sereneColorTintStr.split(',').map(Number);
if (parsedRGB.length === 3 && parsedRGB.every(num => !isNaN(num) && num >= 0 && num <= 255)) {
[R_tint, G_tint, B_tint] = parsedRGB;
} else {
console.warn("Invalid sereneColorTintStr format or values. Using default tint: " + sereneColorTintStr);
}
} else {
console.warn("sereneColorTintStr is not a string. Using default tint.");
}
// 2. Create a canvas
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d', { willReadFrequently: true }); // willReadFrequently for performance with getImageData/putImageData
// 3. Set canvas dimensions
// Use naturalWidth/Height for intrinsic dimensions, fallback to width/height
const imgWidth = originalImg.naturalWidth || originalImg.width;
const imgHeight = originalImg.naturalHeight || originalImg.height;
if (imgWidth === 0 || imgHeight === 0) {
console.error("Image has zero dimensions. Ensure the image is loaded and valid.");
// Return a small error canvas or throw an error
canvas.width = 100;
canvas.height = 50;
ctx.fillStyle = 'red';
ctx.font = '12px Arial';
ctx.fillText('Invalid Image', 10, 30);
return canvas;
}
canvas.width = imgWidth;
canvas.height = imgHeight;
// 4. Draw the original image onto the canvas
ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
// 5. Get the image data
let imageData;
try {
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
} catch (e) {
console.error("Could not get image data, possibly due to cross-origin restrictions:", e);
// Create an error message canvas
const errorCanvas = document.createElement('canvas');
errorCanvas.width = Math.max(200, canvas.width); // Use canvas dimensions if available
errorCanvas.height = Math.max(100, canvas.height);
const errorCtx = errorCanvas.getContext('2d');
errorCtx.fillStyle = 'lightgray';
errorCtx.fillRect(0, 0, errorCanvas.width, errorCanvas.height);
errorCtx.fillStyle = 'red';
errorCtx.font = '16px Arial';
errorCtx.textAlign = 'center';
errorCtx.textBaseline = 'middle';
const lines = ["Error processing image.", "(Cross-origin issue?)"];
lines.forEach((line, index) => {
errorCtx.fillText(line, errorCanvas.width / 2, errorCanvas.height / 2 + (index * 20) - (lines.length-1)*10 );
});
return errorCanvas;
}
const data = imageData.data;
// 6. Iterate through the pixels and apply the filter
for (let i = 0; i < data.length; i += 4) {
let r = data[i];
let g = data[i + 1];
let b = data[i + 2];
// a. Apply brightness adjustment
if (brightnessAdjust !== 1.0) {
r *= brightnessAdjust;
g *= brightnessAdjust;
b *= brightnessAdjust;
}
// b. Apply contrast adjustment
if (contrastAdjust !== 1.0) {
const mid = 127.5; // Midpoint for 0-255 range
r = (r - mid) * contrastAdjust + mid;
g = (g - mid) * contrastAdjust + mid;
b = (b - mid) * contrastAdjust + mid;
}
// c. Apply desaturation
if (desaturationAmount > 0.0 && desaturationAmount <= 1.0) {
// Luminance calculation (standard Rec. 601)
const gray = 0.299 * r + 0.587 * g + 0.114 * b;
r = r * (1 - desaturationAmount) + gray * desaturationAmount;
g = g * (1 - desaturationAmount) + gray * desaturationAmount;
b = b * (1 - desaturationAmount) + gray * desaturationAmount;
}
// d. Apply serene color tint (blend)
if (tintStrength > 0.0 && tintStrength <= 1.0) {
r = r * (1 - tintStrength) + R_tint * tintStrength;
g = g * (1 - tintStrength) + G_tint * tintStrength;
b = b * (1 - tintStrength) + B_tint * tintStrength;
}
// e. Clamp values to [0, 255]
data[i] = Math.max(0, Math.min(255, r));
data[i + 1] = Math.max(0, Math.min(255, g));
data[i + 2] = Math.max(0, Math.min(255, b));
// Alpha channel (data[i + 3]) remains unchanged
}
// 7. Put the modified image data back onto the canvas
ctx.putImageData(imageData, 0, 0);
// 8. Return the canvas
return canvas;
}
Apply Changes