Please bookmark this page to avoid losing your image tool!

Cardboard Love Image Generator

(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, heartScale = 0.85, cardboardColor = "#b58b59", shadowAlpha = 0.65) {
    // 1. Initialize Canvas
    const canvas = document.createElement('canvas');
    const w = originalImg.width;
    const h = originalImg.height;
    canvas.width = w;
    canvas.height = h;
    const ctx = canvas.getContext('2d');
    
    // Parse parameters to correct types
    const scale = Number(heartScale) || 0.85;
    const alpha = Number(shadowAlpha) || 0.65;
    const minDim = Math.min(w, h);
    const heartSize = minDim * scale;
    
    // 2. Draw original image onto the main canvas
    ctx.drawImage(originalImg, 0, 0, w, h);
    
    // Apply a subtle warm vintage filter to the photo for the "love" aesthetic
    ctx.fillStyle = 'rgba(255, 180, 150, 0.15)';
    ctx.fillRect(0, 0, w, h);
    
    // 3. Create Cardboard Layer Canvas
    const cbCanvas = document.createElement('canvas');
    cbCanvas.width = w;
    cbCanvas.height = h;
    const cbCtx = cbCanvas.getContext('2d');
    
    // Fill base cardboard color
    cbCtx.fillStyle = cardboardColor;
    cbCtx.fillRect(0, 0, w, h);
    
    // Generate Corrugated Cardboard Texture (Vertical lines)
    cbCtx.lineWidth = Math.max(1, minDim * 0.002);
    const gap = Math.max(4, minDim * 0.015);
    
    // Dark ridges
    cbCtx.strokeStyle = 'rgba(0, 0, 0, 0.06)';
    for (let i = 0; i < w; i += gap) {
        cbCtx.beginPath(); 
        cbCtx.moveTo(i, 0); 
        cbCtx.lineTo(i, h); 
        cbCtx.stroke();
    }
    // Highlighting ridges for 3D corrugated effect
    cbCtx.strokeStyle = 'rgba(255, 255, 255, 0.06)';
    for (let i = gap / 2; i < w; i += gap) {
        cbCtx.beginPath(); 
        cbCtx.moveTo(i, 0); 
        cbCtx.lineTo(i, h); 
        cbCtx.stroke();
    }
    
    // Add noise to simulate cardboard pulp and texture
    const numNoiseScratches = Math.floor((w * h) / 1200);
    cbCtx.fillStyle = 'rgba(0, 0, 0, 0.08)';
    for (let i = 0; i < numNoiseScratches; i++) {
        cbCtx.fillRect(Math.random() * w, Math.random() * h, 1 + Math.random() * 2, 1 + Math.random() * 2);
    }
    cbCtx.fillStyle = 'rgba(255, 255, 255, 0.08)';
    for (let i = 0; i < numNoiseScratches; i++) {
        cbCtx.fillRect(Math.random() * w, Math.random() * h, 1 + Math.random() * 2, 1 + Math.random() * 2);
    }
    
    // 4. Cut the Heart-shaped Hole
    function createHeartPath(context, cx, cy, size) {
        context.beginPath();
        let hw = size * 0.43;
        let hh = size * 0.43;
        
        context.moveTo(cx, cy - hh * 0.3); // Top dip
        
        // Right half of heart
        context.bezierCurveTo(
            cx + hw * 0.9, cy - hh * 0.9, 
            cx + hw * 1.5, cy + hh * 0.2, 
            cx, cy + hh * 1.1
        ); // Bottom point
        
        // Left half of heart
        context.bezierCurveTo(
            cx - hw * 1.5, cy + hh * 0.2, 
            cx - hw * 0.9, cy - hh * 0.9, 
            cx, cy - hh * 0.3
        ); // Back to top dip
    }
    
    cbCtx.globalCompositeOperation = 'destination-out';
    createHeartPath(cbCtx, w / 2, h / 2, heartSize);
    cbCtx.fill();
    
    cbCtx.globalCompositeOperation = 'source-over';
    
    // Add raw corrugated inner edge details to the cutout heart hole
    cbCtx.strokeStyle = 'rgba(0, 0, 0, 0.12)';
    cbCtx.lineWidth = gap * 0.4;
    cbCtx.stroke();
    cbCtx.strokeStyle = 'rgba(255, 255, 255, 0.1)';
    cbCtx.lineWidth = gap * 0.15;
    cbCtx.stroke();
    
    // 5. Add "Cardboard Love" Artistic Touches (Tape & Marker Scribbles)
    function drawTape(x, y, tw, th, angle) {
        cbCtx.save();
        cbCtx.translate(x, y);
        cbCtx.rotate(angle);
        
        // Masking tape base
        cbCtx.fillStyle = 'rgba(230, 220, 190, 0.85)';
        cbCtx.fillRect(-tw / 2, -th / 2, tw, th);
        
        // Tape wrinkles
        cbCtx.strokeStyle = 'rgba(255, 255, 255, 0.3)';
        cbCtx.lineWidth = Math.max(1, tw * 0.02);
        cbCtx.beginPath(); cbCtx.moveTo(-tw / 2, -th / 4); cbCtx.lineTo(tw / 2, -th / 4); cbCtx.stroke();
        cbCtx.beginPath(); cbCtx.moveTo(-tw / 2, th / 3); cbCtx.lineTo(tw / 2, th / 3); cbCtx.stroke();
        cbCtx.restore();
    }
    
    const tapeW = minDim * 0.25;
    const tapeH = minDim * 0.06;
    drawTape(w * 0.1, h * 0.1, tapeW, tapeH, -Math.PI / 4.5);
    drawTape(w * 0.9, h * 0.1, tapeW, tapeH, Math.PI / 3.8);
    drawTape(w * 0.1, h * 0.9, tapeW, tapeH, Math.PI / 4.2);
    drawTape(w * 0.9, h * 0.9, tapeW, tapeH, -Math.PI / 5);
    
    function scribbleMarkerHeart(x, y, size, angle) {
        cbCtx.save();
        cbCtx.translate(x, y);
        cbCtx.rotate(angle);
        cbCtx.strokeStyle = 'rgba(220, 30, 40, 0.85)'; // Red marker color
        cbCtx.lineWidth = Math.max(2, size * 0.1);
        cbCtx.lineCap = 'round';
        cbCtx.lineJoin = 'round';
        
        // Marker pass 1
        cbCtx.beginPath();
        cbCtx.moveTo(0, size * 0.2);
        cbCtx.bezierCurveTo(size * 0.5, -size * 0.3, size * 1.2, size * 0.3, 0, size);
        cbCtx.bezierCurveTo(-size * 1.2, size * 0.3, -size * 0.5, -size * 0.3, 0, size * 0.2);
        cbCtx.stroke();
        
        // Marker pass 2 (for scribble look)
        cbCtx.beginPath();
        cbCtx.moveTo(-size * 0.05, size * 0.25);
        cbCtx.bezierCurveTo(size * 0.45, -size * 0.25, size * 1.15, size * 0.35, 0, size * 1.05);
        cbCtx.bezierCurveTo(-size * 1.15, size * 0.25, -size * 0.55, -size * 0.25, -size * 0.05, size * 0.25);
        cbCtx.stroke();
        cbCtx.restore();
    }
    
    scribbleMarkerHeart(w * 0.18, h * 0.25, minDim * 0.09, -0.3);
    scribbleMarkerHeart(w * 0.82, h * 0.72, minDim * 0.07, 0.4);
    scribbleMarkerHeart(w * 0.85, h * 0.35, minDim * 0.05, 0.15);
    scribbleMarkerHeart(w * 0.22, h * 0.8, minDim * 0.055, -0.2);
    
    // 6. Final Compositing
    // Set a drop shadow on the main canvas context.
    // By drawing the cardboard cutout over the original image, inner shadow will be cast inside the heart hole realistically.
    ctx.shadowColor = `rgba(0, 0, 0, ${alpha})`;
    ctx.shadowBlur = minDim * 0.035;
    ctx.shadowOffsetX = minDim * 0.01;
    ctx.shadowOffsetY = minDim * 0.015;
    
    // Print the prepared cardboard layer
    ctx.drawImage(cbCanvas, 0, 0);
    
    // Reset shadow
    ctx.shadowColor = 'transparent';
    
    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 Cardboard Love Image Generator applies a creative, handcrafted aesthetic to your photos by overlaying a textured cardboard frame with a heart-shaped cutout. The tool simulates a realistic cardboard effect, complete with corrugated textures, artificial noise, and decorative elements like masking tape and red marker scribbles. It also applies a warm, vintage-style filter to the underlying image to enhance the romantic mood. This tool is ideal for creating personalized digital scrapbooks, romantic social media posts, or unique greeting card designs.

Leave a Reply

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