You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, threshold = 128, darkColorString = "0,0,0", lightColorString = "255,255,255") {
// Clamp threshold to the valid range [0, 255]
const effectiveThreshold = Math.max(0, Math.min(255, Number(threshold)));
// Create a canvas element
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Get image dimensions. Assumes originalImg is a loaded HTMLImageElement.
// naturalWidth/Height provide the intrinsic dimensions of the image.
const imgWidth = originalImg.naturalWidth;
const imgHeight = originalImg.naturalHeight;
// Helper function to create and return a canvas displaying an error message
const createErrorCanvas = (width, height, messageLines) => {
const errCanvas = document.createElement('canvas');
// Use provided dimensions, or fallback to a default size if dimensions are 0
errCanvas.width = width > 0 ? width : 150;
errCanvas.height = height > 0 ? height : 100;
const errCtx = errCanvas.getContext('2d');
// Fill background
errCtx.fillStyle = 'lightgray';
errCtx.fillRect(0, 0, errCanvas.width, errCanvas.height);
// Draw text
errCtx.fillStyle = 'red';
errCtx.textAlign = 'center';
errCtx.textBaseline = 'middle';
const lineHeight = 18; // Adjust as needed for font size
const FONT_SIZE = 12; // Example font size
errCtx.font = `${FONT_SIZE}px Arial`;
const totalTextHeight = messageLines.length * lineHeight;
let startY = (errCanvas.height - totalTextHeight) / 2 + (lineHeight / 2) - (FONT_SIZE / 10) ; // Approximate centering
messageLines.forEach((line, index) => {
errCtx.fillText(line, errCanvas.width / 2, startY + index * lineHeight);
});
return errCanvas;
};
// Validate image dimensions
if (imgWidth === 0 || imgHeight === 0) {
return createErrorCanvas(0, 0, ["Image has zero dimensions.", "(Not loaded or invalid?)"]);
}
canvas.width = imgWidth;
canvas.height = imgHeight;
// Draw the original image onto the canvas
try {
ctx.drawImage(originalImg, 0, 0, imgWidth, imgHeight);
} catch (e) {
// This can happen if originalImg is not a valid image source
return createErrorCanvas(imgWidth, imgHeight, ["Error: Could not draw image."]);
}
// Get the image data
let imageData;
try {
imageData = ctx.getImageData(0, 0, imgWidth, imgHeight);
} catch (e) {
// This typically happens due to cross-origin restrictions
return createErrorCanvas(imgWidth, imgHeight, ["Error: Cannot process pixels.", "(Image may be cross-origin)"]);
}
const data = imageData.data;
// Helper function to parse color strings like "r,g,b"
// Returns an array [r, g, b] or defaultColor if parsing fails.
// Clamps color components to [0, 255].
const parseRgbColor = (colorStr, defaultColor) => {
if (typeof colorStr !== 'string') {
return defaultColor; // Ensure input is a string
}
const components = colorStr.split(',');
if (components.length !== 3) {
return defaultColor; // Expect "r,g,b"
}
const parts = components.map(s => Number(s.trim()));
if (parts.some(p => isNaN(p))) {
return defaultColor; // Expect numeric components
}
// Clamp each component to [0, 255]
return parts.map(p => Math.max(0, Math.min(255, p)));
};
const defaultDarkRgb = [0, 0, 0]; // Default to black
const defaultLightRgb = [255, 255, 255]; // Default to white
const darkColor = parseRgbColor(darkColorString, defaultDarkRgb);
const lightColor = parseRgbColor(lightColorString, defaultLightRgb);
// Iterate over each pixel (R, G, B, Alpha components)
for (let i = 0; i < data.length; i += 4) {
const r = data[i];
const g = data[i + 1];
const b = data[i + 2];
// Calculate grayscale value using the luminosity method for perceived brightness
const gray = 0.299 * r + 0.587 * g + 0.114 * b;
let outputR, outputG, outputB;
if (gray < effectiveThreshold) {
// Pixel is darker than threshold, apply dark color
outputR = darkColor[0];
outputG = darkColor[1];
outputB = darkColor[2];
} else {
// Pixel is lighter than or equal to threshold, apply light color
outputR = lightColor[0];
outputG = lightColor[1];
outputB = lightColor[2];
}
// Apply the new color
data[i] = outputR; // Red
data[i + 1] = outputG; // Green
data[i + 2] = outputB; // Blue
// Alpha (data[i + 3]) remains unchanged to preserve transparency
}
// Put the modified image data back onto the canvas
ctx.putImageData(imageData, 0, 0);
// Return the processed canvas
return canvas;
}
Apply Changes