You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, durationInSeconds = 5, effect = 'top-down') {
// Ensure parameters are correct types and fallbacks
durationInSeconds = Number(durationInSeconds);
if (isNaN(durationInSeconds) || durationInSeconds <= 0) durationInSeconds = 5;
effect = String(effect).toLowerCase();
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const width = originalImg.width;
const height = originalImg.height;
canvas.width = width;
canvas.height = height;
// Initial placeholder background
ctx.fillStyle = '#e0e0e0';
ctx.fillRect(0, 0, width, height);
const loadTimeMs = durationInSeconds * 1000;
let startTime = null;
let lastScale = null;
let maxVisualProgress = 0;
function animate(currentTime) {
if (!startTime) startTime = currentTime;
const elapsed = currentTime - startTime;
let progress = Math.min(elapsed / loadTimeMs, 1);
if (effect === 'progressive') {
// Simulates interlaced / progressive image loading by drawing in increasingly sharp resolutions
let scale;
if (progress < 0.15) scale = 0.02;
else if (progress < 0.3) scale = 0.05;
else if (progress < 0.5) scale = 0.1;
else if (progress < 0.8) scale = 0.25;
else if (progress < 0.95) scale = 0.5;
else scale = 1.0;
if (scale !== lastScale) {
lastScale = scale;
ctx.clearRect(0, 0, width, height);
const sw = Math.max(1, Math.floor(width * scale));
const sh = Math.max(1, Math.floor(height * scale));
// Draw to a smaller off-screen canvas to capture downsampled image
const off = document.createElement('canvas');
off.width = sw;
off.height = sh;
const offCtx = off.getContext('2d');
offCtx.imageSmoothingEnabled = true;
offCtx.drawImage(originalImg, 0, 0, sw, sh);
// Draw back scaled-up and pixelated
ctx.imageSmoothingEnabled = false;
ctx.drawImage(off, 0, 0, sw, sh, 0, 0, width, height);
}
} else if (effect === 'blur') {
// Linearly clears up a blurred image over time
ctx.clearRect(0, 0, width, height);
let blurAmount = Math.max(0, (1 - progress) * 20);
if (progress === 1) blurAmount = 0;
ctx.filter = `blur(${blurAmount}px)`;
ctx.drawImage(originalImg, 0, 0, width, height);
ctx.filter = 'none';
} else {
// 'top-down' - Simulates a classic line-by-line dial-up modem load
// Adds a sine wave modifier to simulate random network connection stalling
let tempP = progress + 0.05 * Math.sin(progress * Math.PI * 10);
let chunkP = Math.floor(tempP * 50) / 50;
if (chunkP > maxVisualProgress) maxVisualProgress = chunkP;
if (progress >= 1) maxVisualProgress = 1;
ctx.clearRect(0, 0, width, height);
const currentHeight = Math.floor(maxVisualProgress * height);
// Draw placeholder color for the portion that "hasn't loaded" yet
ctx.fillStyle = '#e0e0e0';
ctx.fillRect(0, currentHeight, width, height - currentHeight);
if (currentHeight > 0) {
ctx.drawImage(
originalImg,
0, 0, width, currentHeight, // Source crop
0, 0, width, currentHeight // Destination crop
);
}
}
if (progress < 1) {
requestAnimationFrame(animate);
} else {
// Final polish step to ensure peak image quality is rendered
ctx.clearRect(0, 0, width, height);
ctx.imageSmoothingEnabled = true;
ctx.filter = 'none';
ctx.drawImage(originalImg, 0, 0, width, height);
}
}
// Start animation loop
requestAnimationFrame(animate);
return canvas;
}
Apply Changes