Please bookmark this page to avoid losing your image tool!

Image Laces Adder

(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, 
    laceColor = "#eeeeee", 
    laceThickness = "8", 
    eyeletCount = "6", 
    edgeMargin = "40", 
    addBow = "true"
) {
    const canvas = document.createElement("canvas");
    const width = originalImg.width;
    const height = originalImg.height;
    canvas.width = width;
    canvas.height = height;
    const ctx = canvas.getContext("2d");

    // Draw original image
    ctx.drawImage(originalImg, 0, 0);

    const count = Math.max(2, parseInt(eyeletCount, 10));
    const thickness = parseFloat(laceThickness);
    const margin = Math.min(parseFloat(edgeMargin), width / 4);
    const drawBow = String(addBow).toLowerCase() === "true" || addBow === "1";
    
    // Allocate space at the bottom if we are drawing a bow
    const bowSpace = drawBow ? Math.min(150, height * 0.25) : margin;
    
    const startY = margin;
    let endY = height - bowSpace;
    
    // Fallback if image aspect ratio is extreme
    if (endY <= startY) {
        endY = height - margin;
    }
    
    const spacing = (endY - startY) / (count - 1);
    const leftX = margin;
    const rightX = width - margin;
    
    // Helper to draw a straight lace segment
    const drawLaceSegment = (x1, y1, x2, y2) => {
        ctx.shadowColor = 'rgba(0, 0, 0, 0.7)';
        ctx.shadowBlur = 6;
        ctx.shadowOffsetX = 2;
        ctx.shadowOffsetY = 4;
        
        ctx.lineCap = 'round';
        ctx.lineJoin = 'round';

        // Base lace
        ctx.beginPath();
        ctx.moveTo(x1, y1);
        ctx.lineTo(x2, y2);
        ctx.lineWidth = thickness;
        ctx.strokeStyle = laceColor;
        ctx.stroke();

        ctx.shadowColor = 'transparent';
        
        // Inner highlights to make it look rounded
        ctx.beginPath();
        ctx.moveTo(x1, y1);
        ctx.lineTo(x2, y2);
        ctx.lineWidth = thickness * 0.4;
        ctx.strokeStyle = 'rgba(255, 255, 255, 0.4)';
        ctx.stroke();

        // Inner shadow texture 
        ctx.beginPath();
        ctx.moveTo(x1, y1);
        ctx.lineTo(x2, y2);
        ctx.lineWidth = thickness * 0.8;
        ctx.strokeStyle = 'rgba(0, 0, 0, 0.1)';
        ctx.stroke();
    };

    // Helper to draw curved lace (for bows and loose ends)
    const drawLaceCurve = (x1, y1, cp1x, cp1y, cp2x, cp2y, x2, y2) => {
        ctx.shadowColor = 'rgba(0, 0, 0, 0.6)';
        ctx.shadowBlur = 5;
        ctx.shadowOffsetX = 2;
        ctx.shadowOffsetY = 4;
        
        ctx.lineCap = 'round';
        ctx.lineJoin = 'round';

        ctx.beginPath();
        ctx.moveTo(x1, y1);
        ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x2, y2);
        ctx.lineWidth = thickness;
        ctx.strokeStyle = laceColor;
        ctx.stroke();

        ctx.shadowColor = 'transparent';
        
        ctx.beginPath();
        ctx.moveTo(x1, y1);
        ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x2, y2);
        ctx.lineWidth = thickness * 0.4;
        ctx.strokeStyle = 'rgba(255, 255, 255, 0.5)';
        ctx.stroke();

        ctx.beginPath();
        ctx.moveTo(x1, y1);
        ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x2, y2);
        ctx.lineWidth = thickness * 0.8;
        ctx.strokeStyle = 'rgba(0, 0, 0, 0.1)';
        ctx.stroke();
    };

    // 1. Draw main body laces (Crisscross pattern)
    // Starting horizontal straight connection at the top
    drawLaceSegment(leftX, startY, rightX, startY);
    
    for (let i = 0; i < count - 1; i++) {
        const y1 = startY + i * spacing;
        const y2 = startY + (i + 1) * spacing;
        
        // Alternate over/under layering for authenticity
        if (i % 2 === 0) {
            drawLaceSegment(leftX, y1, rightX, y2);
            drawLaceSegment(rightX, y1, leftX, y2);
        } else {
            drawLaceSegment(rightX, y1, leftX, y2);
            drawLaceSegment(leftX, y1, rightX, y2);
        }
    }

    // 2. Draw Eyelets (holes + metallic grommets) over the laces
    const eyeletRadius = Math.max(6, thickness * 0.9); 
    const rimThickness = Math.max(3, thickness * 0.4);

    for (let i = 0; i < count; i++) {
        const y = startY + i * spacing;
        const coords = [leftX, rightX];
        
        coords.forEach((x, index) => {
            // Shadow behind the eyelet to separate from image
            ctx.shadowColor = 'rgba(0,0,0,0.6)';
            ctx.shadowBlur = 4;
            ctx.shadowOffsetX = 1;
            ctx.shadowOffsetY = 2;
            
            // Draw baseline for shadow
            ctx.beginPath();
            ctx.arc(x, y, eyeletRadius + rimThickness / 2, 0, Math.PI * 2);
            ctx.fillStyle = '#666666';
            ctx.fill();

            ctx.shadowColor = 'transparent';
            
            // Black hole to "swallow" the lace lines
            ctx.beginPath();
            ctx.arc(x, y, eyeletRadius, 0, Math.PI * 2);
            ctx.fillStyle = '#181818';
            ctx.fill();

            // Inner dark rim shadow for depth
            ctx.beginPath();
            ctx.arc(x, y, eyeletRadius, 0, Math.PI * 2);
            ctx.lineWidth = 2;
            ctx.strokeStyle = '#050505';
            ctx.stroke();

            // Draw metallic ring (grommet)
            ctx.beginPath();
            ctx.arc(x, y, eyeletRadius + rimThickness / 2, 0, Math.PI * 2);
            ctx.lineWidth = rimThickness;
            
            // Create metallic gradient
            const directionMultiplier = index === 0 ? 1 : -1;
            const grad = ctx.createLinearGradient(
                x - eyeletRadius * directionMultiplier, 
                y - eyeletRadius, 
                x + eyeletRadius * directionMultiplier, 
                y + eyeletRadius
            );
            grad.addColorStop(0, '#f0f0f0');
            grad.addColorStop(0.3, '#999999');
            grad.addColorStop(0.7, '#666666');
            grad.addColorStop(1, '#cccccc');
            
            ctx.strokeStyle = grad;
            ctx.stroke();
        });
    }

    // 3. Draw finishing Bow if requested
    if (drawBow && (endY < height)) {
        const bowY = endY;
        const centerX = (leftX + rightX) / 2;
        const loopW = Math.max(30, (rightX - leftX) * 0.35);
        const loopH = Math.min(60, loopW * 0.8);

        // Curving strings emerging from last eyelet void, merging to center knot
        drawLaceCurve(leftX, bowY, leftX + loopW*0.4, bowY + loopH*0.4, centerX - loopW*0.2, bowY, centerX, bowY);
        drawLaceCurve(rightX, bowY, rightX - loopW*0.4, bowY + loopH*0.4, centerX + loopW*0.2, bowY, centerX, bowY);

        // Left "bunny ear" loop
        drawLaceCurve(centerX, bowY, centerX - loopW*1.2, bowY - loopH, centerX - loopW*1.6, bowY + loopH, centerX, bowY);
        // Right "bunny ear" loop
        drawLaceCurve(centerX, bowY, centerX + loopW*1.2, bowY - loopH, centerX + loopW*1.6, bowY + loopH, centerX, bowY);

        // Left dangling tail
        drawLaceCurve(centerX, bowY, centerX - loopW*0.2, bowY + loopH, centerX - loopW*0.4, bowY + loopH*2, centerX - loopW*0.6, bowY + loopH*2.5);
        // Right dangling tail
        drawLaceCurve(centerX, bowY, centerX + loopW*0.2, bowY + loopH, centerX + loopW*0.4, bowY + loopH*2, centerX + loopW*0.6, bowY + loopH*2.5);

        // The Knot
        ctx.shadowColor = 'rgba(0,0,0,0.6)';
        ctx.shadowBlur = 5;
        ctx.shadowOffsetY = 3;
        
        ctx.beginPath();
        ctx.arc(centerX, bowY, thickness, 0, Math.PI * 2);
        ctx.fillStyle = laceColor;
        ctx.fill();
        ctx.shadowColor = 'transparent';
        
        // Knot highlight for texture
        ctx.beginPath();
        ctx.arc(centerX - thickness*0.2, bowY - thickness*0.2, thickness * 0.35, 0, Math.PI * 2);
        ctx.fillStyle = 'rgba(255,255,255,0.4)';
        ctx.fill();
    }

    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 Laces Adder is a creative tool that overlays a realistic lace-up pattern onto any uploaded image. It simulates a shoelace effect by drawing crisscrossed laces, metallic eyelets (grommets), and an optional decorative bow at the bottom. Users can customize the appearance of the laces by adjusting the color, thickness, the number of eyelets, and the margin from the edges. This tool is ideal for creating fun social media overlays, designing playful graphic elements, or applying a ‘shoe’ aesthetic to photos for artistic projects.

