Please bookmark this page to avoid losing your image tool!

Image To Block Symbol 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.
async function processImage(originalImg, maxWidth = 80) {
    // A character set from sparse to dense, providing a grayscale ramp.
    // We use a coherent subset of the suggested block symbols for a logical progression.
    const symbols = " ▂▃▄▅▆▇█";

    // The maximum number of characters (width * height) in the output, as per description.
    const maxChars = 999;

    // --- 1. Calculate output dimensions ---

    const originalWidth = originalImg.width;
    const originalHeight = originalImg.height;
    const aspectRatio = originalWidth / originalHeight;

    // Adjust for the aspect ratio of a typical character in a monospace font.
    // Characters are taller than they are wide, so we reduce the height proportionally.
    // A factor of ~0.5 is a good correction for many monospace fonts.
    const characterAspectRatio = 0.5;

    let newWidth = Math.min(maxWidth, originalWidth);
    let newHeight = Math.round(newWidth / aspectRatio * characterAspectRatio);

    // If the calculated number of characters exceeds the limit, scale down dimensions
    // while preserving the aspect ratio.
    if (newWidth * newHeight > maxChars) {
      newWidth = Math.floor(Math.sqrt(maxChars * aspectRatio / characterAspectRatio));
      newHeight = Math.round(newWidth / aspectRatio * characterAspectRatio);
    }
    
    // Ensure dimensions are at least 1x1 to avoid errors.
    newWidth = Math.max(1, newWidth);
    newHeight = Math.max(1, newHeight);

    // --- 2. Use Canvas to get pixel data ---

    const canvas = document.createElement('canvas');
    canvas.width = newWidth;
    canvas.height = newHeight;
    
    // Using { willReadFrequently: true } is a performance hint for browsers.
    const ctx = canvas.getContext('2d', { willReadFrequently: true });
    
    // Draw the image onto the canvas, which resizes it to our calculated dimensions.
    ctx.drawImage(originalImg, 0, 0, newWidth, newHeight);
    
    let imageData;
    try {
        imageData = ctx.getImageData(0, 0, newWidth, newHeight).data;
    } catch (e) {
        console.error("Could not get image data. This may be due to a cross-origin image.", e);
        const errorEl = document.createElement('p');
        errorEl.textContent = 'Error: Could not process the image. It might be from a different origin (CORS policy). Try saving the image and uploading it from your device.';
        errorEl.style.color = 'red';
        return errorEl;
    }

    // --- 3. Convert each pixel's brightness to a block character ---

    let output = '';
    for (let y = 0; y < newHeight; y++) {
        for (let x = 0; x < newWidth; x++) {
            const index = (y * newWidth + x) * 4;
            const r = imageData[index];
            const g = imageData[index + 1];
            const b = imageData[index + 2];
            
            // Calculate brightness using the luminosity method for more accurate perceived brightness.
            // Value is from 0 (black) to 255 (white).
            const brightness = 0.2126 * r + 0.7152 * g + 0.0722 * b;

            // Map brightness to a character in our symbol set.
            // We want dark pixels (low brightness) to map to dense symbols (end of the `symbols` string).
            // We want light pixels (high brightness) to map to sparse symbols (start of the `symbols` string).
            // To achieve this, we invert the brightness value before mapping it to the symbols index.
            const invertedBrightness = 255 - brightness;
            const symbolIndex = Math.floor((invertedBrightness / 255) * (symbols.length - 1));

            output += symbols[symbolIndex];
        }
        output += '\n';
    }
    
    // --- 4. Create and return the final HTML element ---
    
    const preElement = document.createElement('pre');
    preElement.textContent = output;
    
    // Style for proper display. A monospace font is crucial for character alignment.
    preElement.style.fontFamily = 'monospace, "Courier New", Courier';
    preElement.style.lineHeight = '1.0';
    preElement.style.margin = '0';
    // Letter spacing can be adjusted to make the blocks touch, creating a more solid look.
    preElement.style.letterSpacing = '0';
    preElement.style.fontSize = '10px'; // A smaller font helps fit more detail.

    return preElement;
}

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 Block Symbol Converter transforms images into text representations using block symbols. It reduces image dimensions while maintaining the aspect ratio, converting each pixel’s brightness into a corresponding character from a predefined set of symbols, ranging from sparse to dense. This tool can be used for artistic purposes, such as creating ASCII art, or for displaying images in environments where traditional images might not be supported, like command-line interfaces or text-based applications. Users can customize the output width to fit different display preferences.

Leave a Reply

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