You can edit the below JavaScript code to customize the image tool.
Apply Changes
async function processImage(originalImg, bubbleCountFactor = 0.01, minBubbleSize = 1, maxBubbleSize = 4, bubbleColorRGB = "255,255,255", bubbleAlpha = 0.65) {
// --- Parameter Type Coercion and Validation ---
bubbleCountFactor = Number(bubbleCountFactor);
if (isNaN(bubbleCountFactor) || bubbleCountFactor < 0) {
console.warn(`Invalid bubbleCountFactor, defaulting to 0.01.`);
bubbleCountFactor = 0.01;
}
minBubbleSize = Number(minBubbleSize);
if (isNaN(minBubbleSize) || minBubbleSize < 0) {
console.warn(`Invalid minBubbleSize, defaulting to 1.`);
minBubbleSize = 1;
}
// Ensure minBubbleSize is at least a very small positive number if not 0, to avoid issues with radius 0
if (minBubbleSize === 0) minBubbleSize = 0.1;
maxBubbleSize = Number(maxBubbleSize);
if (isNaN(maxBubbleSize) || maxBubbleSize < minBubbleSize) {
console.warn(`Invalid maxBubbleSize, defaulting to be slightly larger than minBubbleSize.`);
maxBubbleSize = Math.max(minBubbleSize + 1, 4); // Ensure max is at least minBubbleSize, and a reasonable default.
}
bubbleAlpha = Number(bubbleAlpha);
if (isNaN(bubbleAlpha) || bubbleAlpha < 0 || bubbleAlpha > 1) {
console.warn(`Invalid bubbleAlpha, defaulting to 0.65.`);
bubbleAlpha = 0.65;
}
let r = 255, g = 255, b = 255; // Default bubble color components (white)
const colorParts = bubbleColorRGB.split(',').map(s => parseInt(s.trim(), 10));
if (colorParts.length === 3 && colorParts.every(c => !isNaN(c) && c >= 0 && c <= 255)) {
[r, g, b] = colorParts;
} else {
console.warn(`Invalid bubbleColorRGB string: "${bubbleColorRGB}". Defaulting to "255,255,255" (white).`);
// r, g, b are already set to default white
}
// --- Canvas Setup ---
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const imgWidth = originalImg.naturalWidth || originalImg.width;
const imgHeight = originalImg.naturalHeight || originalImg.height;
if (imgWidth === 0 || imgHeight === 0) {
console.error("Image has zero dimensions. Cannot process.");
// Return a tiny placeholder canvas
canvas.width = 1;
canvas.height = 1;
ctx.fillStyle = 'red'; // Indicate error
ctx.fillRect(0,0,1,1);
return canvas;
}
canvas.width = imgWidth;
canvas.height = imgHeight;
// Draw the original image onto the canvas
ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
// --- Fizz Effect Implementation ---
const numBubbles = Math.floor(canvas.width * canvas.height * bubbleCountFactor);
for (let i = 0; i < numBubbles; i++) {
const x = Math.random() * canvas.width;
const y = Math.random() * canvas.height;
// Ensure minBubbleSize is not greater than maxBubbleSize after potential modifications
const currentMinSize = Math.min(minBubbleSize, maxBubbleSize);
const radius = currentMinSize + Math.random() * (maxBubbleSize - currentMinSize);
if (radius <= 0) continue; // Skip bubbles with no size
// Create a radial gradient for each bubble
// The gradient center (x, y, 0) is the brightest point.
// The gradient outer circle (x, y, radius) is the edge of the bubble.
const gradient = ctx.createRadialGradient(x, y, 0, x, y, radius);
// Stop 1: Center of the bubble - bright highlight (typically whitish)
gradient.addColorStop(0, `rgba(255, 255, 255, ${bubbleAlpha * 0.9})`);
// Stop 2: Mid-section of the bubble - the main bubble color
gradient.addColorStop(0.7, `rgba(${r}, ${g}, ${b}, ${bubbleAlpha})`);
// Stop 3: Edge of the bubble - main bubble color, but more transparent
gradient.addColorStop(1, `rgba(${r}, ${g}, ${b}, ${bubbleAlpha * 0.15})`);
ctx.fillStyle = gradient;
ctx.beginPath();
ctx.arc(x, y, radius, 0, 2 * Math.PI);
ctx.fill();
}
return canvas;
}
Apply Changes