Leave a Reply

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

Other Image Tools:

Pardon

Country Ball Style Image Generator

Au Courant Image Generator

Image Farewell Message Generator

Image Gothic Style Filter Converter

Image Decorum Tool

Lazy Butterfly Effect and Inverted Image Effect Generator

MoreTestosteroneCityNight Image Effect Generator

Photo To Atomic Blonde Logo Style Converter

Photo To Ouija Origin Of Evil Logo Style Converter

Particle Dust Image Effect Generator

Chromatic Aberration Image Effect Generator

Soft Focus Blur Image Effect Generator

Wii Menu Chirp Echo Image Effect Generator

Sunrise Bloom Image Effect Generator

Morning Mist Overlay Image Effect Generator

Dewdrop Refraction Image Effect Generator

Golden Hour Glow Image Effect Generator

Lights Out Movie Poster

Lights Out Sky Scream Roller Coaster Movie Poster Generator

Lights Out Sky Scream Roller Coaster Movie Poster Website Image

Lights Out Sky Scream Roller Coaster Movie Poster Image

Empty Texas State Driver License Generator

Editable Realistic State Driver License Photo Template Generator

Photo To Skype Incoming Call Video Converter for Mac

Photo To Skype Incoming Call Video Converter

Photo To Skype Incoming Call Background Converter

Photo To Video Trailer Creator

Cybernatural Conjuring Teaser Poster Generator

Unfriended Conjuring Movie Poster Image

Annabelle Comes Home Movie Poster

Annabelle Creation Movie Poster

Annabelle Movie Poster 2014

The Conjuring Last Rites Movie Poster

The Conjuring The Devil Made Me Do It Movie Poster

The Conjuring 2 Movie Poster

See All →