You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, crumpleIntensity = 0.6, creaseCount = 100, grainIntensity = 0.15) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const width = originalImg.naturalWidth;
const height = originalImg.naturalHeight;
canvas.width = width;
canvas.height = height;
// Helper function to get a random point on the edge of a rectangle
const getRandomEdgePoint = (w, h) => {
const edge = Math.floor(Math.random() * 4); // 0: top, 1: right, 2: bottom, 3: left
switch (edge) {
case 0: return { x: Math.random() * w, y: 0 };
case 1: return { x: w, y: Math.random() * h };
case 2: return { x: Math.random() * w, y: h };
case 3: default: return { x: 0, y: Math.random() * h };
}
};
// 1. Create the crumple lighting map
const lightCanvas = document.createElement('canvas');
const lightCtx = lightCanvas.getContext('2d');
lightCanvas.width = width;
lightCanvas.height = height;
// Fill with a neutral grey for soft-light/overlay blending
lightCtx.fillStyle = '#808080';
lightCtx.fillRect(0, 0, width, height);
// Draw random crease lines. We scale the number of creases based on the image size.
const scaledCreaseCount = creaseCount * (Math.max(width, height) / 1000);
lightCtx.lineWidth = 1.5;
for (let i = 0; i < scaledCreaseCount; i++) {
const start = getRandomEdgePoint(width, height);
const end = getRandomEdgePoint(width, height);
// Crease color - half dark, half light, with some transparency
lightCtx.strokeStyle = (Math.random() > 0.5)
? `rgba(0, 0, 0, ${Math.random() * 0.2})`
: `rgba(255, 255, 255, ${Math.random() * 0.2})`;
lightCtx.beginPath();
lightCtx.moveTo(start.x, start.y);
// Add a bit of wobble to the line for a more natural crease
const controlX = start.x + (end.x - start.x) * Math.random();
const controlY = start.y + (end.y - start.y) * Math.random();
lightCtx.quadraticCurveTo(controlX, controlY, end.x, end.y);
lightCtx.stroke();
}
// Apply a blur to soften the creases into gradients
lightCtx.filter = 'blur(6px)';
// Draw the canvas onto itself to apply the filter.
lightCtx.globalCompositeOperation = 'source-over';
lightCtx.drawImage(lightCanvas, 0, 0);
// Clear the filter for any future drawing operations
lightCtx.filter = 'none';
// 2. Create a subtle paper grain texture pattern
const patternCanvas = document.createElement('canvas');
const pCtx = patternCanvas.getContext('2d');
const patternSize = 150;
patternCanvas.width = patternSize;
patternCanvas.height = patternSize;
const imageData = pCtx.createImageData(patternSize, patternSize);
const data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
const val = Math.random() * 55 + 200; // Light-grey noise
data[i] = val;
data[i + 1] = val;
data[i + 2] = val;
data[i + 3] = 255;
}
pCtx.putImageData(imageData, 0, 0);
const paperPattern = ctx.createPattern(patternCanvas, 'repeat');
// 3. Composite everything together on the main canvas
// Start with the original image
ctx.drawImage(originalImg, 0, 0);
// Apply crumpled lighting effect using the generated map
ctx.globalCompositeOperation = 'soft-light';
ctx.globalAlpha = crumpleIntensity;
ctx.drawImage(lightCanvas, 0, 0);
// Apply paper grain texture
if (paperPattern) {
ctx.globalCompositeOperation = 'multiply';
ctx.globalAlpha = grainIntensity;
ctx.fillStyle = paperPattern;
ctx.fillRect(0, 0, width, height);
}
// Reset context state to default values
ctx.globalCompositeOperation = 'source-over';
ctx.globalAlpha = 1.0;
return canvas;
}
Apply Changes