Please bookmark this page to avoid losing your image tool!

Image To ANSI Art 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, outputWidth = "80") {
    let width = parseInt(outputWidth, 10);
    if (isNaN(width) || width <= 0) width = 80;
    
    // Scale height proportionally to maintain aspect ratio 
    // (A half block character is roughly 1 pixel wide by 2 pixels tall, 
    // so taking 2 vertical pixels per line will automatically correct to a squarish aspect ratio)
    const height = Math.max(1, Math.round(originalImg.height * (width / originalImg.width)));
    
    const canvas = document.createElement('canvas');
    canvas.width = width;
    canvas.height = height;
    const ctx = canvas.getContext('2d');
    
    // Fill background with black to handle transparent images correctly
    ctx.fillStyle = "black";
    ctx.fillRect(0, 0, width, height);
    ctx.drawImage(originalImg, 0, 0, width, height);
    
    const imgData = ctx.getImageData(0, 0, width, height).data;
    
    let htmlResult = "";
    let ansiResult = ""; // For raw .ans output

    let htmlCurrentFg = "";
    let htmlCurrentBg = "";
    let currentSpanText = "";

    function closeSpan() {
        if (currentSpanText) {
            htmlResult += `<span style="color:${htmlCurrentFg}; background-color:${htmlCurrentBg};">${currentSpanText}</span>`;
            currentSpanText = "";
        }
    }

    let ansiCurrentFg = "";
    let ansiCurrentBg = "";
    
    const charRows = Math.ceil(height / 2);

    for (let cr = 0; cr < charRows; cr++) {
        for (let x = 0; x < width; x++) {
            let tY = cr * 2;
            let bY = tY + 1;
            
            // Get top pixel colors (for character background)
            let tIdx = (tY * width + x) * 4;
            let tR = 0, tG = 0, tB = 0;
            if (tY < height) {
                tR = imgData[tIdx];
                tG = imgData[tIdx+1];
                tB = imgData[tIdx+2];
            }
            
            // Get bottom pixel colors (for character foreground, meaning the lower half block)
            let bIdx = (bY * width + x) * 4;
            let bR = 0, bG = 0, bB = 0;
            if (bY < height) {
                bR = imgData[bIdx];
                bG = imgData[bIdx+1];
                bB = imgData[bIdx+2];
            }
            
            // Prepare HTML preview sequences
            let stepHtmlFg = `rgb(${bR},${bG},${bB})`;
            let stepHtmlBg = `rgb(${tR},${tG},${tB})`;
            
            if (stepHtmlFg !== htmlCurrentFg || stepHtmlBg !== htmlCurrentBg) {
                closeSpan();
                htmlCurrentFg = stepHtmlFg;
                htmlCurrentBg = stepHtmlBg;
            }
            currentSpanText += "▄";
            
            // Prepare raw ANSI True Color terminal sequences
            let stepAnsiFg = `\x1b[38;2;${bR};${bG};${bB}m`;
            let stepAnsiBg = `\x1b[48;2;${tR};${tG};${tB}m`;
            
            if (stepAnsiFg !== ansiCurrentFg) {
                ansiResult += stepAnsiFg;
                ansiCurrentFg = stepAnsiFg;
            }
            if (stepAnsiBg !== ansiCurrentBg) {
                ansiResult += stepAnsiBg;
                ansiCurrentBg = stepAnsiBg;
            }
            ansiResult += "▄";
        }
        
        closeSpan();
        htmlResult += "\n";
        htmlCurrentFg = "";
        htmlCurrentBg = "";
        
        // Reset ANSI formatting at the end of each line
        ansiResult += "\x1b[0m\n";
        ansiCurrentFg = "";
        ansiCurrentBg = "";
    }
    
    // Construct the result UI elements
    const container = document.createElement('div');
    container.style.display = 'flex';
    container.style.flexDirection = 'column';
    container.style.alignItems = 'flex-start';
    container.style.gap = '10px';
    container.style.fontFamily = 'sans-serif';
    container.style.width = '100%';
    
    const pre = document.createElement('pre');
    pre.style.fontFamily = 'Consolas, Monaco, "Courier New", monospace';
    pre.style.fontSize = '8px';
    pre.style.lineHeight = '8px';
    pre.style.letterSpacing = '0';
    pre.style.background = '#000';
    pre.style.margin = '0';
    pre.style.padding = '10px';
    pre.style.borderRadius = '4px';
    pre.style.overflowX = 'auto';
    pre.style.maxWidth = '100%';
    pre.style.whiteSpace = 'pre';
    pre.innerHTML = htmlResult; // Add optimized HTML representation
    
    const buttonGroup = document.createElement('div');
    buttonGroup.style.display = 'flex';
    buttonGroup.style.gap = '10px';
    
    const copyBtn = document.createElement('button');
    copyBtn.textContent = 'Copy ANSI Code';
    copyBtn.style.padding = '8px 16px';
    copyBtn.style.cursor = 'pointer';
    copyBtn.style.backgroundColor = '#4CAF50';
    copyBtn.style.color = '#fff';
    copyBtn.style.fontWeight = 'bold';
    copyBtn.style.border = 'none';
    copyBtn.style.borderRadius = '4px';
    copyBtn.onclick = () => {
        if (navigator.clipboard) {
            navigator.clipboard.writeText(ansiResult).then(() => {
                const origText = copyBtn.textContent;
                copyBtn.textContent = 'Copied!';
                setTimeout(() => copyBtn.textContent = origText, 2000);
            });
        }
    };
    
    const downloadBtn = document.createElement('button');
    downloadBtn.textContent = 'Download .ans File';
    downloadBtn.style.padding = '8px 16px';
    downloadBtn.style.cursor = 'pointer';
    downloadBtn.style.backgroundColor = '#2196F3';
    downloadBtn.style.color = '#fff';
    downloadBtn.style.fontWeight = 'bold';
    downloadBtn.style.border = 'none';
    downloadBtn.style.borderRadius = '4px';
    downloadBtn.onclick = () => {
        const blob = new Blob([ansiResult], { type: 'text/plain' });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = 'ANSI_art.ans';
        a.click();
        URL.revokeObjectURL(url);
    };
    
    buttonGroup.appendChild(copyBtn);
    buttonGroup.appendChild(downloadBtn);
    
    container.appendChild(pre);
    container.appendChild(buttonGroup);
    
    return container;
}

Free Image Tool Creator

Can't find the image tool you're looking for?
Create one based on your own needs now!

Description

This tool converts standard images into ANSI art, representing visual data through color-coded terminal sequences. It uses special block characters to map the foreground and background colors of an image, allowing for a detailed, high-fidelity recreation of the original picture within a command-line interface. Users can adjust the output width to control resolution and can either copy the raw ANSI codes for use in terminal environments or download the result as a .ans file. This is particularly useful for developers, terminal enthusiasts, or digital artists looking to create retro-style terminal graphics and ASCII-based visual content.

Leave a Reply

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