You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, bubbleCount = 50, bubbleOpacity = 0.6) {
const bubbles = parseInt(bubbleCount, 10) || 50;
const opacity = parseFloat(bubbleOpacity) || 0.6;
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const width = originalImg.width;
const height = originalImg.height;
canvas.width = width;
canvas.height = height;
// Draw the original image onto the canvas
ctx.drawImage(originalImg, 0, 0, width, height);
// Apply composite operation to make the bubbles blend softly with the image
ctx.globalCompositeOperation = "screen";
const minRadius = Math.max(width, height) * 0.02;
const maxRadius = Math.max(width, height) * 0.12;
for (let i = 0; i < bubbles; i++) {
// Randomize bubble position, size, and hue
const r = minRadius + Math.random() * (maxRadius - minRadius);
const x = Math.random() * (width + r * 2) - r;
const y = Math.random() * (height + r * 2) - r;
// Random pastel hues for a slight iridescent/soap bubble effect
const hue = Math.floor(Math.random() * 360);
// Create main bubble body (soft radial gradient)
const bubbleGrad = ctx.createRadialGradient(x, y, r * 0.4, x, y, r);
bubbleGrad.addColorStop(0, `hsla(${hue}, 70%, 80%, 0)`);
bubbleGrad.addColorStop(0.7, `hsla(${hue}, 70%, 80%, ${opacity * 0.2})`);
bubbleGrad.addColorStop(0.95, `hsla(${hue}, 80%, 90%, ${opacity})`);
bubbleGrad.addColorStop(1, `hsla(${hue}, 80%, 90%, 0)`);
ctx.fillStyle = bubbleGrad;
ctx.beginPath();
ctx.arc(x, y, r, 0, Math.PI * 2);
ctx.fill();
// Add a soft white highlight to make the bubble look 3D and shiny
const hx = x - r * 0.35;
const hy = y - r * 0.35;
const hr = r * 0.25;
const highlightGrad = ctx.createRadialGradient(hx, hy, 0, hx, hy, hr);
highlightGrad.addColorStop(0, `rgba(255, 255, 255, ${opacity * 0.8})`);
highlightGrad.addColorStop(1, `rgba(255, 255, 255, 0)`);
ctx.fillStyle = highlightGrad;
ctx.beginPath();
ctx.arc(hx, hy, hr, 0, Math.PI * 2);
ctx.fill();
// Add a secondary smaller reflection on the opposite side
const hx2 = x + r * 0.4;
const hy2 = y + r * 0.4;
const hr2 = r * 0.15;
const highlightGrad2 = ctx.createRadialGradient(hx2, hy2, 0, hx2, hy2, hr2);
highlightGrad2.addColorStop(0, `rgba(255, 255, 255, ${opacity * 0.4})`);
highlightGrad2.addColorStop(1, `rgba(255, 255, 255, 0)`);
ctx.fillStyle = highlightGrad2;
ctx.beginPath();
ctx.arc(hx2, hy2, hr2, 0, Math.PI * 2);
ctx.fill();
}
// Reset composite operation
ctx.globalCompositeOperation = "source-over";
return canvas;
}
Apply Changes