You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, dropCount = 40, minSize = 15, maxSize = 60, magnification = 1.3) {
// Parse parameters
const count = Math.max(1, parseInt(dropCount, 10) || 40);
const zoomConfig = Math.max(1, parseFloat(magnification) || 1.3);
let cfgMin = parseInt(minSize, 10) || 15;
let cfgMax = parseInt(maxSize, 10) || 60;
// Create the canvas
const canvas = document.createElement('canvas');
const width = originalImg.width;
const height = originalImg.height;
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
// Draw the original base image
ctx.drawImage(originalImg, 0, 0, width, height);
// Ensure safe sizes so drops don't exceed image dimensions
const maxAllowedSize = Math.min(width, height) / 2;
cfgMax = Math.min(cfgMax, maxAllowedSize);
cfgMin = Math.min(cfgMin, cfgMax);
if (cfgMin <= 0) cfgMin = 1;
// Generate random dewdrops
for (let i = 0; i < count; i++) {
// Randomize radius and position for the droplet
const r = cfgMin + Math.random() * (cfgMax - cfgMin);
const cx = r + Math.random() * (width - 2 * r);
const cy = r + Math.random() * (height - 2 * r);
ctx.save();
// 1. Draw outer drop shadow for the 3D spherical effect
ctx.save();
ctx.beginPath();
ctx.arc(cx, cy, r, 0, Math.PI * 2);
ctx.shadowColor = 'rgba(0, 0, 0, 0.6)';
ctx.shadowBlur = r * 0.4;
ctx.shadowOffsetX = r * 0.15;
ctx.shadowOffsetY = r * 0.3;
ctx.fillStyle = '#000'; // Fill needed for shadow to render
ctx.fill();
ctx.restore(); // Clear shadow settings
// 2. Draw the refracted/magnified background inside the drop
ctx.save();
ctx.beginPath();
ctx.arc(cx, cy, r, 0, Math.PI * 2);
ctx.clip(); // Restrict drawing to the droplet boundary
// Zoom into the image around the drop's center
ctx.translate(cx, cy);
ctx.scale(zoomConfig, zoomConfig);
ctx.translate(-cx, -cy);
ctx.drawImage(originalImg, 0, 0, width, height);
ctx.restore(); // Restore from clipping and scaling
// 3. Apply internal lighting and volume (Inner shadows / Highlights)
ctx.save();
ctx.beginPath();
ctx.arc(cx, cy, r, 0, Math.PI * 2);
ctx.clip();
// Volume Shading: Darkens edges to give a convex spherical appearance
// Assuming light source is at top-left, the bottom-right shadow inside the drop is darker
const volumeGrad = ctx.createRadialGradient(cx - r * 0.2, cy - r * 0.2, r * 0.3, cx, cy, r);
volumeGrad.addColorStop(0, 'rgba(0, 0, 0, 0)');
volumeGrad.addColorStop(0.7, 'rgba(0, 0, 0, 0.15)');
volumeGrad.addColorStop(1, 'rgba(0, 0, 0, 0.7)');
ctx.fillStyle = volumeGrad;
ctx.fill();
// Internal reflection at the bottom (Light passing through)
// A bright crescent at the bottom right where the light concentrates
const ambientGrad = ctx.createLinearGradient(cx - r, cy - r, cx + r, cy + r);
ambientGrad.addColorStop(0, 'rgba(255, 255, 255, 0)');
ambientGrad.addColorStop(0.65, 'rgba(255, 255, 255, 0)');
ambientGrad.addColorStop(0.9, 'rgba(255, 255, 255, 0.4)');
ambientGrad.addColorStop(1, 'rgba(255, 255, 255, 0.8)');
ctx.fillStyle = ambientGrad;
ctx.fill();
ctx.restore();
// 4. Specular Highlight (The direct reflection of the light source)
// Main stretched highlight
const hlX = cx - r * 0.4;
const hlY = cy - r * 0.4;
const hlRX = r * 0.35;
const hlRY = r * 0.15;
ctx.save();
ctx.beginPath();
if (ctx.ellipse) {
// Angle the ellipse reflection to face the top-left corner (-45 degrees)
ctx.ellipse(hlX, hlY, hlRX, hlRY, -Math.PI / 4, 0, Math.PI * 2);
} else {
// Fallback for very old browsers missing ctx.ellipse
ctx.arc(hlX, hlY, hlRY, 0, Math.PI * 2);
}
const hlGrad = ctx.createLinearGradient(hlX - hlRX, hlY - hlRY, hlX + hlRX, hlY + hlRY);
hlGrad.addColorStop(0, 'rgba(255, 255, 255, 0.95)');
hlGrad.addColorStop(1, 'rgba(255, 255, 255, 0.1)');
ctx.fillStyle = hlGrad;
ctx.fill();
// Tiny crisp secondary highlight closer to the top-left edge for realism
ctx.beginPath();
ctx.arc(cx - r * 0.6, cy - r * 0.55, r * 0.06, 0, Math.PI * 2);
ctx.fillStyle = 'rgba(255, 255, 255, 0.9)';
ctx.fill();
ctx.restore();
ctx.restore(); // Restore context to default for the next droplet
}
return canvas;
}
Apply Changes