You can edit the below JavaScript code to customize the image tool.
Apply Changes
/**
* Processes an image to create a stylized version, mimicking an AI-powered creator.
* It can produce a "draw" effect (pencil sketch) or a "colorTranslate" effect (posterization).
*
* @param {Image} originalImg The original source Image object. Must be fully loaded.
* @param {string} [effectType='draw'] The type of effect to apply. Can be 'draw' or 'colorTranslate'.
* @param {number} [drawThreshold=10] A parameter for the 'draw' effect, controlling the blur radius which affects line thickness. Range: 1-50.
* @param {number} [translateLevels=4] A parameter for the 'colorTranslate' effect, controlling the number of color levels per channel. Range: 2-256.
* @returns {HTMLCanvasElement} A new canvas element with the processed image.
*/
function processImage(originalImg, effectType = 'draw', drawThreshold = 10, translateLevels = 4) {
// --- Parameter Sanitization ---
effectType = String(effectType).toLowerCase();
drawThreshold = Math.max(1, Math.min(50, Number(drawThreshold)));
translateLevels = Math.max(2, Math.min(256, Math.floor(Number(translateLevels))));
// --- Canvas Setup ---
const width = originalImg.naturalWidth;
const height = originalImg.naturalHeight;
const finalCanvas = document.createElement('canvas');
finalCanvas.width = width;
finalCanvas.height = height;
// Use { willReadFrequently: true } for performance optimization with getImageData
const finalCtx = finalCanvas.getContext('2d', {
willReadFrequently: true
});
// --- Effect Logic ---
if (effectType === 'draw') {
// This effect creates a pencil sketch look by blending a grayscale image
// with a blurred, inverted version of itself using a "color-dodge" blend mode.
// 1. Create a grayscale version of the original image.
const grayCanvas = document.createElement('canvas');
grayCanvas.width = width;
grayCanvas.height = height;
const grayCtx = grayCanvas.getContext('2d', {
willReadFrequently: true
});
grayCtx.drawImage(originalImg, 0, 0, width, height);
const grayImageData = grayCtx.getImageData(0, 0, width, height);
const grayData = grayImageData.data;
for (let i = 0; i < grayData.length; i += 4) {
// Use luma formula for more perceptually accurate grayscale
const luma = grayData[i] * 0.299 + grayData[i + 1] * 0.587 + grayData[i + 2] * 0.114;
grayData[i] = luma;
grayData[i + 1] = luma;
grayData[i + 2] = luma;
}
grayCtx.putImageData(grayImageData, 0, 0);
// 2. Create an inverted version of the grayscale image.
const invertedCanvas = document.createElement('canvas');
invertedCanvas.width = width;
invertedCanvas.height = height;
const invertedCtx = invertedCanvas.getContext('2d', {
willReadFrequently: true
});
invertedCtx.drawImage(grayCanvas, 0, 0, width, height);
const invertedImageData = invertedCtx.getImageData(0, 0, width, height);
const invertedData = invertedImageData.data;
for (let i = 0; i < invertedData.length; i += 4) {
invertedData[i] = 255 - invertedData[i];
invertedData[i + 1] = 255 - invertedData[i + 1];
invertedData[i + 2] = 255 - invertedData[i + 2];
}
invertedCtx.putImageData(invertedImageData, 0, 0);
// 3. Blur the inverted image using the canvas filter property.
const blurredCanvas = document.createElement('canvas');
blurredCanvas.width = width;
blurredCanvas.height = height;
const blurredCtx = blurredCanvas.getContext('2d');
blurredCtx.filter = `blur(${drawThreshold}px)`;
blurredCtx.drawImage(invertedCanvas, 0, 0, width, height);
// 4. Blend the grayscale and blurred-inverted images on the final canvas.
finalCtx.drawImage(grayCanvas, 0, 0, width, height);
finalCtx.globalCompositeOperation = 'color-dodge';
finalCtx.drawImage(blurredCanvas, 0, 0, width, height);
finalCtx.globalCompositeOperation = 'source-over'; // Reset blend mode
} else if (effectType === 'colortranslate') {
// This effect posterizes the image, reducing the number of colors to create a stylized, "translated" look.
finalCtx.drawImage(originalImg, 0, 0, width, height);
const imageData = finalCtx.getImageData(0, 0, width, height);
const data = imageData.data;
const step = 255 / (translateLevels - 1);
for (let i = 0; i < data.length; i += 4) {
data[i] = Math.round(data[i] / step) * step; // Red
data[i + 1] = Math.round(data[i + 1] / step) * step; // Green
data[i + 2] = Math.round(data[i + 2] / step) * step; // Blue
}
finalCtx.putImageData(imageData, 0, 0);
} else {
// If the effect type is unknown, just draw the original image.
finalCtx.drawImage(originalImg, 0, 0, width, height);
}
return finalCanvas;
}
Apply Changes