Please bookmark this page to avoid losing your image tool!

Image Cracked Screen 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,
    numMainCracks = 6,
    mainCrackColor = "rgba(240, 240, 240, 0.9)",
    maxCrackThickness = 5,
    minCrackThickness = 1,
    impactXPercent = -1, // -1 for random, 0-100 for specific percentage
    impactYPercent = -1, // -1 for random, 0-100 for specific percentage
    jaggedness = 10,      // Max perpendicular deviation for crack segments (pixels)
    crackSegmentLength = 25, // Average length of a segment in a crack line (pixels)
    addSecondaryCracks = 1, // 1 to add secondary cracks, 0 to disable
    secondaryCracksPerMain = 2, // Average number of secondary cracks per main crack
    secondaryCrackLengthFactor = 0.35, // Secondary crack length relative to its main crack
    secondaryCrackThicknessFactor = 0.6 // Secondary crack thickness relative to its main crack
) {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    const w = originalImg.naturalWidth;
    const h = originalImg.naturalHeight;

    if (w === 0 || h === 0) {
        canvas.width = w; // Could be 0
        canvas.height = h; // Could be 0
        console.warn("Image has zero width or height. Output might be empty or an error might occur.");
        // Depending on requirements, could throw an error or return an empty/minimal canvas
        if (w === 0 || h === 0) return canvas; // Return 0x0 canvas if image is 0x0
    }

    canvas.width = w;
    canvas.height = h;

    // Draw the original image onto the canvas
    ctx.drawImage(originalImg, 0, 0, w, h);

    // Sanitize numeric parameters
    numMainCracks = Math.max(0, parseInt(numMainCracks, 10) || 0);
    let nMaxCrackThickness = Math.max(0, parseFloat(maxCrackThickness) || 0);
    let nMinCrackThickness = Math.max(0, parseFloat(minCrackThickness) || 0);
    
    if (nMinCrackThickness > nMaxCrackThickness) {
        [nMinCrackThickness, nMaxCrackThickness] = [nMaxCrackThickness, nMinCrackThickness]; // Swap if min > max
    }
    // Ensure minCrackThickness is at least a very small positive number if max is positive, to avoid 0 thickness if max and min are same
    if (nMaxCrackThickness > 0 && nMinCrackThickness === 0) nMinCrackThickness = Math.min(0.1, nMaxCrackThickness);


    jaggedness = Math.max(0, parseFloat(jaggedness) || 0);
    crackSegmentLength = Math.max(5, parseFloat(crackSegmentLength) || 5); // Min segment length of 5px
    addSecondaryCracks = parseInt(addSecondaryCracks, 10) || 0;
    secondaryCracksPerMain = Math.max(0, parseInt(secondaryCracksPerMain, 10) || 0);
    secondaryCrackLengthFactor = Math.max(0, parseFloat(secondaryCrackLengthFactor) || 0);
    secondaryCrackThicknessFactor = Math.max(0, parseFloat(secondaryCrackThicknessFactor) || 0);


    // Helper function to draw a single jagged crack line
    function drawJaggedLine(context, x1, y1, x2, y2, thickness, currentJaggedness, currentSegmentLength) {
        context.beginPath();
        context.moveTo(x1, y1);

        const dx = x2 - x1;
        const dy = y2 - y1;
        const distance = Math.sqrt(dx * dx + dy * dy);

        if (distance === 0) {
            return; 
        }
        
        currentSegmentLength = Math.max(5, currentSegmentLength); // Ensure segment length is positive
        const numSegments = Math.max(1, Math.floor(distance / currentSegmentLength));

        const normalX = -dy / distance; 
        const normalY = dx / distance;

        for (let i = 1; i <= numSegments; i++) {
            const t = i / numSegments; 

            const currentTargetX = x1 + dx * t;
            const currentTargetY = y1 + dy * t;

            let actualX = currentTargetX;
            let actualY = currentTargetY;

            if (i < numSegments && currentJaggedness > 0) { 
                const randomOffset = (Math.random() - 0.5) * 2 * currentJaggedness;
                actualX += normalX * randomOffset;
                actualY += normalY * randomOffset;
            }
            context.lineTo(actualX, actualY);
        }

        context.lineWidth = Math.max(0.1, thickness); 
        context.stroke();
    }

    // Determine impact point of the cracks
    let impactX, impactY;
    const cleanImpactXPercent = parseFloat(impactXPercent);
    const cleanImpactYPercent = parseFloat(impactYPercent);

    if (cleanImpactXPercent >= 0 && cleanImpactXPercent <= 100) {
        impactX = w * (cleanImpactXPercent / 100);
    } else {
        impactX = Math.random() * w; 
    }
    if (cleanImpactYPercent >= 0 && cleanImpactYPercent <= 100) {
        impactY = h * (cleanImpactYPercent / 100);
    } else {
        impactY = Math.random() * h; 
    }
    impactX = Math.max(0, Math.min(w, impactX)); 
    impactY = Math.max(0, Math.min(h, impactY));

    ctx.strokeStyle = mainCrackColor;
    ctx.lineCap = "round";
    ctx.lineJoin = "round";

    const mainCracksData = [];

    // Generate and draw main cracks
    for (let i = 0; i < numMainCracks; i++) {
        const angle = Math.random() * Math.PI * 2;
        const length = (Math.random() * 0.6 + 0.4) * Math.max(w, h) * 0.85; 
        
        const endX = impactX + Math.cos(angle) * length;
        const endY = impactY + Math.sin(angle) * length;

        const thicknessRange = Math.max(0, nMaxCrackThickness - nMinCrackThickness);
        const crackThickness = nMinCrackThickness + Math.random() * thicknessRange;
        
        if (crackThickness <= 0) continue; // Skip if thickness is zero or less

        drawJaggedLine(ctx, impactX, impactY, endX, endY, crackThickness, jaggedness, crackSegmentLength);
        
        if (addSecondaryCracks !== 0) {
            const actualLength = Math.sqrt(Math.pow(endX - impactX, 2) + Math.pow(endY - impactY, 2));
            if (actualLength > 0) { 
                 mainCracksData.push({
                    startX: impactX, startY: impactY,
                    endX: endX, endY: endY,
                    mainAngle: angle,
                    mainLength: actualLength,
                    mainThickness: crackThickness
                });
            }
        }
    }

    // Generate and draw secondary cracks
    if (addSecondaryCracks !== 0 && mainCracksData.length > 0) {
        mainCracksData.forEach(mainCrack => {
            for (let j = 0; j < secondaryCracksPerMain; j++) {
                if (Math.random() < 0.8) { 
                    const t = Math.random() * 0.8 + 0.1; 
                    
                    const branchStartX = mainCrack.startX + (mainCrack.endX - mainCrack.startX) * t;
                    const branchStartY = mainCrack.startY + (mainCrack.endY - mainCrack.startY) * t;

                    const deviation = (Math.random() - 0.5) * Math.PI / 1.8; 
                    const secondaryAngle = mainCrack.mainAngle + deviation;
                    
                    const lengthRandomFactor = Math.random() * 0.5 + 0.5; 
                    const secondaryLength = mainCrack.mainLength * secondaryCrackLengthFactor * lengthRandomFactor;
                    
                    if (secondaryLength < Math.min(10, crackSegmentLength)) continue; 

                    const secondaryEndX = branchStartX + Math.cos(secondaryAngle) * secondaryLength;
                    const secondaryEndY = branchStartY + Math.sin(secondaryAngle) * secondaryLength;

                    const thicknessRandomFactor = Math.random() * 0.5 + 0.5;
                    let secThickness = mainCrack.mainThickness * secondaryCrackThicknessFactor * thicknessRandomFactor;
                    secThickness = Math.max(0.5, secThickness); // Absolute minimum thickness for secondary cracks
                    secThickness = Math.min(secThickness, mainCrack.mainThickness); // Don't exceed parent thickness

                    if (secThickness <= 0) continue;

                    const secJaggedness = jaggedness * (Math.random() * 0.3 + 0.6);
                    const secSegmentLength = crackSegmentLength * (Math.random() * 0.4 + 0.7);

                    drawJaggedLine(ctx, branchStartX, branchStartY, secondaryEndX, secondaryEndY, secThickness, secJaggedness, secSegmentLength);
                }
            }
        });
    }
    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 Cracked Screen Filter Effect Tool allows users to apply a visual effect to their images, simulating the appearance of a cracked screen. This tool provides various customization options, including the number of primary cracks, their thickness, color, and additional secondary cracks. It can be used for creative purposes, such as enhancing photos for social media, creating unique visual art, or adding a playful touch to digital images.

Leave a Reply

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