You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, isStoryFormat = "true", effectIntensity = "1.0") {
const isStory = String(isStoryFormat).toLowerCase() === "true";
const intensity = Math.max(0, Math.min(2, parseFloat(effectIntensity) || 1.0));
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
// Establish dimensions: 1080x1920 (9:16) for typical stories, otherwise original dimensions
let w = originalImg.width;
let h = originalImg.height;
if (isStory) {
w = 1080;
h = 1920;
}
canvas.width = w;
canvas.height = h;
if (isStory) {
// Draw the background: a zoomed-in, heavily blurred, darkened version of the original image
ctx.filter = "blur(45px) brightness(0.4)";
const scaleCover = Math.max(w / originalImg.width, h / originalImg.height);
const cw = originalImg.width * scaleCover;
const ch = originalImg.height * scaleCover;
const cx = (w - cw) / 2;
const cy = (h - ch) / 2;
ctx.drawImage(originalImg, cx, cy, cw, ch);
ctx.filter = "none";
// Calculate foreground image fit (leaving margins)
const margin = 80;
const mw = w - margin * 2;
const mh = h - margin * 2;
const scaleFit = Math.min(mw / originalImg.width, mh / originalImg.height);
const iw = originalImg.width * scaleFit;
const ih = originalImg.height * scaleFit;
const ix = (w - iw) / 2;
const iy = (h - ih) / 2;
// Apply a cinematic drop shadow to the center image
ctx.shadowColor = "rgba(0, 0, 0, 0.45)";
ctx.shadowBlur = 40;
ctx.shadowOffsetY = 15;
// Draw with rounded corners for the "Story" pop-out aesthetic
ctx.save();
ctx.beginPath();
const radius = 24;
ctx.moveTo(ix + radius, iy);
ctx.lineTo(ix + iw - radius, iy);
ctx.quadraticCurveTo(ix + iw, iy, ix + iw, iy + radius);
ctx.lineTo(ix + iw, iy + ih - radius);
ctx.quadraticCurveTo(ix + iw, iy + ih, ix + iw - radius, iy + ih);
ctx.lineTo(ix + radius, iy + ih);
ctx.quadraticCurveTo(ix, iy + ih, ix, iy + ih - radius);
ctx.lineTo(ix, iy + radius);
ctx.quadraticCurveTo(ix, iy, ix + radius, iy);
ctx.closePath();
// Fill white to cast the shadow, then clip to map the image over it
ctx.fillStyle = "white";
ctx.fill();
ctx.shadowColor = "transparent";
ctx.clip();
ctx.drawImage(originalImg, ix, iy, iw, ih);
ctx.restore();
} else {
ctx.drawImage(originalImg, 0, 0, w, h);
}
// Apply the "Hush" Image Effect: soft, muted, dreamy cinematic fade with a cool tint and vignette
try {
const imgData = ctx.getImageData(0, 0, w, h);
const data = imgData.data;
const maxDist = Math.sqrt((w / 2) ** 2 + (h / 2) ** 2);
for (let i = 0; i < data.length; i += 4) {
let r = data[i];
let g = data[i + 1];
let b = data[i + 2];
// Calculate luminance
const lum = 0.299 * r + 0.587 * g + 0.114 * b;
// 1. Desaturate slightly (muted tone)
const desat = 0.45 * intensity;
r = r + (lum - r) * desat;
g = g + (lum - g) * desat;
b = b + (lum - b) * desat;
// 2. Hush color grading (fade contrast, lift shadows, push cool/blue tint)
r = (r * 0.82) + (18 * intensity);
g = (g * 0.85) + (26 * intensity);
b = (b * 0.88) + (38 * intensity);
// 3. Ambient Vignette
const px = (i / 4) % w;
const py = Math.floor((i / 4) / w);
const dx = px - (w / 2);
const dy = py - (h / 2);
const dist = Math.sqrt(dx * dx + dy * dy);
const vgf = Math.pow(dist / maxDist, 2) * 0.65 * intensity;
const vignetteAmount = Math.max(0, 1 - vgf);
r *= vignetteAmount;
g *= vignetteAmount;
b *= vignetteAmount;
// Constrain RGB
data[i] = Math.max(0, Math.min(255, r));
data[i + 1] = Math.max(0, Math.min(255, g));
data[i + 2] = Math.max(0, Math.min(255, b));
}
ctx.putImageData(imgData, 0, 0);
// Optional film/grain noise to finalize the mood
if (intensity > 0) {
const tempCanvas = document.createElement("canvas");
tempCanvas.width = w;
tempCanvas.height = h;
const tCtx = tempCanvas.getContext("2d");
const noiseData = tCtx.createImageData(w, h);
for (let i = 0; i < noiseData.data.length; i += 4) {
const val = Math.random() * 255;
noiseData.data[i] = val;
noiseData.data[i + 1] = val;
noiseData.data[i + 2] = val;
noiseData.data[i + 3] = 12 * intensity; // Subtle overlay opacity
}
tCtx.putImageData(noiseData, 0, 0);
ctx.globalCompositeOperation = "overlay";
ctx.drawImage(tempCanvas, 0, 0);
ctx.globalCompositeOperation = "source-over"; // Reset for subsequent paints
}
} catch (e) {
// Fallback for CORS disabled images - returns the composite without the pixel manipulation
console.warn("Could not apply pixel effects due to CORS constraints.", e);
}
return canvas;
}
Apply Changes