You can edit the below JavaScript code to customize the image tool.
async function processImage(originalImg, pixelSize = 20) {
// Define cache keys for script loading promises.
// These are defined within the function scope but use window properties for persistence across calls.
const TRACKING_JS_PROMISE_CACHE_KEY = '__processImage_trackingJsPromise_facepixel_v1';
const FACE_DATA_PROMISE_CACHE_KEY = '__processImage_faceDataPromise_facepixel_v1';
// Utility function to load a script ensuring it's only fetched and processed once.
// Defined inside processImage for encapsulation, but effective globally due to window caching.
async function _loadScriptOnce(url, promiseCacheKey, globalObjectCheckFn) {
// If the script's effect (checked by globalObjectCheckFn) is already present, resolve immediately.
if (globalObjectCheckFn && globalObjectCheckFn()) {
return Promise.resolve();
}
// If a loading promise for this script already exists on the window object, return it.
if (window[promiseCacheKey]) {
return window[promiseCacheKey];
}
// Otherwise, create a new promise to load the script.
window[promiseCacheKey] = new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = url;
script.async = true;
script.onload = () => {
// After the script loads, check if it successfully established the expected global objects/conditions.
if (globalObjectCheckFn && globalObjectCheckFn()) {
resolve();
} else {
// If not, the script might not have worked as expected. Nullify the promise cache to allow retry.
window[promiseCacheKey] = null;
reject(new Error(`Script ${url} loaded but expected global object/condition not met.`));
}
};
script.onerror = () => {
// If script loading fails, nullify the promise cache to allow retry.
window[promiseCacheKey] = null;
reject(new Error(`Failed to load script: ${url}`));
};
document.head.appendChild(script);
});
return window[promiseCacheKey];
}
// Validate pixelSize parameter.
if (typeof pixelSize !== 'number' || pixelSize <= 0) {
pixelSize = 20; // Default pixelSize
}
pixelSize = Math.floor(pixelSize); // Ensure it's an integer.
// Create the output canvas.
const outputCanvas = document.createElement('canvas');
const outputCtx = outputCanvas.getContext('2d');
// Check if the originalImg is valid and loaded.
if (!originalImg || typeof originalImg.naturalWidth === 'undefined' || originalImg.naturalWidth === 0 || originalImg.naturalHeight === 0) {
console.error("processImage: Original image is not loaded, invalid, or has zero dimensions.");
// Return a minimal canvas in case of an invalid image.
outputCanvas.width = 1;
outputCanvas.height = 1;
// Optionally, draw an error message on this small canvas.
// outputCtx.font = "8px sans-serif";
// outputCtx.fillText("Invalid Image", 0, 8);
return outputCanvas;
}
// Set canvas dimensions and draw the original image.
outputCanvas.width = originalImg.naturalWidth;
outputCanvas.height = originalImg.naturalHeight;
outputCtx.drawImage(originalImg, 0, 0);
// URLs for the tracking.js library and its face detection data.
const TRACKING_JS_URL = 'https://cdn.jsdelivr.net/npm/tracking@1.1.3/build/tracking-min.js';
const FACE_DATA_URL = 'https://cdn.jsdelivr.net/npm/tracking@1.1.3/build/data/face-min.js';
try {
// Load tracking.js core library.
await _loadScriptOnce(
TRACKING_JS_URL,
TRACKING_JS_PROMISE_CACHE_KEY,
() => typeof window.tracking !== 'undefined' && typeof window.tracking.ObjectTracker !== 'undefined'
);
// Ensure tracking.js core is available before attempting to load face data.
if (typeof window.tracking === 'undefined' || typeof window.tracking.ObjectTracker === 'undefined') {
throw new Error("tracking.js core failed to load or define window.tracking.");
}
// Load face detection data (which depends on tracking.js core).
await _loadScriptOnce(
FACE_DATA_URL,
FACE_DATA_PROMISE_CACHE_KEY,
() => window.tracking.ViolaJones && window.tracking.ViolaJones.classifiers && window.tracking.ViolaJones.classifiers.face
);
// Final check if face classifier data is available.
if (!window.tracking.ViolaJones || !window.tracking.ViolaJones.classifiers || !window.tracking.ViolaJones.classifiers.face) {
throw new Error("Face classifier data not registered after loading attempts.");
}
} catch (error) {
console.error("processImage: Error loading face detection library/data:", error.message);
// If loading fails, return the canvas with the original image.
return outputCanvas;
}
// Face detection is asynchronous, so wrap the tracking logic in a Promise.
return new Promise((resolve) => {
const tracker = new window.tracking.ObjectTracker('face');
// Optional: Configure tracker parameters for performance/accuracy trade-offs.
// tracker.setInitialScale(4);
// tracker.setStepSize(2);
// tracker.setEdgesDensity(0.1);
tracker.on('track', function(event) {
// The 'track' event provides data on detected objects.
if (event.data.length === 0) {
// No faces detected, resolve with the original image canvas.
resolve(outputCanvas);
return;
}
// Iterate over each detected face.
event.data.forEach(function(rect) {
const { x, y, width, height } = rect;
// Skip if the detected region has no area.
if (width === 0 || height === 0) return;
// Create a temporary canvas to draw the downscaled (pixelated) face region.
const tempPixelCanvas = document.createElement('canvas');
const tempPixelCtx = tempPixelCanvas.getContext('2d');
// Calculate dimensions for the small, pixelated version of the face.
// Ensure at least 1x1 pixel dimension.
const downscaleWidth = Math.max(1, Math.round(width / pixelSize));
const downscaleHeight = Math.max(1, Math.round(height / pixelSize));
tempPixelCanvas.width = downscaleWidth;
tempPixelCanvas.height = downscaleHeight;
// Draw the detected face region from the main canvas (outputCanvas) onto the temporary canvas,
// scaling it down. This performs an implicit averaging of pixels.
tempPixelCtx.drawImage(outputCanvas, // Source: the main canvas
x, y, width, height, // Source rectangle (face region)
0, 0, downscaleWidth, downscaleHeight); // Destination rectangle (on temp canvas)
// Before drawing the pixelated version back, disable image smoothing on the main canvas
// to achieve a sharp, blocky effect when upscaling.
const smoothingEnabledState = outputCtx.imageSmoothingEnabled; // Save current state
outputCtx.imageSmoothingEnabled = false;
// Vendor-prefixed versions like mozImageSmoothingEnabled, webkitImageSmoothingEnabled
// are generally not needed for modern browsers but could be added for older ones.
// Draw the small, pixelated image from tempPixelCanvas back onto the main canvas,
// scaling it up to the original dimensions of the face region.
outputCtx.drawImage(tempPixelCanvas,
0, 0, downscaleWidth, downscaleHeight, // Source: the small image from temp canvas
x, y, width, height); // Destination: original face region on main canvas
// Restore the original image smoothing setting on the main canvas.
outputCtx.imageSmoothingEnabled = smoothingEnabledState;
});
// After processing all faces, resolve the Promise with the modified canvas.
resolve(outputCanvas);
});
try {
// Start the face tracking process. tracking.js can track on
// HTMLImageElement, HTMLVideoElement, or HTMLCanvasElement.
// Here, we use outputCanvas, which contains the original image.
window.tracking.track(outputCanvas, tracker);
} catch (err) {
console.error("processImage: Error initiating face tracking:", err.message);
// If tracking initiation fails, resolve with the (original) canvas.
resolve(outputCanvas);
}
});
}
Free Image Tool Creator
Can't find the image tool you're looking for? Create one based on your own needs now!
Photo Face Pixelator is an online tool designed to pixelate faces in images. By identifying faces within a given photo, it applies a pixelation effect that obscures facial features while preserving the overall image context. This tool can be useful for privacy protection, allowing users to share images without revealing identifiable facial details. It can be applied in various scenarios, such as preparing images for social media, creating content for presentations, or ensuring anonymity when sharing personal photos.