You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, amplitude = 15, frequency = 25, aquaTint = 50, poolBorderSize = 30) {
const canvas = document.createElement('canvas');
const width = originalImg.width;
const height = originalImg.height;
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
ctx.drawImage(originalImg, 0, 0);
const srcData = ctx.getImageData(0, 0, width, height);
const dstData = ctx.createImageData(width, height);
const srcPixels = srcData.data;
const dstPixels = dstData.data;
const amp = Number(amplitude);
const freq = Number(frequency);
const tint = Number(aquaTint);
// Apply Waterpark filter: underwater distortion, aqua-blue color, and light caustics
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
// Calculate overlapping sine waves for organic fluid distortion
const waveX = (y / freq) + Math.sin(x / (freq * 1.5));
const waveY = (x / freq) + Math.cos(y / (freq * 1.5));
const dx = amp * Math.sin(waveX);
const dy = amp * Math.cos(waveY);
let srcX = Math.floor(x + dx);
let srcY = Math.floor(y + dy);
// Clamp coordinates to image boundaries to prevent out-of-bounds mapping
srcX = Math.max(0, Math.min(width - 1, srcX));
srcY = Math.max(0, Math.min(height - 1, srcY));
const dstIdx = (y * width + x) * 4;
const srcIdx = (srcY * width + srcX) * 4;
// Generate water caustics (sunlight filtering through water waves)
const caustic = Math.sin(waveX * 2) * Math.cos(waveY * 2) * 25;
// Apply distortion, caustics light, and aqua color shifting
dstPixels[dstIdx] = Math.min(255, Math.max(0, srcPixels[srcIdx] + caustic)); // Red
dstPixels[dstIdx + 1] = Math.min(255, Math.max(0, srcPixels[srcIdx + 1] + tint * 0.5 + caustic)); // Green
dstPixels[dstIdx + 2] = Math.min(255, Math.max(0, srcPixels[srcIdx + 2] + tint + caustic)); // Blue
dstPixels[dstIdx + 3] = srcPixels[srcIdx + 3]; // Alpha
}
}
// Output the water effect onto canvas
ctx.putImageData(dstData, 0, 0);
// Apply Pool/Aquapark ceramic border tiles
const bw = Number(poolBorderSize);
if (bw > 0) {
// Automatically scale tile size so it forms a nice mosaic aesthetic
const tileSize = Math.max(10, Math.floor(bw / 2));
ctx.lineWidth = 1;
ctx.strokeStyle = "rgba(255, 255, 255, 0.9)"; // White tile grout
for (let y = 0; y < height; y += tileSize) {
for (let x = 0; x < width; x += tileSize) {
// Determine if coordinate is within the border boundaries
if (x < bw || x >= width - bw || y < bw || y >= height - bw) {
const isDark = (Math.floor(x / tileSize) + Math.floor(y / tileSize)) % 2 === 0;
// Aquapark pool mosaic colors
ctx.fillStyle = isDark ? "#29b6f6" : "#4fc3f7";
ctx.fillRect(x, y, tileSize, tileSize);
ctx.strokeRect(x, y, tileSize, tileSize);
// Add subtle inner glare to tiles for wet look
ctx.fillStyle = "rgba(255, 255, 255, 0.25)";
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x + tileSize / 1.5, y);
ctx.lineTo(x, y + tileSize / 1.5);
ctx.fill();
}
}
}
}
return canvas;
}
Apply Changes