Please bookmark this page to avoid losing your image tool!

Image To ASCII Translator

(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.
/**
 * Converts an image to ASCII art on a canvas.
 *
 * @param {Image} originalImg The original javascript Image object.
 * @param {string} [charSet='@%#*+=-:. '] The set of characters to use, ordered from darkest to lightest.
 * @param {number} [scale=0.1] The resolution scaling factor. Smaller numbers mean lower resolution (fewer characters) and faster processing. Value should be between 0.01 and 1.
 * @param {number} [invert=0] If 1, inverts the brightness mapping (light areas become dark characters). If 0, normal mapping is used.
 * @param {number} [fontSize=10] The font size of the characters in the output ASCII art.
 * @returns {HTMLCanvasElement} A new canvas element with the ASCII art drawn on it.
 */
function processImage(originalImg, charSet = '@%#*+=-:. ', scale = 0.1, invert = 0, fontSize = 10) {
    // 1. Sanitize and validate parameters
    let finalCharSet = String(charSet) || '@%#*+=-:. ';
    if (finalCharSet.length === 0) {
        finalCharSet = '@%#*+=-:. ';
    }
    // Clamp scale between a small positive number and 1 to avoid errors
    const finalScale = Math.max(0.01, Math.min(1, Number(scale) || 0.1));
    const finalInvert = Number(invert) === 1;
    const finalFontSize = Math.max(1, Number(fontSize) || 10);
    const fontFamily = 'monospace';

    // Using a common approximation for monospace character aspect ratio (width/height)
    const charAspectRatio = 0.5;

    // 2. Create an offscreen canvas to get pixel data. Using willReadFrequently is a performance hint.
    const offscreenCanvas = document.createElement('canvas');
    const offscreenCtx = offscreenCanvas.getContext('2d', {
        willReadFrequently: true
    });
    const imgWidth = originalImg.naturalWidth;
    const imgHeight = originalImg.naturalHeight;
    offscreenCanvas.width = imgWidth;
    offscreenCanvas.height = imgHeight;
    offscreenCtx.drawImage(originalImg, 0, 0);

    // 3. Determine the dimensions of the ASCII grid based on scale and aspect ratio
    const cellWidth = Math.max(1, Math.floor(1 / finalScale));
    const cellHeight = Math.max(1, Math.floor(cellWidth / charAspectRatio));

    const numCols = Math.floor(imgWidth / cellWidth);
    const numRows = Math.floor(imgHeight / cellHeight);

    // 4. Create the final output canvas
    const finalCanvas = document.createElement('canvas');
    const ctx = finalCanvas.getContext('2d');

    // Set font properties to measure character dimensions accurately
    ctx.font = `${finalFontSize}px ${fontFamily}`;
    ctx.textBaseline = 'top';
    const metrics = ctx.measureText('M'); // 'M' is a typically wide character in monospace fonts
    const charWidth = metrics.width;
    const charHeight = finalFontSize;

    // Set final canvas dimensions
    finalCanvas.width = Math.floor(numCols * charWidth);
    finalCanvas.height = Math.floor(numRows * charHeight);

    // Set background and text color
    ctx.fillStyle = 'white';
    ctx.fillRect(0, 0, finalCanvas.width, finalCanvas.height);
    ctx.fillStyle = 'black';
    // Re-apply font settings as fillRect might reset the context state
    ctx.font = `${finalFontSize}px ${fontFamily}`;
    ctx.textBaseline = 'top';

    // 5. Get the raw pixel data from the offscreen canvas
    const imageData = offscreenCtx.getImageData(0, 0, imgWidth, imgHeight);
    const data = imageData.data;

    // 6. Iterate through each cell of the grid
    for (let i = 0; i < numRows; i++) {
        for (let j = 0; j < numCols; j++) {
            const startX = j * cellWidth;
            const startY = i * cellHeight;

            // 7. Calculate the average brightness of all pixels in the current cell
            let totalBrightness = 0;
            let pixelCount = 0;
            for (let y = startY; y < startY + cellHeight; y++) {
                if (y >= imgHeight) continue; // Boundary check

                for (let x = startX; x < startX + cellWidth; x++) {
                    if (x >= imgWidth) continue; // Boundary check

                    const index = (y * imgWidth + x) * 4;
                    const r = data[index];
                    const g = data[index + 1];
                    const b = data[index + 2];

                    // Use the luminance formula for a more perceptually accurate brightness
                    const brightness = 0.299 * r + 0.587 * g + 0.114 * b;
                    totalBrightness += brightness;
                    pixelCount++;
                }
            }

            if (pixelCount === 0) continue;

            const avgBrightness = totalBrightness / pixelCount;

            // 8. Map the calculated brightness to a character from the character set
            const brightnessValue = finalInvert ? (255 - avgBrightness) : avgBrightness;
            const normalized = brightnessValue / 255;
            const charIndex = Math.min(finalCharSet.length - 1, Math.floor(normalized * finalCharSet.length));
            const char = finalCharSet.charAt(charIndex);

            // 9. Draw the character onto the final canvas. Skip drawing spaces for performance and to let the background show.
            if (char && char !== ' ') {
                const xPos = j * charWidth;
                const yPos = i * charHeight;
                ctx.fillText(char, xPos, yPos);
            }
        }
    }

    // 10. Return the final canvas element
    return finalCanvas;
}

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 ASCII Translator converts images into ASCII art, allowing you to create text representations of visual images. Users can customize character sets to define how dark or light areas of the image are represented, adjust the resolution of the output for desired detail, and select font sizes for the final text. This tool is useful for artists, programmers, or anyone looking to create unique text-based artwork or to share images in environments where only text is supported. Additionally, it can be a fun way to turn personal photos into creative text versions for social media sharing or digital communication.

Leave a Reply

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