You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, inkColorStr = "rgb(70,50,30)", paperColorStr = "rgb(240,235,220)", contrastLevel = 75, noiseAmount = 15) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = originalImg.naturalWidth || originalImg.width;
canvas.height = originalImg.naturalHeight || originalImg.height;
ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;
// Helper function to parse color strings (e.g., "rgb(r,g,b)", "#RRGGBB", "colorname")
// into {r, g, b} components (0-255)
function parseColor(colorString) {
const tempCanvas = document.createElement('canvas');
tempCanvas.width = 1;
tempCanvas.height = 1;
const tempCtx = tempCanvas.getContext('2d', { willReadFrequently: true }); // Optimization hint
tempCtx.fillStyle = colorString;
tempCtx.fillRect(0, 0, 1, 1);
const [r, g, b] = tempCtx.getImageData(0, 0, 1, 1).data;
return { r, g, b };
}
const ink = parseColor(inkColorStr);
const paper = parseColor(paperColorStr);
// Map contrastLevel (0-100) to C (-255 to 255) for the contrast formula
// C = cl * 5.1 - 255
// cl = 0 -> C = -255 (flat gray)
// cl = 50 -> C = 0 (no change)
// cl = 100 -> C = 255 (max contrast)
const C = contrastLevel * 5.1 - 255;
const contrastFactor = (259 * (C + 255)) / (255 * (259 - C));
for (let i = 0; i < data.length; i += 4) {
const r = data[i];
const g = data[i + 1];
const b = data[i + 2];
// Calculate luminance (grayscale value)
const originalLum = 0.299 * r + 0.587 * g + 0.114 * b;
// Apply contrast
let contrastedLum = contrastFactor * (originalLum - 128) + 128;
contrastedLum = Math.max(0, Math.min(255, contrastedLum)); // Clamp to 0-255
// Normalize luminance to 0-1 range for interpolation
const normalizedLum = contrastedLum / 255.0;
// Interpolate between ink and paper color based on normalized luminance
let finalR = ink.r * (1 - normalizedLum) + paper.r * normalizedLum;
let finalG = ink.g * (1 - normalizedLum) + paper.g * normalizedLum;
let finalB = ink.b * (1 - normalizedLum) + paper.b * normalizedLum;
// Add noise
if (noiseAmount > 0) {
const noise = (Math.random() - 0.5) * noiseAmount;
finalR += noise;
finalG += noise;
finalB += noise;
}
// Clamp final RGB values and assign to image data
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)));
// Alpha channel (data[i+3]) remains unchanged (typically 255)
}
ctx.putImageData(imageData, 0, 0);
return canvas;
}
Apply Changes