The guide
Text art works when characters are picked by the ink they print, not by habit
Turning a picture into text is printing in miniature: every character is a patch of ink with a weight and a shape, set on a grid whose cells are taller than they are wide.
- 95 graphic characters in ASCII, from the space to the tilde
- 80 x 31 characters for a 640 by 480 picture in the worked example
- 256 eight-dot braille patterns encoded by Unicode
- 8 dots in one braille cell, two across and four down
- 7/16 of each dot's error that Floyd-Steinberg passes to the right
Read the full guide Fold the guide
A picture made of letters looks like a trick. It is closer to a trade. Every character is a small patch of ink or light, and the whole job is choosing the right patch for each spot.
The claim here is plain. Text art comes out well when three things are measured instead of assumed: how dark each character really is, how tall its cell is compared with its width, and where inside the cell its ink sits. The familiar recipes skip all three, which is why so many conversions look stretched and muddy.
Pictures from machines that could only type
The idea is older than the code it is named after. By one account typewriters have been used to make pictures since 1867, and text images were sent by teletypewriter as early as 1923, long before a screen could show anything else. Through the 1960s and 1970s such pictures appeared often on radioteletype.
Computers inherited the habit for a practical reason. Early printers often lacked any graphics ability, so characters stood in for graphic marks. In the 1960s Andries van Dam published a drawing of an electronic circuit made on an IBM 1403 line printer, and Kenneth Knowlton at Bell Labs was producing realistic images on line printers by overprinting several characters on top of one another. Overprinting is the telling detail. A printer that can strike the same spot twice can build a dark patch out of two lighter ones, which means somebody was already thinking of characters as quantities of ink.
Knowlton’s best known picture, made with Leon Harmon, used small electronic symbols for transistors, resistors and the like, arranged so that from a distance they formed a nude. By his own account it was 12 feet wide and hung on a colleague’s office wall at the Labs for one day before it was retired to a basement. It later appeared in books under the more dignified title Studies in Perception I. The marks were not letters, but the principle is the one every converter uses: a vocabulary of small marks, each chosen for how dark it reads from far away.
The vocabulary most tools draw on was fixed in the same decade. The network standard that describes ASCII lists its graphic characters from the space at position 2/0 to the tilde at 7/14, which makes 95, and it describes the space as a normally non-printing graphic character. That odd phrase matters. The space is the one character certain to carry no ink at all. It is the paper.
Ink is a measurement, not a tradition
Most converters order those characters with a ramp that somebody typed once: a fixed string that runs from the space to some heavy sign, handed from one program to the next. One ten-character version, a space followed by . : - = + * # % @, serves as the shades of a fractal program among the examples collected on Rosetta Code, and it is the tool’s Short ramp. Such a string comes with no method. It is a judgment about one typeface on one screen, copied ever since.
A ramp is a claim about darkness, and darkness can be counted. Draw a character in its cell, count how much of the cell is covered, and sort.
The order that comes out depends on the font, sometimes sharply. On the computer where this tool was checked, the system monospace font put a capital N at the dark end, covering about 35 percent of its cell, with the at sign just behind it. In Courier New the darkest character was a capital M at under 20 percent, a far lighter face overall. Even the ten characters of the short ramp sorted differently in the two: the asterisk and the equals sign traded places. A typed ramp is right for one font at most.
Measuring also shows how little ink text has. If the heaviest character covers a third of its cell, a page full of it is still mostly paper. Text cannot reach black on a white page, so the range has to be stretched: the heaviest character stands for black, the space for white, and each tone between goes to the character whose measured ink is nearest. Spacing the characters evenly by rank instead would bunch the tones wherever several characters happen to weigh the same.
Brightness needs a definition too. The usual one weights the three color channels unequally: 0.2126 for red, 0.7152 for green and 0.0722 for blue, the weights the web accessibility guidelines use for relative luminance. Applying them to stored pixel values without first undoing the encoding of those values is a shortcut, not an exact measure of light, and a gamma control is the honest way to let a person correct it by eye.
Cells are tall, and shapes carry edges
A character cell is not square. In the two fonts above it was a little over half as wide as it was tall: 0.52 in one and 0.53 in the other. Lay a picture onto such a grid with one sample per character and every circle becomes a tall oval.
The common fix is to sample half as often down the picture as across it, which assumes a cell exactly twice as tall as it is wide. A browser does not have to assume. Its text measuring interface reports the width of a piece of text and the ascent and descent of the font’s bounding box. The width of one character divided by the sum of the other two is the proportion of the cell.
Here is the arithmetic for one case. Take a picture 640 pixels wide and 480 tall, set 80 columns wide, in a font whose cell is 0.521 wide for every 1 tall. Each column covers 8 pixels of width, so each row must cover 8 divided by 0.521, about 15.4 pixels of height. The picture then needs 480 divided by 15.4 rows, which is 31.3 and rounds to 31. The art is 80 x 31, or 2,480 characters. Assume a cell exactly half as wide as tall and the answer is 30 rows. Assume square cells and it is 60, twice too tall.
Tone alone wastes what characters know. A slash and a backslash weigh the same and mean opposite things. Measuring each character’s ink on a small grid inside its cell, three across and five down, gives it a crude portrait, and the picture can be sampled on the same grid. Choosing the character whose portrait is closest, by the sum of squared differences, puts an underscore where the bottom of a patch is dark and a quotation mark where the top is. Edges sharpen without any edge detector.
More dots per character
Unicode offers characters built for this work. Its Block Elements chart holds an upper half block, a lower half block, a full block, left and right halves and ten quadrant characters. Together with the space they cover all sixteen ways of filling a cell divided two by two, so one character carries four picture elements instead of one. Chafa, a current program for showing pictures in terminals, lists Unicode mosaics of this kind among its outputs.
Braille goes further. The standard encodes a single complete set of 256 eight-dot patterns, which includes the 64 needed for six-dot braille. The dots sit two across and four down: 1 to 3 down the left column, 4 to 6 down the right, and 7 and 8 added underneath. Each pattern’s name lists the dots it holds. A cell has 8 dots, so a braille character carries eight times the detail of a plain one, and projects such as drawille use it to plot pixel graphics in a terminal.
Dots are either on or off, so tone has to come from how many are on. The method Floyd and Steinberg published in 1976 does this by passing the rounding error of each dot to neighbors not yet decided: 7/16 to the right, 3/16 below and to the left, 5/16 directly below and 1/16 below and to the right. Those four numbers were chosen so that a perfectly even gray settles into a checkerboard.
Color reached terminals through a standard that barely mentions it. ECMA-48, in its fifth edition of June 1991, defines the control function that selects graphic rendition and reserves parameter 38 for a foreground color to be specified by another standard. The form terminals accept today, 38 then 2 then three numbers for red, green and blue, is documented by xterm and by Microsoft for the Windows console. That allows about 16 million colors. A survey of terminal support lists programs that only approximate them, and recommends checking the COLORTERM variable before relying on true color.
Three destinations, three sets of rules
Plain text is the most portable form and the least controlled. Whoever pastes it chooses the font, and with the font the cell proportion and the order of the ramp, so the picture may arrive slightly squashed with its tones reshuffled. Braille and block characters add a second risk. Browsers choose fonts one character at a time, moving down the list when a font lacks a glyph, and the fallback font’s braille can be wider than the letters around it. In one check here its cell measured 0.59 against 0.52 for the letters.
A web page fixes most of that. The pre element exists for preformatted text, where structure is carried by typographic convention, and an inline style can pin the font family, the size and the line height. The price is escaping. An ampersand, a less-than sign or a quotation mark that belongs to the picture must be written as a character reference, or the browser reads it as markup. One trap is particular to pre: a line break immediately after the opening tag is stripped.
A terminal file is the liveliest and the most fragile. Its colors travel as control sequences inside the text, so it is noise in an ordinary editor. Each line should end by returning to the default rendition, which the standard defines as parameter 0, so that a stray color cannot leak into whatever the terminal prints next.
None of this makes text a good way to keep a picture. Eighty columns of the best chosen characters hold a few thousand samples, and a photograph holds millions. Fine texture, small faces and thin lines vanish. The measured ramp is true only for the font it was measured in, and a picture bound for someone else’s screen is always a guess about their typeface.
What measurement buys is honesty about the medium. The first people to do this had a typewriter and their eyes, and they judged every key by looking at what it left on the paper. A browser can do that looking now, one glyph at a time, and the picture that comes out is the best those particular characters can do.
Sources
Every source consulted for this guide. Links checked October 4, 2026.
- RFC 20: ASCII format for network interchange RFC Editor
- ASCII art Wikipedia
- Mandelbrot set Rosetta Code
- Portrait of the Artist as a Young Scientist Ken Knowlton
- Braille Patterns (code chart, The Unicode Standard) The Unicode Consortium
- Block Elements (code chart, The Unicode Standard) The Unicode Consortium
- Notational Systems (The Unicode Standard, Version 16.0, Chapter 21) The Unicode Consortium
- ECMA-48: Control functions for coded character sets Ecma International
- XTerm Control Sequences Thomas E. Dickey
- Console Virtual Terminal Sequences Microsoft (Console-Docs on GitHub)
- termstandard/colors: Color standards for terminal emulators GitHub
- Image Dithering: Eleven Algorithms and Source Code Tanner Helland
- TextMetrics MDN Web Docs
- font-family CSS property MDN Web Docs
- HTML Standard, 4.4 Grouping content WHATWG
- Web Content Accessibility Guidelines (WCAG) 2.2 World Wide Web Consortium
- Chafa: Terminal Graphics for the 21st Century Hans Petter Jansson
- asciimoo/drawille: Pixel graphics in terminal with unicode braille characters GitHub