After talking to a friend who suggested I write a text based adventure game I decided could use a way to generate graphics that could be displayed as text. To achieve this I used the HTML canvas to analyse images and comapared the distribution of colours with various characters, providing graphical, textual, and HTML outputs.
Links
Overview
The tool allows the user to choose various character sets for processing the images, including particles for images related to particle physics. The user can also choose which display modes to use, including “colour”, “black and white”, “red green, and blue”, “pixelate”, “Matrix”.
There are two rules for determining which characters to use, which are “parsimony”, and “random”. Parsimony chooses a single character of a single colour that best matches the local pixels.
Strategy
The source image is divided into rectangles of equal size. The rectangles are then painted to a canvas one by one, and the pixel colours analysed to define a single characteristic colour for the rectangle depending on the mode used. (For example, when the mode is “black and white” the characteristic colour is \((\bar{r}+\bar{g}+\bar{b})/3\), where \(\bar{r}\) is the average red value of the pixels, and similarly for green and blue.)
For each rectangle each character is tested one by one to find the best match between the pixels in the source image and those in the character using the characteristic colour. To find the character with the best match a parsimony parameter, \(p\), is defined as the sum of the squares of the differences between the rgb values of the pixels between the character and the source image. The character with the smallest value of \(p\) is chosen. The expression for \(p\) is:
\( p = \sum_i \left[ (r_i^s-r_i^c)^2 + (g_i^s-g_i^c)^2 + (b_i^s-b_i^c)^2 \right] \)
where \(r_i^s(c)\) is the r value of the \(i\)th pixel in the source image (character), and similarly for green and blue.
This character then gets drawn to a large canvas for graphical output, added to a span
element for textual output, and added to a textarea
element for HTML output.
Challenges
- Challenge: The versatility of the tool is limited by the same origin policy restrictions, meaning that currently users can only download image generated from sources files on the same server.
- Solution: Create a secure and reliable service for uploading images to a temporary directory on the server. (To be done)
- Challenge: In textual output, the font spacing requires tweaks depending on the browser used.
- Solution: Edit the CSS to ensure consistent display of text between different clients. (To be done)
- Challenge: For large images and large character sets the processing can cause the browser to freeze up and issues warnings.
- Solution: The processing is split into “spurts” which consist of a fixed number of steps each. The
window.setTimeout
method is used to moderate the CPU load. (Resolved)
Sample input and output
Source image:

Normal settings (colour mode, integers character set, parsimony rule):

Different modes:



Different character sets:





Random rule:

Hi there,
thanks for sharing this interesting tool.
I downloaded the master folder from gitHub. However, I’m not sure how to run the code from OSX…
Could you please provide some hints?
Thanks
Hi Andrea,
Sorry for the late reply, I don’t check this blog much! This is a JavaScript tool, so it should work in any modern browser on any platform. The main executable code is in html/ascii.js and it should work as long as the body tag has an eventListener which calls the start function for onload. I’ll probably rewrite the code this weekend to make it easier to use- it’s a bit of a mess right now.
Aidan