You can edit the below JavaScript code to customize the image tool.
function processImage(originalImg, outlineThickness = 3, outlineThreshold = 50, posterizationLevels = 6, blurRadius = 1) {
/**
* Converts an image to a 3D cartoon style by applying color posterization and edge detection.
* @param {Image} originalImg - The source javascript Image object.
* @param {number} outlineThickness - The thickness of the black outlines.
* @param {number} outlineThreshold - The sensitivity for edge detection (0-255). Lower is more sensitive.
* @param {number} posterizationLevels - The number of color levels for each channel (e.g., 4, 8, 16).
* @param {number} blurRadius - The radius of the initial blur to smooth colors. 0 for no blur.
* @returns {HTMLCanvasElement} A canvas element with the cartoon-styled image.
*/
// Helper function for color posterization
const posterizeChannel = (value, levels) => {
if (levels <= 1) return 128; // Return mid-gray for 1 level
const numLevels = Math.max(2, Math.round(levels));
const step = 255 / (numLevels - 1);
return Math.round(value / step) * step;
};
const width = originalImg.width;
const height = originalImg.height;
// Create the final canvas that will be returned
const finalCanvas = document.createElement('canvas');
finalCanvas.width = width;
finalCanvas.height = height;
const finalCtx = finalCanvas.getContext('2d', { willReadFrequently: true });
if (!finalCtx) {
console.error("Could not get 2D context");
return document.createElement('div').innerText = "Could not process image.";
}
// Use a temporary canvas for pre-processing (initial draw and blur)
const tempCanvas = document.createElement('canvas');
tempCanvas.width = width;
tempCanvas.height = height;
const tempCtx = tempCanvas.getContext('2d', { willReadFrequently: true });
if (!tempCtx) {
console.error("Could not get 2D context for temp canvas");
return document.createElement('div').innerText = "Could not process image.";
}
// Apply blur to smooth out details for a painterly/cartoon effect
if (blurRadius > 0) {
tempCtx.filter = `blur(${blurRadius}px)`;
}
tempCtx.drawImage(originalImg, 0, 0, width, height);
tempCtx.filter = 'none'; // Reset filter
const blurredImageData = tempCtx.getImageData(0, 0, width, height);
const blurredData = blurredImageData.data;
// In a single pass, create both grayscale data (for edges) and posterized data (for color)
const grayData = new Uint8ClampedArray(width * height);
const posterizedImageData = new ImageData(width, height);
const posterizedData = posterizedImageData.data;
for (let i = 0; i < blurredData.length; i += 4) {
const r = blurredData[i];
const g = blurredData[i + 1];
const b = blurredData[i + 2];
const pixelIndex = i / 4;
// Populate grayscale data using the luminosity formula
grayData[pixelIndex] = 0.299 * r + 0.587 * g + 0.114 * b;
// Populate posterized color data
posterizedData[i] = posterizeChannel(r, posterizationLevels);
posterizedData[i + 1] = posterizeChannel(g, posterizationLevels);
posterizedData[i + 2] = posterizeChannel(b, posterizationLevels);
posterizedData[i + 3] = 255; // Set full alpha
}
// STEP 1: Draw the posterized color base onto the final canvas
finalCtx.putImageData(posterizedImageData, 0, 0);
// STEP 2: Create the outlines using a Sobel edge detection operator
const sobelX = [
[-1, 0, 1],
[-2, 0, 2],
[-1, 0, 1]
];
const sobelY = [
[-1, -2, -1],
[0, 0, 0],
[1, 2, 1]
];
// A separate canvas for drawing edges, which will be overlaid
const edgeCanvas = document.createElement('canvas');
edgeCanvas.width = width;
edgeCanvas.height = height;
const edgeCtx = edgeCanvas.getContext('2d');
if (!edgeCtx) {
console.error("Could not get 2D context for edge canvas");
return document.createElement('div').innerText = "Could not process image.";
}
edgeCtx.fillStyle = 'black';
// Convolve the grayscale image with the Sobel kernels
for (let y = 1; y < height - 1; y++) {
for (let x = 1; x < width - 1; x++) {
let gx = 0;
let gy = 0;
for (let ky = -1; ky <= 1; ky++) {
for (let kx = -1; kx <= 1; kx++) {
const grayValue = grayData[(y + ky) * width + (x + kx)];
gx += grayValue * sobelX[ky + 1][kx + 1];
gy += grayValue * sobelY[ky + 1][kx + 1];
}
}
const magnitude = Math.sqrt(gx * gx + gy * gy);
// If the magnitude of the gradient is above the threshold, it's an edge
if (magnitude > outlineThreshold) {
// To control thickness, draw a small, centered rectangle
const halfThickness = Math.floor(outlineThickness / 2);
edgeCtx.fillRect(x - halfThickness, y - halfThickness, outlineThickness, outlineThickness);
}
}
}
// STEP 3: Composite the outlines on top of the posterized base
finalCtx.drawImage(edgeCanvas, 0, 0);
return finalCanvas;
}
Free Image Tool Creator
Can't find the image tool you're looking for? Create one based on your own needs now!
The 3D Cartoon Style Image Creator transforms images into a 3D cartoon style by applying techniques such as color posterization and edge detection. Users can customize various parameters like outline thickness, edge detection sensitivity, posterization levels, and blur radius, allowing for a personalized cartoon effect. This tool is ideal for creating unique and playful versions of photos for social media, printing art, or enhancing creative projects where a whimsical visual style is desired.