You can edit the below JavaScript code to customize the image tool.
function processImage(originalImg, contrastFactor = 1.6, grainAmount = 6) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Check if the image is loaded and has valid dimensions.
// `originalImg.complete` indicates if the image is fully loaded.
// `naturalWidth` being 0 can mean it hasn't loaded, or it's an invalid/empty image.
if (!originalImg.complete || originalImg.naturalWidth === 0 || originalImg.naturalHeight === 0) {
console.error("Image is not loaded or has zero dimensions. Cannot apply filter.");
// Create a placeholder canvas with an error message.
// Use originalImg.width/height if available (e.g., from HTML attributes if it's an <img>), otherwise default.
const errorCanvasWidth = originalImg.width || 200;
const errorCanvasHeight = originalImg.height || 100;
canvas.width = errorCanvasWidth;
canvas.height = errorCanvasHeight;
ctx.fillStyle = 'lightgray';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.font = "12px Arial";
ctx.fillStyle = "black";
ctx.textAlign = "center";
ctx.textBaseline = "middle"; // Vertically center text
ctx.fillText("Error: Image not loaded or invalid.", canvas.width / 2, canvas.height / 2);
return canvas;
}
canvas.width = originalImg.naturalWidth;
canvas.height = originalImg.naturalHeight;
// Draw the original image onto the canvas.
try {
ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
} catch (e) {
// This could happen for various reasons, e.g. if the image object is somehow corrupted after loading.
console.error("Error drawing image to canvas:", e);
// Prepare canvas for error message
ctx.fillStyle = 'lightgray';
ctx.fillRect(0,0,canvas.width, canvas.height);
ctx.font = "12px Arial";
ctx.fillStyle = "red";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText("Error: Could not draw the image.", canvas.width / 2, canvas.height / 2);
return canvas;
}
let imageData;
try {
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
} catch (e) {
// This is a common issue with cross-origin images if the canvas becomes 'tainted'.
// The image is drawn, but pixel manipulation is disallowed.
console.error("Could not get image data (cross-origin issue?):", e);
// Display an error message overlay on the (already drawn) original image.
ctx.font = "bold 14px Arial";
// Semi-transparent red background for the text to make it readable
const text = "Cannot apply filter: Image source restricts processing (CORS).";
const textMetrics = ctx.measureText(text);
const textWidth = textMetrics.width;
const textHeight = parseInt(ctx.font, 10) * 1.2; // Approximate height
const K_PADDING = 10;
ctx.fillStyle = "rgba(0, 0, 0, 0.5)";
ctx.fillRect(
canvas.width / 2 - textWidth / 2 - K_PADDING,
canvas.height / 2 - textHeight / 2 - K_PADDING,
textWidth + 2 * K_PADDING,
textHeight + K_PADDING // extra padding at bottom
);
ctx.fillStyle = "white";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(text, canvas.width / 2, canvas.height / 2);
return canvas; // Return canvas with original image and error message
}
const data = imageData.data;
// Ensure grainAmount is non-negative.
const actualGrainAmount = Math.max(0, grainAmount);
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 formula (Rec. 709).
// This formula weights R, G, B according to human perception of brightness.
let gray = 0.2126 * r + 0.7152 * g + 0.0722 * b;
// 2. Apply contrast adjustment.
// This formula linearly increases the difference from the mid-gray value (128).
// Values darker than 128 become darker, and values lighter than 128 become lighter.
gray = (gray - 128) * contrastFactor + 128;
// 3. Add film grain simulation.
if (actualGrainAmount > 0) {
// Generate random noise. (Math.random() - 0.5) results in a range of [-0.5, 0.5].
// Multiplying by 2 * actualGrainAmount scales it to [-actualGrainAmount, actualGrainAmount].
const noise = (Math.random() - 0.5) * 2 * actualGrainAmount;
gray += noise;
}
// Clamp the final gray value to the valid [0, 255] range.
gray = Math.max(0, Math.min(255, gray));
// Ensure the value is an integer for pixel data.
gray = Math.floor(gray);
// Set the R, G, and B channels to the new gray value. Alpha remains unchanged.
data[i] = gray; // Red
data[i + 1] = gray; // Green
data[i + 2] = gray; // Blue
// data[i+3] is the alpha channel, which is left as is.
}
// Write the modified pixel data back to the canvas.
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 Ilford Pan F Plus 50 Filter Effect Tool is an online utility designed to apply a black and white filter effect to images, emulating the look of classic film photography. Users can adjust the contrast and grain level, enhancing the aesthetic of their images with a vintage feel. This tool is ideal for photographers and graphic designers looking to create high-contrast monochrome images or to add a nostalgic touch to their work. It can be used in various contexts, such as social media posts, art projects, or personal photography collections.