You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, escapeIntensity = 85, barCount = 8, barThickness = 'auto', barColor = '#4a4f54', dramaticLighting = 100) {
const canvas = document.createElement('canvas');
const W = originalImg.width;
const H = originalImg.height;
canvas.width = W;
canvas.height = H;
const ctx = canvas.getContext('2d');
// 1. Draw Original Image
ctx.drawImage(originalImg, 0, 0, W, H);
const cx = W / 2;
const cy = H / 2;
// 2. Cinematic Vignette (Simulates dark cell / dramatic lighting around the edges)
const dl = Math.max(0, Math.min(100, Number(dramaticLighting))) / 100;
if (dl > 0) {
const vignette = ctx.createRadialGradient(cx, cy, Math.min(W, H) * 0.1, cx, cy, Math.max(W, H) * 0.85);
vignette.addColorStop(0, 'rgba(0, 0, 0, 0)');
vignette.addColorStop(0.4, `rgba(0, 0, 0, ${0.3 * dl})`);
vignette.addColorStop(1, `rgba(0, 0, 0, ${0.9 * dl})`);
ctx.fillStyle = vignette;
ctx.fillRect(0, 0, W, H);
}
// 3. Variables for Bars
const sev = Math.max(0, Number(escapeIntensity)) / 100;
const numBars = Math.max(0, Number(barCount));
const spacing = W / (numBars + 1);
// Auto scale thickness based on width so it looks consistently like solid bars
const thickness = barThickness === 'auto'
? Math.max(4, Math.floor(W / (numBars * 8)))
: Math.max(1, Number(barThickness));
// Bending math configurations
const R_x = W * 0.4; // Falloff radius for X dispersion
const max_push = W * 0.45 * sev; // How wide the opening becomes
// Precalculate paths for the bent bars
const barsData = [];
for (let i = 1; i <= numBars; i++) {
let x0 = i * spacing;
let dx = x0 - cx;
// Avoid strict zero to naturally push center bars apart
if (Math.abs(dx) < 1) dx = dx >= 0 ? 1 : -1;
let x_factor = Math.exp(-(dx * dx) / (2 * R_x * R_x));
let bar_push = max_push * x_factor * Math.sign(dx);
barsData.push({ x0, bar_push });
}
// Function to draw all bars with specific offsets and widths
const drawBarLayer = (offsetX, strokeStyle, lineWidth, isShadow = false) => {
if (!numBars) return;
ctx.beginPath();
barsData.forEach(b => {
let steps = Math.max(10, Math.floor(H / 20)); // Ensure smooth bends with enough subdivisions
for (let y = 0; y <= H + steps; y += steps) {
let clampY = Math.min(y, H);
let dy = clampY - cy;
// Curve is extreme at center, straight at top & bottom
let y_factor = Math.pow(Math.cos((dy / (H / 2)) * (Math.PI / 2)), 2);
let x = b.x0 + b.bar_push * y_factor + offsetX;
if (clampY === 0) ctx.moveTo(x, clampY);
else ctx.lineTo(x, clampY);
if (clampY === H) break;
}
});
ctx.lineJoin = 'round';
ctx.lineCap = 'butt';
if (isShadow) {
ctx.shadowColor = 'rgba(0, 0, 0, 0.8)';
ctx.shadowBlur = thickness * 1.5;
ctx.shadowOffsetX = thickness * 0.5;
ctx.shadowOffsetY = thickness * 0.4;
} else {
ctx.shadowColor = 'transparent';
}
ctx.lineWidth = lineWidth;
ctx.strokeStyle = strokeStyle;
ctx.stroke();
};
// 4. Draw the 3D Bent Metal Bars
// Shadow & Solid Base Black
drawBarLayer(0, '#000000', thickness, true);
// Main Solid Color Base
drawBarLayer(0, String(barColor), thickness * 0.85, false);
// Dark Left Edge (Cylindrical rim shading)
drawBarLayer(-thickness * 0.35, 'rgba(0, 0, 0, 0.7)', thickness * 0.15, false);
// Dark Right Edge
drawBarLayer(thickness * 0.35, 'rgba(0, 0, 0, 0.8)', thickness * 0.15, false);
// Metallic Highlight Shifted Left
drawBarLayer(-thickness * 0.1, 'rgba(255, 255, 255, 0.4)', thickness * 0.2, false);
// Core Highlight Reflection Strip
drawBarLayer(-thickness * 0.05, 'rgba(255, 255, 255, 0.2)', thickness * 0.05, false);
// 5. Build Top & Bottom Window Frames (locks in the structure)
const drawSill = (isTop) => {
let ft = thickness * 1.8;
let yBase = isTop ? 0 : H - ft;
// Window Sill Drop Shadow
ctx.shadowColor = 'rgba(0, 0, 0, 0.9)';
ctx.shadowBlur = thickness;
ctx.shadowOffsetY = isTop ? thickness * 0.3 : -thickness * 0.3;
ctx.fillStyle = '#060606'; // True base for deep shadow
ctx.fillRect(0, yBase, W, ft);
ctx.shadowColor = 'transparent';
// Base Sill Material
ctx.fillStyle = String(barColor);
ctx.fillRect(0, yBase + ft * 0.1, W, ft * 0.8);
// Top Facing Sill Highlight
ctx.fillStyle = 'rgba(255, 255, 255, 0.15)';
ctx.fillRect(0, yBase + ft * 0.12, W, ft * 0.25);
// Underside/Bottom Edge Shadows
ctx.fillStyle = 'rgba(0, 0, 0, 0.6)';
ctx.fillRect(0, yBase + ft * 0.65, W, ft * 0.25);
// Rivet strip or border line on frame
ctx.fillStyle = 'rgba(0, 0, 0, 0.3)';
ctx.fillRect(0, yBase + ft * (isTop ? 0.9 : 0.05), W, ft * 0.05);
};
if (numBars > 0) {
drawSill(true); // Top frame border
drawSill(false); // Bottom frame border
}
return canvas;
}
Apply Changes