You can edit the below JavaScript code to customize the image tool.
function processImage(originalImg, strength = 10, frequency = 0.05, tint = 'rgba(0, 80, 150, 0.3)', blurAmount = 2) {
const width = originalImg.naturalWidth;
const height = originalImg.naturalHeight;
if (width === 0 || height === 0) {
console.warn("Image has zero dimensions. It might not be loaded yet or is invalid.");
const placeholderCanvas = document.createElement('canvas');
placeholderCanvas.width = Math.max(100, width); // Use original dimensions if >0, else 100
placeholderCanvas.height = Math.max(100, height);
const phCtx = placeholderCanvas.getContext('2d');
phCtx.fillStyle = '#dddddd';
phCtx.fillRect(0, 0, placeholderCanvas.width, placeholderCanvas.height);
phCtx.fillStyle = 'red';
phCtx.font = 'bold 14px Arial';
phCtx.textAlign = 'center';
phCtx.textBaseline = 'middle';
phCtx.fillText("Image Invalid/Not Loaded", placeholderCanvas.width / 2, placeholderCanvas.height / 2);
return placeholderCanvas;
}
// 1. Create a source canvas to draw the original image and get its pixel data
const srcCanvas = document.createElement('canvas');
srcCanvas.width = width;
srcCanvas.height = height;
// Add { willReadFrequently: true } as an optimization hint for getImageData
const srcCtx = srcCanvas.getContext('2d', { willReadFrequently: true });
srcCtx.drawImage(originalImg, 0, 0, width, height);
let srcImageData;
try {
srcImageData = srcCtx.getImageData(0, 0, width, height);
} catch (e) {
console.error("Failed to get image data from source canvas.", e);
// This error often occurs due to CORS policy if the image is from a different origin.
// Return a canvas with the original image and an error message.
const errorCanvas = document.createElement('canvas');
errorCanvas.width = width;
errorCanvas.height = height;
const errCtx = errorCanvas.getContext('2d');
errCtx.drawImage(originalImg, 0, 0, width, height); // Draw the original image as a fallback
// Overlay a semi-transparent red box and an error message
errCtx.fillStyle = 'rgba(255, 0, 0, 0.6)';
errCtx.fillRect(0, 0, width, height);
errCtx.fillStyle = 'white';
errCtx.font = `bold ${Math.min(16, width / 15)}px Arial`; // Adjust font size based on image width
errCtx.textAlign = 'center';
errCtx.textBaseline = 'middle';
errCtx.fillText('Error: Could not process image.', width / 2, height / 2 - 10);
errCtx.font = `${Math.min(14, width / 20)}px Arial`;
errCtx.fillText('(Possibly CORS security issue)', width / 2, height / 2 + 10);
return errorCanvas;
}
const srcData = srcImageData.data;
// 2. Create a destination canvas for the processed image
const destCanvas = document.createElement('canvas');
destCanvas.width = width;
destCanvas.height = height;
const destCtx = destCanvas.getContext('2d');
const destImageData = destCtx.createImageData(width, height);
const destData = destImageData.data;
// 3. Apply underwater distortion effect (pixel manipulation)
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
// Calculate wave-like displacements for X and Y coordinates
// The constants (e.g., 0.3, 0.4) and use of sin/cos create irregular ripples.
const waveXTerm = y * frequency + x * frequency * 0.3; // Adjust 0.3 to change wave shape
const waveYTerm = x * frequency + y * frequency * 0.4; // Adjust 0.4 to change wave shape
const offsetX = strength * Math.sin(waveXTerm);
const offsetY = strength * Math.cos(waveYTerm); // Use cosine for Y for a different phase/pattern
// Calculate the source pixel coordinates after applying displacement
const srcX = x + offsetX;
const srcY = y + offsetY;
// Round to the nearest integer for source pixel (nearest neighbor sampling)
const iSrcX = Math.round(srcX);
const iSrcY = Math.round(srcY);
// Clamp coordinates to ensure they are within the image boundaries
const clampedX = Math.max(0, Math.min(width - 1, iSrcX));
const clampedY = Math.max(0, Math.min(height - 1, iSrcY));
// Calculate array indices for source and destination pixel data
const srcIndex = (clampedY * width + clampedX) * 4; // 4 bytes per pixel (R,G,B,A)
const destIndex = (y * width + x) * 4;
// Copy RGBA values from the source pixel to the destination pixel
destData[destIndex] = srcData[srcIndex]; // Red
destData[destIndex + 1] = srcData[srcIndex + 1]; // Green
destData[destIndex + 2] = srcData[srcIndex + 2]; // Blue
destData[destIndex + 3] = srcData[srcIndex + 3]; // Alpha (transparency)
}
}
// Put the distorted pixel data onto the destination canvas
destCtx.putImageData(destImageData, 0, 0);
// 4. Apply blur (if blurAmount is greater than 0)
// Canvas filters apply to drawing operations, not directly to ImageData.
// So, we draw the current destCanvas (distorted image) to a temporary canvas,
// then draw it back to destCanvas with the blur filter applied.
if (blurAmount > 0) {
const tempCanvasForBlur = document.createElement('canvas');
tempCanvasForBlur.width = width;
tempCanvasForBlur.height = height;
const tempCtxForBlur = tempCanvasForBlur.getContext('2d');
// Draw the current (distorted) content of destCanvas to the temporary canvas
tempCtxForBlur.drawImage(destCanvas, 0, 0);
// Clear destCanvas, set the blur filter, and draw the image from tempCanvas back to destCanvas
destCtx.clearRect(0, 0, width, height); // Clear before drawing blurred image
destCtx.filter = `blur(${blurAmount}px)`;
destCtx.drawImage(tempCanvasForBlur, 0, 0);
// Reset the filter to 'none' so it doesn't affect subsequent drawing operations (like tint)
destCtx.filter = 'none';
}
// 5. Apply tint overlay
// Check if the tint parameter is a valid string and not empty or 'none'
if (tint && typeof tint === 'string' && tint.trim() !== '' && tint.toLowerCase() !== 'none') {
// The `fillRect` method with an RGBA color string for `fillStyle` will blend the color
// over the existing content using the default 'source-over' composite operation.
destCtx.fillStyle = tint;
destCtx.fillRect(0, 0, width, height);
}
// 6. Return the fully processed canvas
return destCanvas;
}
Free Image Tool Creator
Can't find the image tool you're looking for? Create one based on your own needs now!
The Image Underwater Distortion Filter Effect Tool allows users to apply a creative underwater distortion effect to their images. By adjusting parameters such as distortion strength, frequency, tint, and blur amount, users can achieve various artistic effects that mimic the appearance of being viewed underwater. This tool is useful for graphic designers, content creators, and anyone looking to enhance their images with unique visual styles, or for those who want to create eye-catching social media posts or artwork.