You can edit the below JavaScript code to customize the image tool.
function processImage(originalImg, contrast = 2.0) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const originalWidth = originalImg.naturalWidth || originalImg.width;
const originalHeight = originalImg.naturalHeight || originalImg.height;
canvas.width = originalWidth;
canvas.height = originalHeight;
// Handle cases where image might not be loaded or dimensions are zero.
if (originalWidth === 0 || originalHeight === 0) {
// Return an empty (or minimally sized) canvas as there's nothing to process.
console.warn("Original image has zero width or height. Returning empty canvas.");
// Ensure canvas has at least 1x1 size to be valid for some contexts.
if (canvas.width === 0) canvas.width = 1;
if (canvas.height === 0) canvas.height = 1;
// Optionally fill with a color to indicate an issue or leave transparent.
// ctx.fillStyle = 'rgba(0,0,0,0.1)';
// ctx.fillRect(0, 0, canvas.width, canvas.height);
return canvas;
}
try {
ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
} catch (e) {
console.error("Error drawing image to canvas: ", e);
// Return the canvas, potentially empty or partially drawn, or throw.
return canvas;
}
let imageData;
try {
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
} catch (e) {
// This can happen due to security restrictions (e.g., cross-origin image without CORS)
console.error("Could not get image data (potentially CORS issue): ", e);
// Fallback: return the canvas with the original image drawn, as filter cannot be applied.
// Alternatively, one could draw an error message on the canvas.
return canvas;
}
const data = imageData.data;
// Metallic curve control points (normalized 0-1 for luminance).
// These points define a piecewise linear curve:
// (0,0) -> (P1_IN,P1_OUT) -> (P2_IN,P2_OUT) -> (P3_IN,P3_OUT) -> (1,1)
// This specific curve aims for a "polished metal" look by:
// - Severely darkening shadows and lower mid-tones.
// - Sharply increasing brightness for highlights, creating a shiny appearance.
const P1_IN = 0.25, P1_OUT = 0.05; // Input luminance 25% maps to 5% (darkens shadows)
const P2_IN = 0.50, P2_OUT = 0.15; // Input luminance 50% maps to 15% (darkens mid-tones)
const P3_IN = 0.75, P3_OUT = 0.90; // Input luminance 75% maps to 90% (boosts highlights)
// Helper function to apply the piecewise linear metallic curve.
// Input lumNorm is expected to be in [0, 1].
const applyMetallicCurve = (lumNorm) => {
if (lumNorm <= P1_IN) { // Segment from (0,0) to (P1_IN, P1_OUT)
// If P1_IN is 0, this branch handles lumNorm = 0. result is P1_OUT or 0 if P1_OUT is also 0.
return (P1_IN === 0) ? P1_OUT : (P1_OUT / P1_IN) * lumNorm;
} else if (lumNorm <= P2_IN) { // Segment from (P1_IN, P1_OUT) to (P2_IN, P2_OUT)
return P1_OUT + ((P2_OUT - P1_OUT) / (P2_IN - P1_IN)) * (lumNorm - P1_IN);
} else if (lumNorm <= P3_IN) { // Segment from (P2_IN, P2_OUT) to (P3_IN, P3_OUT)
return P2_OUT + ((P3_OUT - P2_OUT) / (P3_IN - P2_IN)) * (lumNorm - P2_IN);
} else { // Segment from (P3_IN, P3_OUT) to (1,1)
// If P3_IN is 1, this branch handles lumNorm = 1. result is P3_OUT or 1 if P3_OUT is also 1.
return (1.0 - P3_IN === 0) ? P3_OUT : P3_OUT + ((1.0 - P3_OUT) / (1.0 - P3_IN)) * (lumNorm - P3_IN);
}
};
for (let i = 0; i < data.length; i += 4) {
const r = data[i];
const g = data[i + 1];
const b = data[i + 2];
// 1. Convert to grayscale using the luminance method (standard weights)
let gray = 0.299 * r + 0.587 * g + 0.114 * b;
// 2. Apply contrast adjustment
// Normalize gray from [0, 255] to [-0.5, 0.5] (center around 0 for contrast calculation)
let normalizedGray = (gray / 255.0) - 0.5;
// Apply contrast factor (contrast > 1 increases contrast, < 1 decreases)
normalizedGray *= contrast;
// Map back to [0, 255] range
gray = (normalizedGray + 0.5) * 255.0;
// Clamp values to ensure they are within the 0-255 range
gray = Math.max(0, Math.min(255, gray));
// 3. Apply the metallic curve to the contrasted grayscale value
const lumNorm = gray / 255.0; // Normalize for curve function (input is [0,1])
const metalValNorm = applyMetallicCurve(lumNorm); // Output is [0,1]
// Convert normalized curved value back to 0-255 range, round, and clamp
const finalGray = Math.round(Math.max(0, Math.min(1, metalValNorm)) * 255);
// Set the new RGB values (all same for grayscale)
data[i] = finalGray;
data[i + 1] = finalGray;
data[i + 2] = finalGray;
// Alpha channel (data[i + 3]) is preserved
}
ctx.putImageData(imageData, 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 Polished Metal Effect Filter allows users to transform their images by applying a polished metal effect. This tool enhances the contrast and alters the luminance values of the image to create a sleek, metallic appearance. It is ideal for graphic designers and photographers looking to add a stylish touch to their images, making them suitable for presentations, product showcases, or digital art. Whether you want to give a photo a shiny look or create eye-catching graphics, this filter offers a straightforward solution.