You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, contrast = 1.2, saturation = 0.85, noiseAmount = 20, vignetteStrength = 0.6, dateStamp = '', frameThickness = 0) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const width = originalImg.naturalWidth || originalImg.width;
const height = originalImg.naturalHeight || originalImg.height;
canvas.width = width;
canvas.height = height;
// 1. Apply contrast and saturation filters and draw the image
ctx.filter = `contrast(${contrast}) saturate(${saturation})`;
ctx.drawImage(originalImg, 0, 0, width, height);
// Reset filter for subsequent canvas operations
ctx.filter = 'none';
// 2. Add film grain/noise effect
if (noiseAmount > 0) {
const imageData = ctx.getImageData(0, 0, width, height);
const data = imageData.data;
// Iterate over each pixel, add random noise, and clamp the value between 0 and 255
for (let i = 0; i < data.length; i += 4) {
const noise = (Math.random() - 0.5) * noiseAmount;
data[i] = Math.max(0, Math.min(255, data[i] + noise)); // Red
data[i + 1] = Math.max(0, Math.min(255, data[i + 1] + noise)); // Green
data[i + 2] = Math.max(0, Math.min(255, data[i + 2] + noise)); // Blue
}
ctx.putImageData(imageData, 0, 0);
}
// 3. Add vignette effect
if (vignetteStrength > 0) {
const outerRadius = Math.sqrt(width * width + height * height) / 2;
const gradient = ctx.createRadialGradient(
width / 2, height / 2, 0,
width / 2, height / 2, outerRadius
);
// The gradient is transparent in the center and fades to dark at the edges
gradient.addColorStop(0, 'rgba(0,0,0,0)');
gradient.addColorStop(0.6, 'rgba(0,0,0,0)'); // Adjust for a wider transparent center
gradient.addColorStop(1, `rgba(0,0,0,${vignetteStrength})`);
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, width, height);
}
// 4. Add viewfinder frame overlay (optional)
if (frameThickness > 0) {
const inset = Math.min(width, height) * 0.03; // 3% inset from edges
// Thin inner guide rectangle
ctx.strokeStyle = 'rgba(200, 200, 200, 0.5)';
ctx.lineWidth = Math.max(1, frameThickness / 2); // Thinner line for the guide
ctx.strokeRect(inset, inset, width - 2 * inset, height - 2 * inset);
// Bold corner focus markers
const cornerLength = inset * 1.5;
ctx.strokeStyle = 'rgba(255, 255, 255, 0.7)';
ctx.lineWidth = Math.max(1, frameThickness);
ctx.beginPath();
// Top-left
ctx.moveTo(inset - ctx.lineWidth / 2, inset + cornerLength);
ctx.lineTo(inset - ctx.lineWidth / 2, inset - ctx.lineWidth / 2);
ctx.lineTo(inset + cornerLength, inset - ctx.lineWidth / 2);
// Top-right
ctx.moveTo(width - inset + ctx.lineWidth / 2, inset + cornerLength);
ctx.lineTo(width - inset + ctx.lineWidth / 2, inset - ctx.lineWidth / 2);
ctx.lineTo(width - inset - cornerLength, inset - ctx.lineWidth / 2);
// Bottom-left
ctx.moveTo(inset - ctx.lineWidth / 2, height - inset - cornerLength);
ctx.lineTo(inset - ctx.lineWidth / 2, height - inset + ctx.lineWidth / 2);
ctx.lineTo(inset + cornerLength, height - inset + ctx.lineWidth / 2);
// Bottom-right
ctx.moveTo(width - inset + ctx.lineWidth / 2, height - inset - cornerLength);
ctx.lineTo(width - inset + ctx.lineWidth / 2, height - inset + ctx.lineWidth / 2);
ctx.lineTo(width - inset - cornerLength, height - inset + ctx.lineWidth / 2);
ctx.stroke();
}
// 5. Add date stamp (optional)
if (dateStamp && typeof dateStamp === 'string' && dateStamp.trim() !== '') {
// Calculate a dynamic font size based on image height
const fontSize = Math.max(12, Math.round(height * 0.04));
ctx.font = `bold ${fontSize}px "Courier New", monospace`;
ctx.fillStyle = 'rgba(255, 180, 0, 0.9)'; // Classic orange date stamp color
ctx.textAlign = 'right';
ctx.textBaseline = 'bottom';
// Add a subtle shadow to make the text more readable against any background
ctx.shadowColor = 'rgba(0, 0, 0, 0.8)';
ctx.shadowBlur = 4;
ctx.shadowOffsetX = 1;
ctx.shadowOffsetY = 1;
const padding = Math.round(fontSize * 0.6);
ctx.fillText(dateStamp, width - padding, height - padding);
// Reset shadow properties
ctx.shadowColor = 'transparent';
ctx.shadowBlur = 0;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
}
// Return the final canvas element
return canvas;
}
Apply Changes