You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(
originalImg,
blurAmount = "0.5",
noiseIntensity = "15",
vignetteOpacity = "0.6",
aberrationOffset = "2",
warmthIntensity = "8"
) {
// Parse parameters to ensure they are numbers
const blur = parseFloat(blurAmount);
const noiseAmt = parseFloat(noiseIntensity);
const vignette = parseFloat(vignetteOpacity);
const aberration = Math.round(parseFloat(aberrationOffset));
const warmth = parseFloat(warmthIntensity);
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const width = originalImg.width;
const height = originalImg.height;
canvas.width = width;
canvas.height = height;
// 1. Initial draw with a subtle blur and contrast adjustment to soften perfect, sharp digital edges
ctx.filter = `blur(${blur}px) brightness(1.02) contrast(1.05)`;
ctx.drawImage(originalImg, 0, 0, width, height);
ctx.filter = 'none';
// 2. Pixel-level manipulation: Chromatic Aberration, Noise, and Color Temperature
const imgData = ctx.getImageData(0, 0, width, height);
const data = imgData.data;
const outData = new Uint8ClampedArray(data.length);
// Helper to get the 1D array index from 2D coordinates
const getIdx = (x, y) => (y * width + x) * 4;
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const idx = getIdx(x, y);
// Calculate chromatic aberration offsets (simulating real lens imperfection)
const rx = Math.min(Math.max(x - aberration, 0), width - 1);
const bx = Math.min(Math.max(x + aberration, 0), width - 1);
const rIdx = getIdx(rx, y);
const bIdx = getIdx(bx, y);
// Channel separation
let r = data[rIdx]; // Shifted Red channel
let g = data[idx + 1]; // True Green channel
let b = data[bIdx + 2]; // Shifted Blue channel
let a = data[idx + 3]; // Alpha
// Add monochromatic camera/film noise
if (noiseAmt > 0) {
const noise = (Math.random() - 0.5) * noiseAmt * 2;
r += noise;
g += noise;
b += noise;
}
// Adjust color temperature (warmth) for a more realistic photographic look
if (warmth > 0) {
r += warmth;
b -= warmth;
}
// Store back to new array
outData[idx] = r;
outData[idx + 1] = g;
outData[idx + 2] = b;
outData[idx + 3] = a;
}
}
// Apply the manipulated pixels back to the canvas
const newImgData = new ImageData(outData, width, height);
ctx.putImageData(newImgData, 0, 0);
// 3. Lighting Realism: Vignette and subtle environmental reflection/highlight
if (vignette > 0) {
const cx = width / 2;
const cy = height / 2;
const maxRadius = Math.sqrt(cx * cx + cy * cy);
// Vignette (darken corners simulating lens light falloff)
const radialGradient = ctx.createRadialGradient(cx, cy, maxRadius * 0.4, cx, cy, maxRadius);
radialGradient.addColorStop(0, 'rgba(0, 0, 0, 0)');
radialGradient.addColorStop(1, `rgba(0, 0, 0, ${vignette})`);
ctx.fillStyle = radialGradient;
ctx.fillRect(0, 0, width, height);
// Env lighting highlight (simulating soft directional light casting over the template surface)
const linearGradient = ctx.createLinearGradient(0, 0, width, height);
linearGradient.addColorStop(0, 'rgba(255, 255, 255, 0.12)');
linearGradient.addColorStop(0.4, 'rgba(255, 255, 255, 0)');
linearGradient.addColorStop(1, 'rgba(0, 0, 0, 0.1)'); // subtle shadow corner opposite to light
ctx.fillStyle = linearGradient;
ctx.fillRect(0, 0, width, height);
}
return canvas;
}
Apply Changes