You can edit the below JavaScript code to customize the image tool.
function processImage(originalImg, strength = 1.0) {
const canvas = document.createElement('canvas');
const width = originalImg.naturalWidth || originalImg.width;
const height = originalImg.naturalHeight || originalImg.height;
// Ensure the image has valid dimensions
if (width === 0 || height === 0) {
canvas.width = 0;
canvas.height = 0;
return canvas; // Return an empty canvas if image dimensions are zero
}
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
// Check if context was created successfully (it might not be in some environments)
if (!ctx) {
console.error("Unable to get Canvas 2D context. Ensure this code is running in a browser environment.");
// Return an empty canvas or a canvas with an error message
canvas.width = Math.max(1, width); // Ensure drawable area for message
canvas.height = Math.max(1, height);
// Optionally draw an error message if possible, but for now, just return
return canvas;
}
ctx.drawImage(originalImg, 0, 0, width, height);
let S = parseFloat(strength);
// Handle cases where strength might be parsed as NaN (e.g., if an invalid string was passed)
if (isNaN(S)) {
S = 1.0; // Revert to default strength if parsing fails
}
// If strength is zero, no sharpening is applied.
// The canvas already contains the original image drawn by ctx.drawImage.
if (S === 0) {
return canvas;
}
let imageData;
try {
imageData = ctx.getImageData(0, 0, width, height);
} catch (e) {
console.error("Error getting ImageData: ", e);
// This can happen due to cross-origin issues if the image source is from a different domain
// and the server doesn't set appropriate CORS headers (e.g., `Access-Control-Allow-Origin`).
// In such a case, the canvas is "tainted".
// The canvas currently holds the original image drawn by drawImage.
// Returning it is a reasonable fallback as the sharpened version cannot be computed.
return canvas;
}
const data = imageData.data;
// Create a new array for the output pixel data.
// Uint8ClampedArray automatically clamps values to the 0-255 range.
const outputPixelData = new Uint8ClampedArray(data.length);
// Define the 3x3 sharpening kernel based on strength (S).
// This is a common Laplacian-based sharpening kernel.
// Structure:
// [ 0, -S, 0 ]
// [-S, C, -S ]
// [ 0, -S, 0 ]
// where C (center value) = 1 + 4*S.
// The sum of kernel elements is (1 + 4*S) + 4*(-S) = 1. This helps preserve overall image brightness.
const kernel = [
[0, -S, 0 ],
[-S, 1 + 4 * S, -S ],
[0, -S, 0 ]
];
// Iterate over each pixel of the image
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
let sumR = 0;
let sumG = 0;
let sumB = 0;
// Apply the convolution kernel to the current pixel (x,y)
for (let ky = -1; ky <= 1; ky++) { // Kernel y-offset (-1, 0, 1) -> kernel row index ky+1
for (let kx = -1; kx <= 1; kx++) { // Kernel x-offset (-1, 0, 1) -> kernel col index kx+1
const kernelVal = kernel[ky + 1][kx + 1];
// Skip if kernel value is 0 for a minor optimization
if (kernelVal === 0) {
continue;
}
// Calculate coordinates of the source pixel (neighbor pixel)
let Val_Check_pixelX = x + kx; // Renamed to avoid conflict, originally pixelX
let Val_Check_pixelY = y + ky; // Renamed to avoid conflict, originally pixelY
// Handle edge cases: clamp neighbor coordinates to image boundaries
// This is the "clamp to edge" or "extend edge" strategy.
Val_Check_pixelX = Math.max(0, Math.min(width - 1, Val_Check_pixelX));
Val_Check_pixelY = Math.max(0, Math.min(height - 1, Val_Check_pixelY));
// Get the G_IDX (or base index) of the neighbor pixel in the_data_ array.
// Each pixel has 4 components (R, G, B, A), so we multiply by 4.
const neighborPixelBaseIndex = (Val_Check_pixelY * width + Val_Check_pixelX) * 4;
// Accumulate weighted R, G, B values from the neighbor pixel
sumR += data[neighborPixelBaseIndex] * kernelVal;
sumG += data[neighborPixelBaseIndex + 1] * kernelVal;
sumB += data[neighborPixelBaseIndex + 2] * kernelVal;
// Alpha channel is not typically part of sharpening convolution sum based on color. It's copied.
}
}
// Get the G_IDX (or base index) of the current_pixel in the output data array
const currentPixelBaseIndex = (y * width + x) * 4;
// Set the sharpened R, G, B values. Alpha channel is preserved from original.
// Uint8ClampedArray will automatically clamp sumR, sumG, sumB to [0, 255].
outputPixelData[currentPixelBaseIndex] = sumR;
outputPixelData[currentPixelBaseIndex + 1] = sumG;
outputPixelData[currentPixelBaseIndex + 2] = sumB;
outputPixelData[currentPixelBaseIndex + 3] = data[currentPixelBaseIndex + 3]; // Preserve original alpha
}
}
// Create a new ImageData object from the processed (sharpened) pixel data
const outputImageData = new ImageData(outputPixelData, width, height);
// Put the sharpened image data back onto the canvas, overwriting the original image
ctx.putImageData(outputImageData, 0, 0);
return canvas;
}
Free Image Tool Creator
Can't find the image tool you're looking for? Create one based on your own needs now!
The Image Sharpener Tool enhances the clarity and definition of images by applying a sharpening effect. Users can adjust the strength of the sharpening effect according to their needs. This tool is useful for photographers, graphic designers, and anyone looking to improve the visual quality of their images, such as sharpening details in product photos, enhancing facial features in portraits, or refining artwork before printing or sharing online.