Please bookmark this page to avoid losing your image tool!

Image Fingerprint Scan 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, lineRGBColor = "0,200,50", lineWidth = 1, lineSpacing = 4, centerOffsetXRatio = 0, centerOffsetYRatio = 0, distortion = 8, noiseFrequency = 5, minLineOpacity = 0.1, maxLineOpacity = 0.7, imageBlendOpacity = 1.0) {

    // Ensure numeric parameters are valid and within sensible ranges
    lineWidth = Math.max(0, Number(lineWidth));
    lineSpacing = Math.max(1, Number(lineSpacing)); // Must be at least 1
    centerOffsetXRatio = Number(centerOffsetXRatio);
    centerOffsetYRatio = Number(centerOffsetYRatio);
    distortion = Math.max(0, Number(distortion));
    noiseFrequency = Number(noiseFrequency); // Can be any number, typically small integers
    minLineOpacity = Math.max(0, Math.min(1, Number(minLineOpacity)));
    maxLineOpacity = Math.max(0, Math.min(1, Number(maxLineOpacity)));
    imageBlendOpacity = Math.max(0, Math.min(1, Number(imageBlendOpacity)));

    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    canvas.width = originalImg.width;
    canvas.height = originalImg.height;

    if (canvas.width === 0 || canvas.height === 0) {
        return canvas; // Or throw an error for invalid image dimensions
    }
    
    // Draw the original image with the specified blend opacity
    if (imageBlendOpacity > 0) {
        ctx.globalAlpha = imageBlendOpacity;
        ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
        ctx.globalAlpha = 1.0; // Reset global alpha for subsequent drawing
    }


    // Create a temporary canvas to get pixel data from the original image
    // This is used to determine brightness for modulating line opacity
    const tempCanvas = document.createElement('canvas');
    const tempCtx = tempCanvas.getContext('2d');
    tempCanvas.width = canvas.width;
    tempCanvas.height = canvas.height;
    tempCtx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
    const imageData = tempCtx.getImageData(0, 0, canvas.width, canvas.height);

    // Parse lineRGBColor string "R,G,B" into numeric R, G, B values
    const colorParts = lineRGBColor.split(',');
    const r = parseInt(colorParts[0], 10) || 0;
    const g = parseInt(colorParts[1], 10) || 0;
    const b = parseInt(colorParts[2], 10) || 0;

    // Calculate the center of the fingerprint pattern
    const actualCenterX = canvas.width / 2 + centerOffsetXRatio * canvas.width;
    const actualCenterY = canvas.height / 2 + centerOffsetYRatio * canvas.height;

    ctx.lineWidth = lineWidth;
    if (lineWidth === 0) { // No lines to draw if lineWidth is 0
        return canvas;
    }

    // Helper function to get brightness (luminance) at a point (0-1 range)
    function getBrightness(x, y, imgData, imgWidth, imgHeight) {
        const ix = Math.round(x);
        const iy = Math.round(y);
        // Return 0 for points outside image bounds (treat as dark)
        if (ix < 0 || ix >= imgWidth || iy < 0 || iy >= imgHeight) {
            return 0; 
        }
        const pixelIdx = (iy * imgWidth + ix) * 4;
        const R = imgData.data[pixelIdx];
        const G = imgData.data[pixelIdx + 1];
        const B = imgData.data[pixelIdx + 2];
        // Standard luminance calculation
        return (0.299 * R + 0.587 * G + 0.114 * B) / 255;
    }

    // Determine the maximum radius needed to cover the entire canvas from the fingerprint center
    const distToCorner1 = Math.sqrt(actualCenterX**2 + actualCenterY**2);
    const distToCorner2 = Math.sqrt((canvas.width - actualCenterX)**2 + actualCenterY**2);
    const distToCorner3 = Math.sqrt(actualCenterX**2 + (canvas.height - actualCenterY)**2);
    const distToCorner4 = Math.sqrt((canvas.width - actualCenterX)**2 + (canvas.height - actualCenterY)**2);
    const maxLoopRadius = Math.max(distToCorner1, distToCorner2, distToCorner3, distToCorner4) + lineSpacing;

    // Iterate outwards from the center, drawing concentric, distorted lines
    for (let radius = 0; radius < maxLoopRadius; radius += lineSpacing) {
        let prevX = NaN;
        let prevY = NaN;
        
        // Calculate number of angular steps for this radius.
        // More steps for larger radii to maintain segment detail.
        const circumference = 2 * Math.PI * radius;
        // Target segment length aims to balance detail and performance.
        // It's based on distortion (more detail for higher distortion) and lineSpacing.
        const targetSegmentLength = Math.max(1, distortion / 2, lineSpacing / 2); 
        const numAngleSteps = (radius === 0 && circumference === 0) ? 1 : Math.max(20, Math.ceil(circumference / targetSegmentLength));


        for (let i = 0; i <= numAngleSteps; i++) {
            const angle = (i / numAngleSteps) * 2 * Math.PI;

            // Apply sinusoidal distortion to the radius
            // The 'radius * 0.1' term makes the pattern evolve with increasing radius
            const rOffset = Math.sin(angle * noiseFrequency + radius * 0.1) * distortion * 0.5;
            const currentR = radius + rOffset;

            // Calculate point coordinates with added random jitter
            const x = actualCenterX + currentR * Math.cos(angle) + (Math.random() - 0.5) * distortion * 0.5;
            const y = actualCenterY + currentR * Math.sin(angle) + (Math.random() - 0.5) * distortion * 0.5;

            if (i > 0 && !isNaN(prevX) && !isNaN(prevY)) {
                // Get brightness at the midpoint of the current segment
                const midX = (x + prevX) / 2;
                const midY = (y + prevY) / 2;
                const brightness = getBrightness(midX, midY, imageData, canvas.width, canvas.height);
                
                // Modulate line opacity based on brightness
                let alpha = minLineOpacity + (maxLineOpacity - minLineOpacity) * brightness;
                alpha = Math.max(0, Math.min(1, alpha)); // Clamp alpha to [0, 1]

                // Draw the segment if its alpha is above a small threshold
                if (alpha > 0.005) { 
                    ctx.beginPath();
                    ctx.moveTo(prevX, prevY);
                    ctx.lineTo(x, y);
                    ctx.strokeStyle = `rgba(${r}, ${g}, ${b}, ${alpha})`;
                    ctx.stroke();
                }
            }
            prevX = x;
            prevY = y;
        }
    }
    return canvas;
}

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 Fingerprint Scan Filter Effect Tool provides a unique way to enhance images by applying a distinctive fingerprint-like effect. Users can customize various parameters, such as line color, thickness, spacing, distortion, and opacity, to achieve personalized artistic effects. This tool can be particularly useful for graphic designers, artists looking to create digital artworks, or anyone wanting to add a stylized filter to their images for social media or presentations.

Leave a Reply

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