You can edit the below JavaScript code to customize the image tool.
function processImage(originalImg, grainSize = 3) {
// Validate and parse grainSize parameter
// It can be a string or number as per guidelines. Default is 3.
let currentGrainSize = Number(grainSize);
if (isNaN(currentGrainSize) || currentGrainSize <= 0) {
// If grainSize was invalid (e.g., "abc", 0, or negative), reset to a sensible default.
currentGrainSize = 3;
}
// Ensure grainSize is an integer and at least 1.
currentGrainSize = Math.max(1, Math.floor(currentGrainSize));
// Canvas setup
const canvas = document.createElement('canvas');
// The { willReadFrequently: true } hint can potentially optimize performance
// for contexts involving frequent getImageData/putImageData calls.
const ctx = canvas.getContext('2d', { willReadFrequently: true });
const imgWidth = originalImg.naturalWidth || originalImg.width;
const imgHeight = originalImg.naturalHeight || originalImg.height;
canvas.width = imgWidth;
canvas.height = imgHeight;
// Handle cases where image dimensions might be zero (e.g., if the image hasn't loaded properly)
if (imgWidth === 0 || imgHeight === 0) {
console.warn("Image Autochrome Lumière Filter: Input image has zero dimensions. Returning an empty canvas.");
return canvas; // Return empty canvas
}
// Draw the original image onto the canvas. This allows us to get its pixel data.
ctx.drawImage(originalImg, 0, 0, imgWidth, imgHeight);
let originalImageData;
try {
// Get pixel data from the canvas where the original image was drawn.
originalImageData = ctx.getImageData(0, 0, imgWidth, imgHeight);
} catch (e) {
// This error can occur if the canvas is "tainted", often due to loading a cross-origin image
// without appropriate CORS (Cross-Origin Resource Sharing) headers from the server.
console.error("Image Autochrome Lumière Filter: Could not get ImageData from canvas. This might be due to CORS policy restrictions if the image is from a different origin. Error details:", e);
// Fallback: Return the canvas with the original image drawn, as processing is not possible.
return canvas;
}
const originalData = originalImageData.data; // This is a Uint8ClampedArray of RGBA values from the original image.
// Create a new ImageData object to hold the processed pixels.
// This is crucial because we need to read from originalData while writing to outputData,
// avoiding modification of pixels that might be read later in the same pass.
const outputImageData = ctx.createImageData(imgWidth, imgHeight);
const outputData = outputImageData.data;
// Define the characteristic Autochrome grain colors.
// These specific RGB values are chosen to evoke the somewhat muted and distinct palette of Autochrome images.
const autochromeColors = [
{ r: 210, g: 90, b: 50 }, // A muted Orange-Red
{ r: 80, g: 150, b: 90 }, // A somewhat desaturated Green
{ r: 100, g: 90, b: 170 } // A soft Blue-Violet
];
// Iterate over the image in blocks, where each block's size is defined by currentGrainSize.
for (let y = 0; y < imgHeight; y += currentGrainSize) {
for (let x = 0; x < imgWidth; x += currentGrainSize) {
// For each block, randomly select one of the defined Autochrome base colors.
// This simulates the random distribution of colored starch grains.
const baseColor = autochromeColors[Math.floor(Math.random() * autochromeColors.length)];
// Process each pixel within the current block.
for (let dy = 0; dy < currentGrainSize; dy++) {
for (let dx = 0; dx < currentGrainSize; dx++) {
const currentY = y + dy;
const currentX = x + dx;
// Ensure that the current pixel coordinates are within the image boundaries.
if (currentY < imgHeight && currentX < imgWidth) {
// Calculate the index in the 1D pixel data array for the current pixel.
// Each pixel has 4 components (R, G, B, A).
const i = (currentY * imgWidth + currentX) * 4;
// Get the R, G, B, A components of the original pixel.
const r_orig = originalData[i];
const g_orig = originalData[i+1];
const b_orig = originalData[i+2];
const a_orig = originalData[i+3];
// Calculate the luminosity (brightness) of the original pixel.
// This uses standard coefficients (Rec. ITU-R BT.601) for converting RGB to luminance.
// The result is normalized to a 0.0 - 1.0 range.
const luminosity = (0.299 * r_orig + 0.587 * g_orig + 0.114 * b_orig) / 255.0;
// Apply the chosen base Autochrome color, modulated by the original pixel's luminosity.
// The new color for the pixel will be the selected grain color, scaled by the original brightness.
// Clamp values to ensure they remain within the valid 0-255 range for RGB components.
outputData[i] = Math.max(0, Math.min(255, baseColor.r * luminosity));
outputData[i+1] = Math.max(0, Math.min(255, baseColor.g * luminosity));
outputData[i+2] = Math.max(0, Math.min(255, baseColor.b * luminosity));
outputData[i+3] = a_orig; // Preserve the original alpha (transparency) of the pixel.
}
}
}
}
}
// After processing all pixels, put the modified pixel data (from outputImageData) back onto the canvas.
ctx.putImageData(outputImageData, 0, 0);
// Return the canvas element with the Autochrome effect applied.
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 Autochrome Lumière Filter Effect Tool allows users to apply a vintage Autochrome filter effect to their images. This effect emulates the distinctive soft color palette reminiscent of early color photography, incorporating muted orange-red, soft blue-violet, and desaturated green hues. Users can adjust the grain size of the effect to customize the appearance of the image, adding a nostalgic touch to modern photos. This tool is ideal for artists, photographers, and hobbyists looking to create a retro aesthetic or enhance their digital images with a unique vintage look.