Please bookmark this page to avoid losing your image tool!

Image Cassette Tape Cover Template Creator

(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,
    titleText = "ALBUM TITLE",
    artistText = "ARTIST NAME",
    spineText = "MY ALBUM ● MY ARTIST",
    spineBgColor = "#DDDDDD",
    spineTextColor = "#000000",
    frontTextColor = "#FFFFFF",
    titleFontSize = 36, // px
    artistTextSize = 22, // px
    spineFontSize = 20, // px
    fontFamily = "Impact, Arial, sans-serif",
    frontTextShadow = 1, // 0 for no, 1 for yes
    drawFoldLine = 1, // 0 for no, 1 for yes
    foldLineColor = "rgba(0,0,0,0.5)"
) {
    // Helper function for text truncation, defined within processImage scope
    function _truncateText(ctx, text, maxWidth) {
        let currentText = String(text); // Ensure it's a string

        if (maxWidth <= 0) return ""; // Cannot fit anything if maxWidth is zero or negative

        if (ctx.measureText(currentText).width <= maxWidth) {
            return currentText;
        }

        const ellipsis = "...";
        const ellipsisWidth = ctx.measureText(ellipsis).width;

        // If ellipsis itself doesn't fit, return empty string or as much text as possible without ellipsis
        if (ellipsisWidth > maxWidth) {
            let minimalText = "";
            for (let i = 0; i < currentText.length; i++) {
                if (ctx.measureText(minimalText + currentText[i]).width <= maxWidth) {
                    minimalText += currentText[i];
                } else {
                    break;
                }
            }
            return minimalText;
        }

        // Iteratively shorten the text and check if it fits with ellipsis
        while (currentText.length > 0) {
            currentText = currentText.slice(0, -1);
            if (ctx.measureText(currentText + ellipsis).width <= maxWidth) {
                return currentText + ellipsis;
            }
        }
        
        // This case should ideally be covered if ellipsis fits but no char + ellipsis fits
        return ""; // Or return ellipsis if it fits by itself and currentText is empty
    }

    const DPI = 150; // Resolution for the template
    const FRONT_WIDTH_IN = 4;    // inches
    const FRONT_HEIGHT_IN = 2.5; // inches
    const SPINE_WIDTH_IN = 0.5;  // inches

    const FRONT_WIDTH = FRONT_WIDTH_IN * DPI;     // pixels
    const FRONT_HEIGHT = FRONT_HEIGHT_IN * DPI;   // pixels
    const SPINE_WIDTH = SPINE_WIDTH_IN * DPI;     // pixels
    const SPINE_HEIGHT = FRONT_HEIGHT;            // pixels (same as front panel height)

    const CANVAS_WIDTH = FRONT_WIDTH + SPINE_WIDTH;
    const CANVAS_HEIGHT = FRONT_HEIGHT;

    const canvas = document.createElement('canvas');
    canvas.width = CANVAS_WIDTH;
    canvas.height = CANVAS_HEIGHT;
    const ctx = canvas.getContext('2d');

    // Default canvas background color (e.g., transparent or white)
    // This helps if originalImg is transparent or doesn't fully cover due to error
    ctx.fillStyle = '#FFFFFF'; // White background for the whole template area
    ctx.fillRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);

    // 1. Draw front cover image
    if (originalImg && typeof originalImg.width === 'number' && originalImg.width > 0 && typeof originalImg.height === 'number' && originalImg.height > 0) {
        const imgAspect = originalImg.width / originalImg.height;
        const frontPanelAspect = FRONT_WIDTH / FRONT_HEIGHT;
        let sx = 0, sy = 0, sWidth = originalImg.width, sHeight = originalImg.height;

        if (imgAspect > frontPanelAspect) { // Image wider than panel aspect: fit height, crop width
            sWidth = originalImg.height * frontPanelAspect;
            sx = (originalImg.width - sWidth) / 2;
        } else if (imgAspect < frontPanelAspect) { // Image taller than panel aspect: fit width, crop height
            sHeight = originalImg.width / frontPanelAspect;
            sy = (originalImg.height - sHeight) / 2;
        }
        // else: aspect ratios match, use full image (sx, sy, sWidth, sHeight are already correct)

        ctx.drawImage(originalImg, sx, sy, sWidth, sHeight, 0, 0, FRONT_WIDTH, FRONT_HEIGHT);
    } else {
        // Fallback for missing/invalid image: draw a placeholder on the front panel
        ctx.fillStyle = '#CCCCCC'; // Light gray placeholder
        ctx.fillRect(0, 0, FRONT_WIDTH, FRONT_HEIGHT);
        ctx.fillStyle = '#555555'; // Dark gray text
        ctx.font = `bold 20px sans-serif`;
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        ctx.fillText("Image Error", FRONT_WIDTH / 2, FRONT_HEIGHT / 2);
    }

    // 2. Draw Spine
    ctx.fillStyle = spineBgColor;
    ctx.fillRect(FRONT_WIDTH, 0, SPINE_WIDTH, SPINE_HEIGHT);

    // Spine Text
    if (String(spineText).trim() !== "" && SPINE_WIDTH > 0 && SPINE_HEIGHT > 0) {
        let actualSpineFontSize = Math.max(1, spineFontSize); // Ensure positive font size
        const spineTextVerticalPadding = Math.max(2, SPINE_WIDTH * 0.05); // Padding for character height within spine width
        const maxCharHeightOnSpine = SPINE_WIDTH - (2 * spineTextVerticalPadding);
        
        if (actualSpineFontSize > maxCharHeightOnSpine) {
            actualSpineFontSize = maxCharHeightOnSpine;
        }
        
        if (actualSpineFontSize > 0) { // Only draw if calculated font size is usable
            ctx.save();
            ctx.fillStyle = spineTextColor;
            ctx.font = `bold ${actualSpineFontSize}px ${fontFamily}`;
            ctx.textAlign = 'center';
            ctx.textBaseline = 'middle';

            ctx.translate(FRONT_WIDTH + SPINE_WIDTH / 2, SPINE_HEIGHT / 2);
            ctx.rotate(-Math.PI / 2); // Rotate -90 degrees (clockwise)

            const spineTextHorizontalPadding = Math.max(5, SPINE_HEIGHT * 0.025); // Padding for text length along spine height
            const maxSpineTextWidth = SPINE_HEIGHT - (2 * spineTextHorizontalPadding);
            const truncatedSpineText = _truncateText(ctx, spineText, maxSpineTextWidth);
            
            ctx.fillText(truncatedSpineText, 0, 0);
            ctx.restore();
        }
    }

    // 3. Draw Front Panel Text (Title and Artist)
    const frontTextHorizontalPadding = Math.max(10, FRONT_WIDTH * 0.05); // Horizontal padding
    const frontTextVerticalPadding = Math.max(10, FRONT_HEIGHT * 0.05);   // Vertical padding

    if (frontTextShadow === 1) {
        ctx.shadowColor = 'rgba(0,0,0,0.7)';
        ctx.shadowOffsetX = 2;
        ctx.shadowOffsetY = 2;
        ctx.shadowBlur = 3;
    }

    // Title Text
    if (String(titleText).trim() !== "" && FRONT_WIDTH > 0 && FRONT_HEIGHT > 0) {
        let actualTitleFontSize = Math.max(1, titleFontSize);
        ctx.font = `bold ${actualTitleFontSize}px ${fontFamily}`;
        ctx.fillStyle = frontTextColor;
        ctx.textAlign = 'center';
        ctx.textBaseline = 'top'; 
        const maxTitleWidth = FRONT_WIDTH - (2 * frontTextHorizontalPadding);
        const truncatedTitleText = _truncateText(ctx, titleText, maxTitleWidth);
        ctx.fillText(truncatedTitleText, FRONT_WIDTH / 2, frontTextVerticalPadding);
    }

    // Artist Text
    if (String(artistText).trim() !== "" && FRONT_WIDTH > 0 && FRONT_HEIGHT > 0) {
        let actualArtistTextSize = Math.max(1, artistTextSize);
        ctx.font = `normal ${actualArtistTextSize}px ${fontFamily}`;
        ctx.fillStyle = frontTextColor;
        ctx.textAlign = 'center';
        ctx.textBaseline = 'bottom';
        const maxArtistWidth = FRONT_WIDTH - (2 * frontTextHorizontalPadding);
        const truncatedArtistText = _truncateText(ctx, artistText, maxArtistWidth);
        ctx.fillText(truncatedArtistText, FRONT_WIDTH / 2, FRONT_HEIGHT - frontTextVerticalPadding);
    }

    if (frontTextShadow === 1) { // Reset shadow effects
        ctx.shadowColor = 'transparent';
        ctx.shadowOffsetX = 0;
        ctx.shadowOffsetY = 0;
        ctx.shadowBlur = 0;
    }

    // 4. Draw Fold Line (optional)
    if (drawFoldLine === 1 && SPINE_WIDTH > 0) {
        ctx.strokeStyle = foldLineColor;
        ctx.lineWidth = 1; 
        ctx.setLineDash([4, 2]); // Example: 4px line, 2px gap
        ctx.beginPath();
        ctx.moveTo(FRONT_WIDTH, 0);
        ctx.lineTo(FRONT_WIDTH, FRONT_HEIGHT);
        ctx.stroke();
        ctx.setLineDash([]); // Reset line dash to solid for subsequent drawings
    }
    
    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 Cassette Tape Cover Template Creator allows users to create custom cassette tape cover designs for personal or project use. By uploading an image, users can easily add personalized text elements such as album titles and artist names, and configure design features including spine text, background colors, font styles, and sizes. This tool is ideal for musicians, graphic designers, or anyone looking to design retro-style cassette covers for their music albums, digital projects, or artistic endeavors.

