Please bookmark this page to avoid losing your image tool!

Image Bullet Trajectory Filter Effect

(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,
    centerXPercent = 50,
    centerYPercent = 50,
    numTrajectories = 50,
    maxTrajectoryLength = 100,
    minTrajectoryLength = 20,
    trajectoryThickness = 1,
    trajectoryColor = 'rgba(255, 255, 255, 0.8)',
    startOffset = 0
) {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    // Set canvas dimensions to the original image's dimensions.
    // It's assumed originalImg is loaded, so naturalWidth/Height are available.
    // If originalImg is not loaded, naturalWidth/Height might be 0.
    // The caller should ensure originalImg is loaded (e.g., via originalImg.onload).
    canvas.width = originalImg.naturalWidth || 300; // Fallback width if naturalWidth is 0
    canvas.height = originalImg.naturalHeight || 150; // Fallback height if naturalHeight is 0

    // Draw the original image onto the canvas
    if (originalImg.naturalWidth > 0 && originalImg.naturalHeight > 0) {
        ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
    } else {
        // Optionally, draw a placeholder if image is not loaded/invalid
        ctx.fillStyle = '#cccccc';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        ctx.fillStyle = '#000000';
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        ctx.fillText('Image not loaded', canvas.width / 2, canvas.height / 2);
    }


    // --- Parameter Parsing and Sanitization ---

    let p_centerXPercent = parseFloat(centerXPercent);
    if (isNaN(p_centerXPercent)) {
        p_centerXPercent = 50; // Fallback to default from signature
    }

    let p_centerYPercent = parseFloat(centerYPercent);
    if (isNaN(p_centerYPercent)) {
        p_centerYPercent = 50; // Fallback to default from signature
    }

    const cx = (p_centerXPercent / 100) * canvas.width;
    const cy = (p_centerYPercent / 100) * canvas.height;
    
    let p_numTrajectories = parseInt(numTrajectories, 10);
    // If p_numTrajectories is NaN or <0, the loop `for (let i = 0; i < p_numTrajectories; i++)` later
    // will not execute, effectively drawing 0 trajectories. This is an acceptable outcome.
    // No explicit fallback to default (e.g., 50) needed here, as 0 trajectories is a safe result of invalid input.

    let p_minLen = parseFloat(minTrajectoryLength);
    if (isNaN(p_minLen)) {
        p_minLen = 20; // Fallback to default from signature
    }

    let p_maxLen = parseFloat(maxTrajectoryLength);
    if (isNaN(p_maxLen)) {
        p_maxLen = 100; // Fallback to default from signature
    }

    // Ensure minLength is not greater than maxLength, and lengths are not negative
    if (p_minLen > p_maxLen) {
        [p_minLen, p_maxLen] = [p_maxLen, p_minLen]; // Swap them
    }
    if (p_minLen < 0) p_minLen = 0;
    if (p_maxLen < 0) p_maxLen = 0; // Will be at least p_minLen (so >=0) after check & potential swap

    let p_thickness = parseFloat(trajectoryThickness);
    // ctx.lineWidth will handle p_thickness. (NaN > 0) is false.
    // If p_thickness is NaN or <=0, it will be set to 1 below.

    const p_color = String(trajectoryColor); // Ensures color is a string
    
    let p_startOffset = parseFloat(startOffset);
    if (isNaN(p_startOffset) || p_startOffset < 0) {
        p_startOffset = 0; // Fallback to 0 if NaN or negative
    }

    // --- End of Parameter Parsing and Sanitization ---


    // Set line properties for the trajectories
    ctx.strokeStyle = p_color;
    ctx.lineWidth = (p_thickness > 0) ? p_thickness : 1; // Ensure lineWidth is positive, default to 1
    ctx.lineCap = 'round'; // Options: 'butt', 'round', 'square'. 'round' gives softer ends.

    // Draw the trajectories
    // The loop condition handles p_numTrajectories being NaN, negative, or zero safely.
    for (let i = 0; i < p_numTrajectories; i++) {
        const angle = Math.random() * 2 * Math.PI; // Random angle (0 to 2*PI radians)

        // Calculate a random length for this specific trajectory within the min/max range
        const currentTrajectoryLength = p_minLen + Math.random() * (p_maxLen - p_minLen);
        
        // Calculate start and end points of the trajectory line
        const startX = cx + p_startOffset * Math.cos(angle);
        const startY = cy + p_startOffset * Math.sin(angle);

        const endX = cx + (p_startOffset + currentTrajectoryLength) * Math.cos(angle);
        const endY = cy + (p_startOffset + currentTrajectoryLength) * Math.sin(angle);

        // Draw the line
        ctx.beginPath();
        ctx.moveTo(startX, startY);
        ctx.lineTo(endX, endY);
        ctx.stroke();
    }

    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 Bullet Trajectory Filter Effect tool is designed to add visually striking bullet trajectory effects to images. Users can specify the number of trajectories, their lengths, thickness, and color, allowing for customization based on their creative vision. This tool is suitable for enhancing images in gaming, action photography, or graphic design, where a dynamic and action-packed aesthetic is desired. Whether you’re looking to create compelling graphics for promotional material or simply experimenting with artistic effects, this tool provides a versatile solution for adding unique visual elements to your images.

Leave a Reply

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