Please bookmark this page to avoid losing your image tool!

Image To Books Converter

(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, effectStyle = "spines", bookSizeStr = "") {
    // Determine the effect mode: "spines" (bookshelf effect) or "emoji" (book emoji mosaic)
    const effect = ["spines", "emoji"].includes(effectStyle.toLowerCase()) ? effectStyle.toLowerCase() : "spines";
    
    // Parse base size for books or emoji pixels
    let size = parseInt(bookSizeStr, 10);
    if (isNaN(size) || size <= 0) {
        size = effect === "spines" ? 40 : 12;
    }
    
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    const width = originalImg.width;
    const height = originalImg.height;
    
    if (effect === "emoji") {
        // Emoji Mosaic Mode
        let cols = Math.floor(width / size);
        let rows = Math.floor(height / size);
        if (cols === 0) cols = 1;
        if (rows === 0) rows = 1;
        
        // Downscale image to calculate pixel averages
        let offCanvas = document.createElement('canvas');
        offCanvas.width = cols;
        offCanvas.height = rows;
        let octx = offCanvas.getContext('2d', { willReadFrequently: true });
        octx.drawImage(originalImg, 0, 0, cols, rows);
        let imgData = octx.getImageData(0, 0, cols, rows).data;
        
        canvas.width = cols * size;
        canvas.height = rows * size;
        ctx.clearRect(0, 0, canvas.width, canvas.height); // keep transparent background
        
        ctx.font = `${size}px "Segoe UI Emoji", "Apple Color Emoji", "Noto Color Emoji", sans-serif`;
        ctx.textAlign = "center";
        ctx.textBaseline = "middle";
        
        // Book-themed Emojis and their approximate RGB colors
        const emojis = [
            { char: '📕', rgb: [212, 50, 48] },    // Red Book
            { char: '📗', rgb: [80, 160, 90] },    // Green Book
            { char: '📘', rgb: [50, 100, 200] },   // Blue Book
            { char: '📙', rgb: [240, 140, 50] },   // Orange Book
            { char: '📓', rgb: [30, 30, 30] },     // Notebook (mapped to very dark colors)
            { char: '📓', rgb: [80, 80, 80] },     // Notebook (grey)
            { char: '📔', rgb: [220, 200, 140] },  // Decorative Cover (Tan/Beige)
            { char: '📖', rgb: [240, 240, 240] },  // Open Book (White)
            { char: '📚', rgb: [140, 90, 80] },    // Books (Brown/Mixed)
            { char: '📒', rgb: [240, 200, 50] }    // Ledger (Yellow)
        ];
        
        function getClosestEmoji(r, g, b) {
            let minDist = Infinity;
            let best = '📖';
            for (let e of emojis) {
                let dr = r - e.rgb[0];
                let dg = g - e.rgb[1];
                let db = b - e.rgb[2];
                let dist = dr*dr + dg*dg + db*db;
                if (dist < minDist) {
                    minDist = dist;
                    best = e.char;
                }
            }
            return best;
        }
        
        for (let y = 0; y < rows; y++) {
            for (let x = 0; x < cols; x++) {
                let idx = (y * cols + x) * 4;
                let r = imgData[idx];
                let g = imgData[idx+1];
                let b = imgData[idx+2];
                let a = imgData[idx+3];
                
                // Only draw if pixel is fairly opaque
                if (a > 20) {
                    let emoji = getClosestEmoji(r, g, b);
                    ctx.fillText(emoji, x * size + size / 2, y * size + size / 2 + size * 0.05);
                }
            }
        }
        return canvas;
    }
    
    // Default Mode: "Spines" (Bookshelf Generator)
    canvas.width = width;
    canvas.height = height;
    
    // Draw bookshelf background space (dark wood / deep shadow)
    ctx.fillStyle = "#110b07";
    ctx.fillRect(0, 0, width, height);
    
    let x = 0;
    
    // Pseudo-random generator for consistent procedural rendering
    let seed = 1234.5;
    function random() {
        let val = Math.sin(seed++) * 10000;
        return val - Math.floor(val);
    }
    
    while (x < width) {
        // Vary book width slightly based on input size
        let bw = Math.floor(size + (random() * 20 - 10));
        if (bw < 15) bw = 15; // enforce minimum size
        if (x + bw > width) {
            bw = width - x; // exact boundary cap on the last book
        }
        
        // Randomize differing book heights via top and bottom masking
        let topDrop = Math.floor(random() > 0.5 ? random() * (height * 0.08) : random() * (height * 0.02));
        let bottomDrop = Math.floor(random() > 0.5 ? random() * (height * 0.05) : random() * (height * 0.02));
        
        let bookY = topDrop;
        let bookH = height - topDrop - bottomDrop;
        
        // Map the original image directly onto the spines
        ctx.drawImage(originalImg, x, bookY, bw, bookH, x, bookY, bw, bookH);
        
        // Draw 3D spine gradient (makes it look arched)
        let grad = ctx.createLinearGradient(x, 0, x + bw, 0);
        grad.addColorStop(0, "rgba(0,0,0,0.6)");
        grad.addColorStop(0.1, "rgba(0,0,0,0.1)");
        grad.addColorStop(0.35, "rgba(255,255,255,0.05)");
        grad.addColorStop(0.65, "rgba(255,255,255,0.15)");
        grad.addColorStop(0.9, "rgba(0,0,0,0.2)");
        grad.addColorStop(1, "rgba(0,0,0,0.6)");
        
        ctx.fillStyle = grad;
        ctx.fillRect(x, bookY, bw, bookH);
        
        // Inner shadows for top and bottom book curving
        let vertGrad = ctx.createLinearGradient(0, bookY, 0, bookY + bookH);
        vertGrad.addColorStop(0, "rgba(0,0,0,0.9)");
        vertGrad.addColorStop(0.015, "rgba(0,0,0,0.0)");
        vertGrad.addColorStop(0.985, "rgba(0,0,0,0.0)");
        vertGrad.addColorStop(1, "rgba(0,0,0,0.9)");
        
        ctx.fillStyle = vertGrad;
        ctx.fillRect(x, bookY, bw, bookH);
        
        // Top and bottom highlights (pages / book headbands)
        ctx.fillStyle = "rgba(255,255,255,0.4)";
        ctx.fillRect(x + 2, bookY + 1, bw - 4, 1);
        ctx.fillRect(x + 2, bookY + bookH - 2, bw - 4, 1);
        
        // Add horizontal horizontal spine bands (ribbing)
        let numRibs = Math.floor(random() * 3) + 3; // 3 to 5 ribs per book
        let ribSpacing = bookH / (numRibs + 1);
        
        for (let r = 1; r <= numRibs; r++) {
            let ry = Math.floor(bookY + ribSpacing * r);
            
            ctx.fillStyle = "rgba(0,0,0,0.4)";
            ctx.fillRect(x, ry - 1, bw, 2);
            ctx.fillStyle = "rgba(255,255,255,0.15)";
            ctx.fillRect(x, ry + 1, bw, 1);
            
            // Random gold embellishments bordering the ribs
            if (random() > 0.6) {
                ctx.fillStyle = "rgba(255, 215, 0, 0.35)";
                ctx.fillRect(x, ry - 3, bw, 1);
                ctx.fillRect(x, ry + 3, bw, 1);
            }
        }
        
        // Subtle gold-embossed faux title shapes
        if (random() > 0.5 && ribSpacing > 40) {
            let titleBaseY = bookY + ribSpacing * 1.5;
            let titleParts = Math.floor(random() * 3) + 2;
            
            ctx.fillStyle = "rgba(255, 215, 0, 0.3)";
            for (let t = 0; t < titleParts; t++) {
                let tw = bw * 0.4;
                let th = 5 + random() * 15;
                let tx = Math.floor(x + (bw - tw) / 2);
                let ty = Math.floor(titleBaseY + t * 20);
                
                if (ty + th < bookY + bookH - 20) {
                    ctx.fillRect(tx, ty, tw, th);
                }
            }
        }
        
        // Right-edge separator gap to distinguish individual volumes
        ctx.fillStyle = "rgba(0,0,0,0.7)";
        ctx.fillRect(x + bw - 1, bookY, 1, bookH);
        
        // Advance to next spine
        x += bw;
    }
    
    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 To Books Converter transforms your standard photos into unique, book-themed artistic visuals. Users can choose between two distinct creative modes: a ‘spines’ effect, which reconstructs the image as a detailed bookshelf where the picture is mapped onto the spines of various books, and an ’emoji’ mode, which creates a mosaic of your image using a variety of book-related emojis. This tool is ideal for creating stylized social media content, custom digital art, or themed graphics for literary blogs and libraries.

Leave a Reply

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