Leave a Reply

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

Other Image Tools:

Image Passport Page Template Generator

Image Old Map Frame With Compass Rose Decorator

Image Diploma and Degree Certificate Framer

Image Soviet Propaganda Poster Style Generator

Image Yu-Gi-Oh Card Template Creator

Image Ancient Roman Greek Tablet Frame Creator

Image Marriage Certificate Template Creator

Image Video Game Achievement Frame Creator

Image Newspaper Front Page Template Creator

Image Botanical Illustration Frame Creator

Image Vinyl Record Sleeve Template Creator

Vintage Photo Booth Strip Template Generator

Image Cyberpunk Interface Frame Designer

Image Detective Novel Cover Template

Image Achievement Certificate Framer

Image Illuminated Manuscript Frame Generator

Image Art Deco Poster Frame Creator

Image Egyptian Papyrus Scroll Frame Designer

Image Vintage Postage Stamp Frame Creator

Image Magic: The Gathering Card Frame Generator

Image Birth Certificate Template Generator

Image Driver’s License Template Creator

Image Scout Explorer Badge Template Creator

Image Steampunk Document Frame Creator

Image Vintage Scientific Illustration Frame Creator

Image Magazine Cover Template Creator

Image Album Cover Template Creator

Image Medieval Bestiary Page Template

Image Polaroid Instant Photo Frame

Image Pulp Fiction Book Cover Template

Image Medieval Manuscript Frame Creator

Image Vintage Advertisement Poster Generator

Victorian Image Calling Card Template

Image Award Certificate Template

Image Military Insignia Patch Template Creator

Image ID Card Template Creator

See All →