You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg) {
// --- Input Validation ---
// Check if originalImg is a valid, loaded HTMLImageElement
if (!(originalImg instanceof HTMLImageElement) || !originalImg.complete || originalImg.naturalWidth === 0 || originalImg.naturalHeight === 0) {
console.error("processImage: The provided image is not a valid, loaded HTMLImageElement.");
// Create and return an error canvas
const errorCanvas = document.createElement('canvas');
errorCanvas.width = 200; // Arbitrary small size
errorCanvas.height = 100;
const ctx = errorCanvas.getContext('2d');
if (ctx) {
ctx.fillStyle = 'rgb(240, 240, 240)'; // Light gray background
ctx.fillRect(0, 0, errorCanvas.width, errorCanvas.height);
ctx.fillStyle = 'red';
ctx.font = '14px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('Invalid Image Input', errorCanvas.width / 2, errorCanvas.height / 2);
}
return errorCanvas;
}
// --- Canvas Setup ---
const canvas = document.createElement('canvas');
canvas.width = originalImg.naturalWidth;
canvas.height = originalImg.naturalHeight;
// Add willReadFrequently hint for potential performance improvement on repeated getImageData/putImageData calls
const ctx = canvas.getContext('2d', { willReadFrequently: true });
// Draw the original image onto the canvas
ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
let imageData;
try {
// Get the pixel data from the canvas
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
} catch (e) {
// Handle potential security errors (e.g., canvas tainted by cross-origin image)
console.error("processImage: SecurityError - Could not get ImageData. Canvas might be tainted.", e);
// Draw a warning message on the canvas. The canvas currently holds the original image.
ctx.fillStyle = 'rgba(0, 0, 0, 0.7)'; // Semi-transparent black overlay
ctx.fillRect(0, 0, canvas.width, canvas.height);
const fontSize = Math.max(16, Math.min(canvas.width, canvas.height) / 15); // Responsive font size
ctx.font = `bold ${fontSize}px Arial`;
ctx.fillStyle = 'white';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
const messageLines = ["Error: Cannot process image.", "Possibly a cross-origin issue."];
const lineHeight = fontSize * 1.2;
const totalTextHeight = messageLines.length * lineHeight;
let startY = canvas.height / 2 - totalTextHeight / 2 + lineHeight / 2;
messageLines.forEach(line => {
ctx.fillText(line, canvas.width / 2, startY);
startY += lineHeight;
});
return canvas; // Return the canvas with the original image and error message
}
const data = imageData.data; // The array of RGBA values
// --- Ektachrome E100 Filter Parameters ---
// These values are chosen to approximate the Ektachrome E100 look:
// vibrant colors, cool tones, good contrast.
const E100_BRIGHTNESS = 5; // A slight overall lift in brightness.
const E100_CONTRAST = 1.22; // Moderate contrast boost typical for slide film.
const E100_RED_FACTOR = 0.96; // Slightly cool down reds or shift them subtly.
const E100_GREEN_FACTOR = 1.04; // Enhance green vibrancy.
const E100_BLUE_FACTOR = 1.10; // Boost blues for the characteristic cool Ektachrome look.
// --- Pixel Manipulation Loop ---
for (let i = 0; i < data.length; i += 4) {
let r = data[i]; // Red channel
let g = data[i+1]; // Green channel
let b = data[i+2]; // Blue channel
// Alpha channel (data[i+3]) is usually left unchanged for filters.
// 1. Apply Brightness
// This shifts all color values up or down.
r += E100_BRIGHTNESS;
g += E100_BRIGHTNESS;
b += E100_BRIGHTNESS;
// 2. Apply Contrast
// This pushes colors away from or towards the mid-gray point (128).
// Formula: NewValue = factor * (OldValue - 128) + 128
r = E100_CONTRAST * (r - 128) + 128;
g = E100_CONTRAST * (g - 128) + 128;
b = E100_CONTRAST * (b - 128) + 128;
// 3. Apply Ektachrome-specific Color Tinting/Balancing
// Multiplies each channel by its respective factor.
r *= E100_RED_FACTOR;
g *= E100_GREEN_FACTOR;
b *= E100_BLUE_FACTOR;
// Clamp values to ensure they are within the valid 0-255 range.
data[i] = Math.max(0, Math.min(255, r));
data[i+1] = Math.max(0, Math.min(255, g));
data[i+2] = Math.max(0, Math.min(255, b));
}
// Write the modified pixel data back to the canvas
ctx.putImageData(imageData, 0, 0);
return canvas; // Return the processed canvas
}
Apply Changes