You can edit the below JavaScript code to customize the image tool.
Apply Changes
async function processImage(originalImg, effectCount = 5) {
// 1. Setup Canvas
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const w = originalImg.naturalWidth;
const h = originalImg.naturalHeight;
if (w === 0 || h === 0) {
// Handle cases where the image has no dimensions
canvas.width = 1;
canvas.height = 1;
return canvas;
}
canvas.width = w;
canvas.height = h;
// Draw the original image onto the canvas. Effects will be layered on this.
ctx.drawImage(originalImg, 0, 0, w, h);
// 2. Helper Utilities
const getRandom = (min, max) => Math.random() * (max - min) + min;
const getRandomInt = (min, max) => Math.floor(getRandom(min, max + 1));
// 3. Library of Effects
// Each function takes the context, width, and height and applies one random effect.
const effects = [
/**
* Applies a semi-transparent colored rectangle to a random area.
*/
(context, width, height) => {
const x = getRandomInt(0, width * 0.8);
const y = getRandomInt(0, height * 0.8);
const rectW = getRandomInt(width * 0.1, width - x);
const rectH = getRandomInt(height * 0.1, height - y);
const r = getRandomInt(0, 255);
const g = getRandomInt(0, 255);
const b = getRandomInt(0, 255);
const a = getRandom(0.1, 0.4);
context.fillStyle = `rgba(${r},${g},${b},${a})`;
context.fillRect(x, y, rectW, rectH);
},
/**
* Applies a random CSS-style filter (like blur, contrast, hue-rotate)
* to a random rectangular area of the canvas.
*/
(context, width, height) => {
const filters = [
`blur(${getRandom(0.5, 5)}px)`,
`contrast(${getRandom(0.5, 2.5)})`,
`brightness(${getRandom(0.5, 1.8)})`,
`saturate(${getRandom(0, 5)})`,
`hue-rotate(${getRandomInt(0, 360)}deg)`,
`sepia(${getRandom(0, 1)})`,
`invert(${getRandom(0, 1)})`,
];
const randomFilter = filters[getRandomInt(0, filters.length - 1)];
const x = getRandomInt(0, width * 0.8);
const y = getRandomInt(0, height * 0.8);
const rectW = getRandomInt(width * 0.2, width - x);
const rectH = getRandomInt(height * 0.2, height - y);
context.save();
context.beginPath();
context.rect(x, y, rectW, rectH);
context.clip();
context.filter = randomFilter;
// Drawing the canvas onto itself applies the filter to the clipped region
context.drawImage(context.canvas, 0, 0);
context.restore();
},
/**
* Creates a "glitch" effect by shifting a horizontal slice of the image.
*/
(context, width, height) => {
const y = getRandomInt(0, height - 2);
// Ensure slice height is at least 1 and doesn't exceed canvas bounds
const sliceHeight = getRandomInt(1, Math.max(1, Math.min(40, height - y)));
const offset = getRandomInt(-width * 0.2, width * 0.2);
if (offset === 0 || sliceHeight <= 0) return;
try {
const sliceData = context.getImageData(0, y, width, sliceHeight);
// Clearing the original slice area prevents visual duplication
context.clearRect(0, y, width, sliceHeight);
context.putImageData(sliceData, offset, y);
} catch (e) {
console.error("Glitch effect failed. This can happen with tainted canvases.", e);
}
},
/**
* Pixelates a random area of the image.
*/
(context, width, height) => {
const x = getRandomInt(0, width * 0.8);
const y = getRandomInt(0, height * 0.8);
const areaW = getRandomInt(width * 0.1, width * 0.5);
const areaH = getRandomInt(height * 0.1, height * 0.5);
const pixelSize = getRandomInt(5, 25);
const effectiveW = Math.min(areaW, width - x);
const effectiveH = Math.min(areaH, height - y);
if (effectiveW <= 0 || effectiveH <= 0) return;
// Efficiently pixelate by scaling down then scaling up with smoothing disabled
const tempCanvas = document.createElement('canvas');
const tempCtx = tempCanvas.getContext('2d');
const scaledW = Math.max(1, Math.ceil(effectiveW / pixelSize));
const scaledH = Math.max(1, Math.ceil(effectiveH / pixelSize));
tempCanvas.width = scaledW;
tempCanvas.height = scaledH;
tempCtx.drawImage(context.canvas, x, y, effectiveW, effectiveH, 0, 0, scaledW, scaledH);
context.save();
context.imageSmoothingEnabled = false;
context.drawImage(tempCanvas, 0, 0, scaledW, scaledH, x, y, effectiveW, effectiveH);
context.restore();
},
/**
* Adds random RGB noise to a specific area.
*/
(context, width, height) => {
const x = getRandomInt(0, width * 0.8);
const y = getRandomInt(0, height * 0.8);
const areaW = getRandomInt(width * 0.1, width - x);
const areaH = getRandomInt(height * 0.1, height - y);
const noiseAmount = getRandomInt(10, 80);
if (areaW <= 0 || areaH <= 0) return;
try {
const imageData = context.getImageData(x, y, areaW, areaH);
const data = imageData.data;
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));
data[i + 1] = Math.max(0, Math.min(255, data[i + 1] + noise));
data[i + 2] = Math.max(0, Math.min(255, data[i + 2] + noise));
}
context.putImageData(imageData, x, y);
} catch (e) {
console.error("Noise effect failed. This can happen with tainted canvases.", e);
}
},
];
// 4. Apply a number of random effects
const numEffectsToApply = Math.max(0, parseInt(effectCount, 10)) || 5;
for (let i = 0; i < numEffectsToApply; i++) {
// Pick a random effect from the library and apply it
const randomEffect = effects[getRandomInt(0, effects.length - 1)];
randomEffect(ctx, w, h);
}
// Ensure any lingering filter settings are cleared
ctx.filter = 'none';
// 5. Return the final canvas element
return canvas;
}
Apply Changes