TechEarl

How to Turn an Image Into ASCII Art From the Command Line

Turn any image into ASCII art from the terminal: jp2a for the classic monospace look (with ANSI color and an invert flag for dark terminals), and chafa for truecolor, Unicode-detail, and even animated GIFs.

Ishan Karunaratne⏱️ 7 min readUpdated
Share thisCopied
Turn a JPG or PNG into ASCII art from the command line with jp2a for the classic look and chafa for truecolor Unicode detail and animated GIFs.

The two tools that turn an image into terminal art are jp2a for the classic monospace ASCII look, and chafa for high-detail, truecolor output. The minimal versions:

bash
# Classic ASCII characters, 80 columns wide
jp2a --width=80 photo.jpg

# Modern, full-color, far more detail
chafa photo.png

jp2a gives you the recognizable typewriter-grain ASCII portrait. chafa is the one to reach for when you want the image to actually look good in the terminal, because it uses Unicode block and braille characters and 24-bit color instead of a 70-odd character ramp. The rest of this page is when to pick which, and the flags that matter.

jp2a: the classic ASCII look

jp2a maps each block of pixels to a single ASCII character chosen by brightness, which produces the familiar grayscale-text portrait. Despite the name, it reads both JPEG and PNG.

bash
jp2a --width=80 photo.jpg

The most useful flags:

bash
# ANSI color in the terminal (truecolor where supported, else 256-color)
jp2a --colors --width=100 photo.jpg

# Invert brightness for a light-on-dark terminal
jp2a --invert --width=80 photo.jpg

# Save the plain-text art to a file instead of printing it
jp2a --width=80 --output=art.txt photo.jpg

A few things worth knowing:

  • --colors prints with ANSI escape codes so the characters carry the image's colors. It looks great in the terminal but is no longer plain text, so do not pipe it somewhere that expects clean ASCII (more on saving below).
  • --invert flips the brightness-to-character mapping. The default ramp assumes a dark character on a light background (like ink on paper). On a normal dark terminal that comes out as a photo negative, so --invert is the flag you almost always want there.
  • --output=art.txt writes the result to a file. Without --colors, that file is portable plain text you can paste into a README or a code comment. jp2a can also emit HTML with --html if you want a colored version for the web.

If you only pass --width, jp2a works out the height from the image's aspect ratio, correcting for the fact that terminal cells are taller than they are wide. You rarely need to set both.

chafa: the modern, high-detail tool

chafa is the one I reach for when the output needs to look like the actual picture. Instead of a single ASCII character per cell it draws from Unicode block, quadrant, sextant, and braille glyphs, and it renders in 24-bit truecolor, so a single character cell can carry far more visual information than one ASCII glyph ever could.

bash
chafa photo.png

With no flags it auto-detects your terminal and picks the best output it can. If the terminal supports a real graphics protocol (sixel, Kitty, or iTerm2) chafa sends an actual bitmap; otherwise it falls back to Unicode character art. That detection is the whole appeal: you get the best your terminal can show without configuring anything.

Useful flags:

bash
# Constrain to a width x height in character cells
chafa --size=100x40 photo.png

# Pure monochrome braille art (no color, dense detail)
chafa --colors none --symbols braille photo.png

# Force a color mode if auto-detect guesses wrong: none, 2, 8, 16, 240, 256, full
chafa --colors 256 photo.png

# Force plain ASCII-only symbols (closest to the jp2a look)
chafa --symbols ascii photo.png

The --symbols classes (block, braille, ascii, half, quad, and more) let you trade detail for portability: braille packs the most pixels per cell, ascii keeps it copy-paste friendly. --colors full is the default truecolor mode; drop to 256 or 16 for terminals or recordings that mangle 24-bit color.

Animated GIFs

chafa also plays animated GIFs straight in the terminal, looping the frames in place:

bash
chafa animation.gif

This is genuinely useful for previewing a GIF over SSH without a desktop. jp2a does not do this.

Choosing a width that fits your terminal

The single most common mistake is asking for art wider than the terminal, which wraps every line and turns the picture into noise. Match the width to your actual column count:

bash
# How wide is the terminal, in columns?
tput cols

# Feed that straight into jp2a
jp2a --width=$(tput cols) photo.jpg

chafa handles this for you by default (it sizes to the terminal automatically), which is another reason it is the friendlier default. Use --size only when you want a specific, smaller dimension, for example to keep the art small enough to paste somewhere.

Plain text vs colored output: which to save

This distinction trips people up, so it is worth being explicit:

  • Plain ASCII text (no color flag) is portable. jp2a --width=80 --output=art.txt photo.jpg gives you a .txt you can drop into a README, a Git commit, or an email, and it renders anywhere a monospace font does.
  • Colored ANSI output (jp2a --colors, or chafa's default) embeds terminal escape codes. Redirect it to a file and the file contains those raw codes; it only displays correctly when cat-ed back into an ANSI-capable terminal, not in a plain text viewer.
bash
# Portable plain text
jp2a --width=80 --output=banner.txt photo.jpg

# Colored, terminal-only (escape codes baked in)
jp2a --colors --width=80 photo.jpg > color-art.ansi
cat color-art.ansi   # replays the colors

So: if the destination is a document or anywhere outside a terminal, keep it plain. If it is going to live in a terminal (a login banner, a cat-able file, an SSH session), color is fine.

Other tools worth knowing

jp2a and chafa cover almost every case, but two more come up in roundups and are worth a sentence each:

  • img2txt ships with the libcaca text-mode graphics library (the caca-utils package). It reads PNG, JPEG, GIF, and BMP, and its real strength is the output formats: besides colored ANSI it can emit HTML, SVG, IRC color codes, and PostScript. If you need ASCII art as SVG or HTML rather than terminal escape codes, it is the tool that does it directly. The character output itself is coarser than chafa's Unicode rendering.
  • ascii-image-converter is a single cross-platform Go binary (Linux, macOS, Windows) that does colored ASCII and braille art, reads JPEG, PNG, BMP, WEBP, TIFF, and GIF, and saves straight to a PNG or text file. It is the easiest to install on Windows where jp2a and chafa are fiddlier.

For most of what I do, the split is still: chafa for fidelity, jp2a for the classic plain-text look. The other two are situational.

FAQ

See also

Sources

Authoritative references this article was fact-checked against.

Tagsjp2achafaASCII artCLIterminalimage conversionLinux

Found this useful? Pass it on.

Copied

Ishan Karunaratne

Tech Architect · Software Engineer · AI/DevOps

Tech architect and software engineer with 20+ years building software, Linux systems, and DevOps infrastructure, and lately working AI into the stack. Currently Chief Technology Officer at a healthcare tech startup, which is where most of these field notes come from.

Keep reading

Related posts