Please bookmark this page to avoid losing your image tool!

Image Oasis Reflection Filter Effect Tool

(Free & Supports Bulk Upload)

Drag & drop your images here or

The result will appear here...
You can edit the below JavaScript code to customize the image tool.
function processImage(originalImg, p_waveAmplitude = 10, p_numWaves = 3, p_startAlpha = 0.7, p_endAlpha = 0.0) {
    // Parameter parsing and validation
    let waveAmplitude = Number(p_waveAmplitude);
    let numWaves = Number(p_numWaves);
    let startAlpha = Number(p_startAlpha);
    let endAlpha = Number(p_endAlpha);

    // Defaulting logic for NaN or otherwise invalid inputs
    waveAmplitude = isNaN(waveAmplitude) ? 10 : waveAmplitude;
    // Ensure numWaves is non-negative; if NaN or negative, default to 3.
    numWaves = (isNaN(numWaves) || numWaves < 0) ? 3 : numWaves;
    // Clamp alpha values to the [0,1] range; if NaN, use defaults.
    startAlpha = isNaN(startAlpha) ? 0.7 : Math.max(0, Math.min(1, startAlpha));
    endAlpha = isNaN(endAlpha) ? 0.0 : Math.max(0, Math.min(1, endAlpha));

    const imgWidth = originalImg.width;
    const imgHeight = originalImg.height;

    // Handle cases where the image might not be loaded or has zero dimensions
    if (imgWidth === 0 || imgHeight === 0) {
        const emptyCanvas = document.createElement('canvas');
        emptyCanvas.width = 1; 
        emptyCanvas.height = 1;
        // Optional: clear to ensure it's blank transparent
        const ctx = emptyCanvas.getContext('2d');
        if (ctx) {
          ctx.clearRect(0,0,1,1); 
        }
        return emptyCanvas;
    }

    // Main canvas that will contain the original image and its reflection
    const mainCanvas = document.createElement('canvas');
    mainCanvas.width = imgWidth;
    mainCanvas.height = imgHeight * 2; // Double height for reflection
    const mainCtx = mainCanvas.getContext('2d', { willReadFrequently: true });

    // 1. Draw the original image onto the top half of the main canvas
    mainCtx.drawImage(originalImg, 0, 0, imgWidth, imgHeight);

    // 2. Create the reflection
    // Temporary canvas to prepare the reflection (flipped and rippled)
    const reflectionCanvas = document.createElement('canvas');
    reflectionCanvas.width = imgWidth;
    reflectionCanvas.height = imgHeight;
    const reflectionCtx = reflectionCanvas.getContext('2d', { willReadFrequently: true });

    // Flip the image vertically and draw it onto the reflectionCanvas
    reflectionCtx.save();
    reflectionCtx.translate(0, imgHeight);
    reflectionCtx.scale(1, -1);
    reflectionCtx.drawImage(originalImg, 0, 0, imgWidth, imgHeight);
    reflectionCtx.restore(); // Restore context to normal for getImageData/putImageData

    // Apply ripple effect if waveAmplitude and numWaves are effective
    if (waveAmplitude !== 0 && numWaves > 0) {
        const sourceImageData = reflectionCtx.getImageData(0, 0, imgWidth, imgHeight);
        const sourceData = sourceImageData.data;
        const outputImageData = reflectionCtx.createImageData(imgWidth, imgHeight);
        const outputData = outputImageData.data;

        const effectiveWaveFrequency = (numWaves * 2 * Math.PI) / imgHeight;

        for (let y = 0; y < imgHeight; y++) {
            // Calculate horizontal displacement for this row
            const displacement = waveAmplitude * Math.sin(y * effectiveWaveFrequency);
            for (let x = 0; x < imgWidth; x++) {
                // Determine the source X coordinate, applying the displacement
                let srcX = Math.round(x - displacement);
                
                // Clamp source X to be within image bounds to avoid reading outside pixels
                srcX = Math.max(0, Math.min(imgWidth - 1, srcX));

                const dstIdx = (y * imgWidth + x) * 4; // Destination pixel index
                const srcIdx = (y * imgWidth + srcX) * 4; // Source pixel index

                // Copy RGBA pixel data
                outputData[dstIdx]     = sourceData[srcIdx];
                outputData[dstIdx + 1] = sourceData[srcIdx + 1];
                outputData[dstIdx + 2] = sourceData[srcIdx + 2];
                outputData[dstIdx + 3] = sourceData[srcIdx + 3];
            }
        }
        // Put the rippled image data back onto the reflectionCanvas, overwriting the simply-flipped image
        reflectionCtx.putImageData(outputImageData, 0, 0);
    }
    // At this point, reflectionCanvas holds the flipped image, possibly with ripples.

    // Draw the prepared reflection (from reflectionCanvas) onto the bottom half of the main canvas
    mainCtx.drawImage(reflectionCanvas, 0, imgHeight);

    // 3. Apply a vertical alpha gradient to make the reflection fade out
    mainCtx.save();
    // Use 'destination-in' composite operation: the existing content (reflection) is kept
    // where it's covered by the new shape (gradient rectangle). The alpha of the new shape
    // determines the alpha of the kept content.
    mainCtx.globalCompositeOperation = 'destination-in';
    
    const gradient = mainCtx.createLinearGradient(0, imgHeight, 0, imgHeight * 2);
    gradient.addColorStop(0, `rgba(0,0,0,${startAlpha})`); // Alpha at the reflection line (top of reflection)
    gradient.addColorStop(1, `rgba(0,0,0,${endAlpha})`);   // Alpha at the bottom of the reflection

    mainCtx.fillStyle = gradient;
    mainCtx.fillRect(0, imgHeight, imgWidth, imgHeight); // Apply gradient to the reflection area
    
    mainCtx.restore(); // Restore globalCompositeOperation to default ('source-over')

    return mainCanvas;
}

Free Image Tool Creator

Can't find the image tool you're looking for?
Create one based on your own needs now!

Description

The Image Oasis Reflection Filter Effect Tool allows users to create stunning reflective effects on images. By applying a ripple effect to the reflection, users can modify parameters such as wave amplitude and number of waves to achieve a variety of artistic looks. This tool is particularly useful for graphic designers, photographers, or anyone looking to enhance their images for presentations, social media posts, or digital art. The gradient alpha feature provides an option for the reflection to fade out, adding a professional touch to the final result.

Leave a Reply

Your email address will not be published. Required fields are marked *