ASCII Art Starter Kit

Updated 2026-03-27 · By SPUNK13 · Back to spunk.bet

ASCII art splits into two crafts that share a character set. One is generated: text turned into large letterforms, or a photograph quantised into characters. The other is drawn by hand, cell by cell, and is closer to pixel art than to typography. This kit covers the generated side properly, because that is where the tooling and the maths live, and then the conventions that stop your output looking broken in someone else's terminal.

The tools worth installing

figlet is the starting point and still the best at what it does. figlet -f slant "SPUNK" gives you the banner everyone recognises; run showfigfonts to see every installed face at once, and -w 80 to keep it inside a terminal width. toilet is the sibling with colour filters built in, as in toilet -f mono12 -F metal "BUILD". Pipe anything through lolcat for a rainbow gradient. boxes -d stone wraps a block of text in a frame and, more usefully, can also remove one with -r, which makes it safe to use on comment headers you will edit later. cowsay is a joke that has outlived most serious software.

Turning a photo into characters

Three converters, in order of how good the output looks. chafa is the strongest: it picks characters by shape as well as brightness, handles colour well, and can fall back cleanly with chafa --symbols=ascii --size=80x40 photo.jpg when you need plain seven-bit output. jp2a --width=80 --colors photo.jpg is the classic, fast and predictable, and accepts a custom ramp with --chars=. ascii-image-converter handles more input formats including animated GIFs.

Preprocess before converting. You have roughly ten distinguishable brightness levels to work with, so a low-contrast photo becomes grey mush. Crop tight on the subject, then flatten and stretch the tonal range first: magick photo.jpg -colorspace gray -normalize -resize 80x prepped.png. Portraits and high-contrast silhouettes work; landscapes almost never do.

The luminance ramp, and why your output looks flat

Every converter maps pixel brightness onto an ordered string of characters. The short ramp everyone uses is .:-=+*#%@, ten steps from empty to dense. Longer ramps of around seventy characters exist and give smoother gradients at large sizes, but at 80 columns the extra steps are indistinguishable.

The mistake that ruins most first attempts is ramp direction. On a dark terminal, a dense character such as @ is bright, because you are seeing lit pixels on black. On white paper or a light-themed README it is dark. So the same ramp needs inverting depending on where the art will be displayed, and art that looks perfect in your terminal can render as a negative on a documentation site. Decide the target background first. It is also worth applying a gamma correction of roughly 2.2 before quantising, since character density is closer to perceptual brightness than to linear intensity, and skipping it crushes the midtones.

Aspect ratio is why your circles are eggs

A terminal cell is about twice as tall as it is wide. Convert an image one pixel to one character and everything comes out stretched vertically by a factor of two. The correction is to halve the row count:

rows = round(cols * (img_height / img_width) * 0.5)

# 80 columns, source 1600x1200:
# rows = round(80 * 0.75 * 0.5) = 30

jp2a and chafa apply this automatically when you give only a width. ImageMagick does not, so if you are resizing by hand, resize to 80x30! with the exclamation mark to force the non-uniform scale. The exact ratio depends on the font: 0.5 suits most monospace faces, but a condensed font may want 0.45 and some terminal defaults 0.55. Adjust by eye against a known circle.

Boxes, braille and colour

Pure seven-bit ASCII with + - | corners renders anywhere, including in a fifteen-year-old mail client. Unicode box-drawing characters from the U+2500 block look far better and need only a font with reasonable coverage, which every modern terminal has. Going further, the braille block at U+2800 packs a 2x4 grid of dots into a single cell, giving eight times the effective resolution; this is how terminal graph tools draw smooth curves. The cost is that braille output is unreadable in any font missing those glyphs and useless to a screen reader, so keep it for live displays rather than files you commit.

Colour is ANSI escapes: \033[38;5;208m for the 256-colour palette, \033[38;2;255;95;31m for truecolor, and always \033[0m at the end or the rest of the session inherits your colour. Check $COLORTERM for truecolor before emitting 24-bit codes, and strip escapes entirely when output is not a TTY.

Shipping it without breaking things

Stay within 80 columns for anything going into a README, a commit message, an email or a MOTD; wider art wraps and turns into noise on the first narrow viewport it meets. In Markdown, always wrap art in a fenced code block, or leading spaces get collapsed and consecutive lines get joined into a paragraph. Watch for editors and formatters stripping trailing whitespace, which silently deletes the right-hand side of art that relies on padding; exclude those files in .editorconfig and your formatter's ignore file. If you embed art in source code, remember backslashes need escaping in most string literals, and a lone backslash at the end of a line will eat the next one. Finally, attribution: a great deal of the classic ASCII art in circulation is signed by its author in the bottom corner, and stripping those initials to reuse the piece is the one thing the community has always treated as unforgivable. Keep the signature or draw your own.

Want More?

Explore our complete collection of free tools and resources.

Visit spunk.bet
400+ Free Tools Free Casino Meme Generator Birth Charts Scam Database BPM Calculator