Please bookmark this page to avoid losing your image tool!

Image Animal Track 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.
async function processImage(originalImg, trackType = "paw", trackColor = "black", trackSize = 30, trackDensity = 0.1, trackOpacity = 0.7, randomRotation = "true") {

    // Helper function to draw a paw print
    function _drawPaw(ctx, x, y, size, color, angle) {
        ctx.save();
        ctx.translate(x, y);
        ctx.rotate(angle);
        ctx.fillStyle = color;

        // Main pad (rounded rectangle)
        const mainPadWidth = size * 0.8;
        const mainPadHeight = size * 0.6;
        const mainPadYOffset = size * 0.15; // Move main pad down a bit from center
        const mainPadRadius = size * 0.15; // Corner radius

        ctx.beginPath();
        ctx.moveTo(-mainPadWidth / 2 + mainPadRadius, mainPadYOffset - mainPadHeight / 2); // Top-left corner start
        // Top edge
        ctx.lineTo(mainPadWidth / 2 - mainPadRadius, mainPadYOffset - mainPadHeight / 2);
        // Top-right corner
        ctx.quadraticCurveTo(mainPadWidth / 2, mainPadYOffset - mainPadHeight / 2, mainPadWidth / 2, mainPadYOffset - mainPadHeight / 2 + mainPadRadius);
        // Right edge
        ctx.lineTo(mainPadWidth / 2, mainPadYOffset + mainPadHeight / 2 - mainPadRadius);
        // Bottom-right corner
        ctx.quadraticCurveTo(mainPadWidth / 2, mainPadYOffset + mainPadHeight / 2, mainPadWidth / 2 - mainPadRadius, mainPadYOffset + mainPadHeight / 2);
        // Bottom edge
        ctx.lineTo(-mainPadWidth / 2 + mainPadRadius, mainPadYOffset + mainPadHeight / 2);
        // Bottom-left corner
        ctx.quadraticCurveTo(-mainPadWidth / 2, mainPadYOffset + mainPadHeight / 2, -mainPadWidth / 2, mainPadYOffset + mainPadHeight / 2 - mainPadRadius);
        // Left edge
        ctx.lineTo(-mainPadWidth / 2, mainPadYOffset - mainPadHeight / 2 + mainPadRadius);
        // Top-left corner end
        ctx.quadraticCurveTo(-mainPadWidth / 2, mainPadYOffset - mainPadHeight / 2, -mainPadWidth / 2 + mainPadRadius, mainPadYOffset - mainPadHeight / 2);
        ctx.closePath();
        ctx.fill();

        // Toes (4, slightly oval)
        const toeSize = size * 0.22; 
        const toeRadiusX = toeSize * 0.8; // Width of toe
        const toeRadiusY = toeSize;       // Height of toe
        const toeY = -size * 0.3;         // Y position of toes relative to track center

        const toePositions = [
            { dx: -size * 0.33, dy: toeY - size * 0.05, angle: -Math.PI / 12 }, // Outer left
            { dx: -size * 0.11, dy: toeY - size * 0.10, angle: -Math.PI / 24 }, // Inner left
            { dx:  size * 0.11, dy: toeY - size * 0.10, angle:  Math.PI / 24 }, // Inner right
            { dx:  size * 0.33, dy: toeY - size * 0.05, angle:  Math.PI / 12  }  // Outer right
        ];

        for (const pos of toePositions) {
            ctx.save();
            ctx.translate(pos.dx, pos.dy);
            ctx.rotate(pos.angle);
            ctx.beginPath();
            ctx.ellipse(0, 0, toeRadiusX, toeRadiusY, 0, 0, Math.PI * 2);
            ctx.fill();
            ctx.restore();
        }
        ctx.restore();
    }

    // Helper function to draw a hoof print (deer-like, two ellipses)
    function _drawHoof(ctx, x, y, size, color, angle) {
        ctx.save();
        ctx.translate(x, y);
        ctx.rotate(angle); // Overall track rotation
        ctx.fillStyle = color;

        const toeLength = size * 0.6; // Length of each half of the hoof
        const toeWidth = size * 0.25; // Width of each half
        const toeAngle = Math.PI / 16; // Slight outward angle for each toe (e.g., ~11 degrees)
        const toeSeparation = size * 0.12; // Distance from center to each toe's own center

        // Left toe
        ctx.save();
        ctx.translate(-toeSeparation, 0); // Move to left toe's position
        ctx.rotate(-toeAngle); // Rotate left toe slightly outwards
        ctx.beginPath();
        ctx.ellipse(0, 0, toeWidth / 2, toeLength / 2, 0, 0, Math.PI * 2);
        ctx.fill();
        ctx.restore();

        // Right toe
        ctx.save();
        ctx.translate(toeSeparation, 0); // Move to right toe's position
        ctx.rotate(toeAngle); // Rotate right toe slightly outwards
        ctx.beginPath();
        ctx.ellipse(0, 0, toeWidth / 2, toeLength / 2, 0, 0, Math.PI * 2);
        ctx.fill();
        ctx.restore();
        
        ctx.restore(); // Restores from the main track rotation and translation
    }

    // Helper function to draw a bird track
    function _drawBirdTrack(ctx, x, y, size, color, angle) {
        ctx.save();
        ctx.translate(x, y);
        ctx.rotate(angle);
        
        const toeLength = size * 0.45;
        const lineWidth = Math.max(1.5, size * 0.1); // Ensure lines are visible
        
        ctx.strokeStyle = color;
        ctx.fillStyle = color; // For claws/pads at the end of toes
        ctx.lineWidth = lineWidth;
        ctx.lineCap = 'round';
        ctx.lineJoin = 'round';

        const originOffsetY = 0; // Toes radiate from the center point (x,y)

        // Central forward toe
        ctx.beginPath();
        ctx.moveTo(0, originOffsetY);
        ctx.lineTo(0, -toeLength + originOffsetY);
        ctx.stroke();
        ctx.beginPath(); // "Claw" or "pad"
        ctx.arc(0, -toeLength + originOffsetY, lineWidth / 1.5, 0, Math.PI * 2);
        ctx.fill();

        // Left forward toe (angled)
        const sideToeAngle = Math.PI / 5.5; // Angle for side toes (approx 32 degrees)
        ctx.beginPath();
        ctx.moveTo(0, originOffsetY);
        ctx.lineTo(toeLength * Math.sin(-sideToeAngle), -toeLength * Math.cos(-sideToeAngle) + originOffsetY);
        ctx.stroke();
        ctx.beginPath(); // "Claw" or "pad"
        ctx.arc(toeLength * Math.sin(-sideToeAngle), -toeLength * Math.cos(-sideToeAngle) + originOffsetY, lineWidth / 1.5, 0, Math.PI * 2);
        ctx.fill();

        // Right forward toe (angled)
        ctx.beginPath();
        ctx.moveTo(0, originOffsetY);
        ctx.lineTo(toeLength * Math.sin(sideToeAngle), -toeLength * Math.cos(sideToeAngle) + originOffsetY);
        ctx.stroke();
        ctx.beginPath(); // "Claw" or "pad"
        ctx.arc(toeLength * Math.sin(sideToeAngle), -toeLength * Math.cos(sideToeAngle) + originOffsetY, lineWidth / 1.5, 0, Math.PI * 2);
        ctx.fill();

        // Backward toe
        const backToeLength = toeLength * 0.7;
        ctx.beginPath();
        ctx.moveTo(0, originOffsetY);
        ctx.lineTo(0, backToeLength + originOffsetY); // Points downwards
        ctx.stroke();
        ctx.beginPath(); // "Claw" or "pad"
        ctx.arc(0, backToeLength + originOffsetY, lineWidth / 1.5, 0, Math.PI * 2);
        ctx.fill();
        
        ctx.restore();
    }

    // --- Main processImage function logic ---

    // Parameter parsing & validation
    const pTrackSize = (Number.isFinite(Number(trackSize)) && Number(trackSize) > 0) ? Number(trackSize) : 30;
    const pTrackDensity = (Number.isFinite(Number(trackDensity)) && Number(trackDensity) >= 0) ? Number(trackDensity) : 0.1;
    const pTrackOpacity = (Number.isFinite(Number(trackOpacity)) && Number(trackOpacity) >= 0 && Number(trackOpacity) <= 1) ? Number(trackOpacity) : 0.7;
    const pRandomRotation = String(randomRotation).toLowerCase() === 'true';
    const pTrackColor = String(trackColor); // Default handled by signature
    const pTrackType = String(trackType);   // Default handled by signature

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

    canvas.width = originalImg.naturalWidth || originalImg.width || 0;
    canvas.height = originalImg.naturalHeight || originalImg.height || 0;

    if (canvas.width === 0 || canvas.height === 0) {
        // Return empty (0x0) canvas if image dimensions are zero
        console.warn("Image has zero width or height.");
        return canvas;
    }

    // Draw the original image
    ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);

    // Set track properties for drawing
    ctx.globalAlpha = pTrackOpacity;

    // Calculate number of tracks based on density
    // Density is a factor of how many tracks of size (pTrackSize * pTrackSize) would cover the canvas
    const numTracks = Math.max(0, Math.floor(((canvas.width * canvas.height) / (pTrackSize * pTrackSize)) * pTrackDensity));

    for (let i = 0; i < numTracks; i++) {
        const R_x = Math.random() * canvas.width;  // Random x position
        const R_y = Math.random() * canvas.height; // Random y position
        
        let R_angle = 0; // Default angle if not random
        if (pRandomRotation) {
            R_angle = Math.random() * Math.PI * 2; // Random angle
        }

        // Call the appropriate drawing function based on trackType
        if (pTrackType === "paw") {
            _drawPaw(ctx, R_x, R_y, pTrackSize, pTrackColor, R_angle);
        } else if (pTrackType === "hoof") {
            _drawHoof(ctx, R_x, R_y, pTrackSize, pTrackColor, R_angle);
        } else if (pTrackType === "bird") {
            _drawBirdTrack(ctx, R_x, R_y, pTrackSize, pTrackColor, R_angle);
        }
        // Add more track types here with else if (pTrackType === "newType") { _drawNewType(...); }
    }
    
    ctx.globalAlpha = 1.0; // Reset global alpha to default

    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 Animal Track Filter Effect Tool allows users to enhance their images by overlaying realistic animal track patterns, such as paw prints, hoof prints, and bird tracks. Users can customize the size, color, density, and opacity of the tracks, as well as apply random rotations to create a natural look. This tool is useful for various creative projects, including digital art, photography, and animal-themed designs, enabling users to add a playful or thematic element to their visuals.

Leave a Reply

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