You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, underwaterTint = "rgba(0, 150, 200, 0.35)", vignetteIntensity = 0.7, elementsCount = 80) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const width = originalImg.width;
const height = originalImg.height;
canvas.width = width;
canvas.height = height;
// 1. Draw the original image
ctx.drawImage(originalImg, 0, 0);
// 2. Apply a dreamy, soft glow (Wedding vibe)
const blurRadius = Math.max(width, height) * 0.01;
ctx.globalCompositeOperation = 'screen';
ctx.globalAlpha = 0.35;
ctx.filter = `blur(${blurRadius}px)`;
ctx.drawImage(originalImg, 0, 0);
// Reset settings
ctx.filter = 'none';
ctx.globalAlpha = 1.0;
// 3. Apply an underwater cyan/teal tint (Mermaid vibe)
ctx.globalCompositeOperation = 'color';
ctx.fillStyle = underwaterTint;
ctx.fillRect(0, 0, width, height);
// Add a deeper blue tone to multiply for a slight cinematic aquatic depth
ctx.globalCompositeOperation = 'multiply';
ctx.fillStyle = 'rgba(0, 40, 80, 0.25)';
ctx.fillRect(0, 0, width, height);
// Switch back to normal rendering for overlays
ctx.globalCompositeOperation = 'source-over';
// 4. Dark edges / Vignette (Detective's Case / Mystery vibe)
const intensity = parseFloat(vignetteIntensity) || 0.7;
const gradient = ctx.createRadialGradient(
width / 2, height / 2, Math.min(width, height) * 0.4,
width / 2, height / 2, Math.max(width, height) * 0.75
);
gradient.addColorStop(0, 'rgba(0, 20, 40, 0)');
gradient.addColorStop(1, `rgba(0, 15, 30, ${intensity})`);
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, width, height);
// 5. Draw underwater bubbles & wedding sparkles randomly
const count = parseInt(elementsCount) || 80;
for (let i = 0; i < count; i++) {
// Pseudo-random distribution
const x = Math.random() * width;
const y = Math.random() * height;
const size = (Math.random() * 0.02 + 0.005) * Math.min(width, height);
const isBubble = Math.random() > 0.25; // 75% bubbles, 25% sparkles
if (isBubble) {
// Draw Bubble
ctx.beginPath();
ctx.arc(x, y, size, 0, Math.PI * 2);
ctx.fillStyle = 'rgba(255, 255, 255, 0.08)';
ctx.fill();
ctx.lineWidth = Math.max(1, size * 0.1);
ctx.strokeStyle = 'rgba(255, 255, 255, 0.35)';
ctx.stroke();
// Inner light reflection on the bubble
ctx.beginPath();
ctx.arc(x - size * 0.3, y - size * 0.3, size * 0.2, 0, Math.PI * 2);
ctx.fillStyle = 'rgba(255, 255, 255, 0.6)';
ctx.fill();
} else {
// Draw Sparkle (Star)
ctx.save();
ctx.translate(x, y);
ctx.beginPath();
for (let j = 0; j < 4; j++) {
ctx.rotate(Math.PI / 2);
ctx.lineTo(0, size);
ctx.lineTo(size * 0.2, size * 0.2);
}
ctx.closePath();
ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
ctx.fill();
ctx.restore();
}
}
// 6. Imprint the Case Title: "Дело о Свадьбе Русалки" (Web-safe classic font)
const fontSize = Math.max(20, Math.floor(height * 0.06));
ctx.font = `italic 300 ${fontSize}px "Georgia", "Times New Roman", serif`;
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
// Add text shadow for readability
ctx.shadowColor = 'rgba(0, 0, 0, 0.8)';
ctx.shadowBlur = 8;
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
// Write text at the bottom center
ctx.fillStyle = 'rgba(255, 255, 255, 0.9)';
ctx.fillText("Дело о Свадьбе Русалки", width / 2, height - (fontSize * 0.5));
// Reset shadow for safe return
ctx.shadowColor = 'transparent';
return canvas;
}
Apply Changes