Here's another one from the terminal graphics extravaganza dept: Chafa 1.6.0 brings fullwidth character support, so in addition to the usual block elements and ASCII art, you now get some mean CJK art too. Or grab as many fonts as you can and combine all of the Unicode into one big glorious mess. Chafa can efficiently distinguish between thousands of symbols, so it also runs fast enough for animations — up to a point.
Since some users want this in environments where it's not practical to build from source or even to have nice things like GLib, I've started adding statically linked builds. These are pretty bare-bones (fewer image loaders, no man page), so look to your steadfast distribution first.
Speaking of distributions, a big thank you to the packagers. Special thanks go to Florian Viehweger for getting in touch re. adding it to OpenBSD ports, and Mo Zhou (Debian), Michael Vetter (openSUSE), Herby Gillot (MacPorts), @chenrui and Carlo Cabrera (Homebrew) for getting 1.6 out there before I could even finish this post.
So what's it look like?
Obviously if you just want as faithful a reproduction as possible, stick with the default block elements or sixels. That said, fullwidth characters open up some new artistic possibilities.
Above, a rendering of Dog's Head (1920) by Julie de Graag, digitally enhanced by Rawpixel. It was generated with the following command line:
chafa --glyph-file /usr/share/fonts/truetype/SourceHanSansCN-Normal.otf \
--glyph-file /usr/share/fonts/truetype/SourceHanSansJP-Normal.otf \
--glyph-file /usr/share/fonts/truetype/DroidSansThai.ttf \
--glyph-file /usr/share/fonts/truetype/SourceCodePro-Regular.ttf \
--symbols 0..fffff-block-border-stipple-dot-geometric \
-c none -w 9 dog.png
Although I'd like to include a moderately large built-in selection of fullwidth symbols in a future release, for now you must load fonts with --glyph-file
in order to achieve this effect. You also need to enable the Unicode ranges you want and curtail the use of block and border elements with --symbols
. The latter is necessary because block elements produce more accurate results and will otherwise pretty much always come out on top during error minimization.
This is a rendering of Shinjuku Skyscrapers, CC-BY-SA Wilhelm Joys Andersen. I used the same set of options to produce it, but left out -c none
, resulting in 24-bit color — the default under VTE.
A side effect of allowing lots of color variation is fewer wide characters. This makes sense considering that they force a pair of cells to have the same color, which is often less accurate than two narrow characters with different colors.
彡 (._.) ( l: ) (.-.) ( :l )
Like many subjects that look simple at first, terminal graphics makes for a surprisingly deep rabbit hole to be tumbling into. Chafa now spans the gamut from the most basic monochrome ASCII art to fullwidth Unicode, 24-bit color and sixels, and there's still a lot that can be done to improve it. I will be doing so… slowly.
If you want to help, feel free to send pull requests or file any issues you find. I think it's also at the point where you can achieve various surprising effects, so if you manage to get something particularly cool/sick/downright disgusting out of it, just lob it in my general direction and maybe I'll include it in a future gallery.
Bit of a feedback on an issue I encountered playing around with Chafa recently.
~/hg/chafa$ LD_LIBRARY_PATH=./chafa/.libs /home/nemo/hg/chafa/tools/chafa/.libs/chafa ~/libera-color.svg > temp.ansi
Segmentation fault
Any redirection to a file crashed.
$ hg bisect -g
The first bad revision is:
changeset: 673:89152f358a00
user: Hans Petter Jansson
date: Mon Jul 13 20:35:53 2020 +0200
summary: ChafaCanvas: Split out symbol printing logic
The git revision being:
commit 58c3534cd9d2b59345e2e38a027d02a9d044fa87
0x00007f656cae9442 in coverage_to_bitmap (rowstride=16, cov=0x557c09630f90 "") at chafa-symbols.c:22
227I if (cov [y * rowstride + x])
Hm… actually bisect might have found another crash?
0x0000556aaff2ac06 in run_magickwand (quiet=, is_first_frame=1, is_first_file=1, filename=) at chafa.c:1471
1471 fwrite (frame->gs->str, sizeof (gchar), frame->gs->len, stdout);
lemme try skipping ahead a bit.
Ok. New crash location.
changeset: 773:e14883bb1031
user: Hans Petter Jansson
date: Tue Mar 02 22:01:47 2021 +0100
summary: symbols: Add Japanese kana symbols
git hash 44c93be7bcde7c346f6c22895f16d04219266c6f
At least it's recent! Also. Confirmed same crash location this time.
0x00007fc9f234e352 in coverage_to_bitmap (rowstride=16, cov=0x5579ed58df90 "") at chafa-symbols.c:221
221 if (cov [y * rowstride + x])
Eh… Feel free to delete useless comments above if you like. pippin figured out issue.
$ tools/chafa/chafa ~/computer.png > temp.ansi
Segmentation fault
$ /usr/local/bin/chafa ~/computer.png > temp.ansi
WORKS FINE
needed to be installed ☹
Sorry.
… it turns out that working in local did not mean it was *really* working 😃 hpf suggested
libtool –mode=execute valgrind tools/chafa/chafa and suuure enough…
So. Yay. Didn't spam up the feedback for nothing.
Nice find, thanks a lot for reporting it! This turned out to be a real issue, and as mentioned on IRC, the fix is now in master.
I can't get the same result for the dog with the same fonts. I get a lot of some kind of elongated dash symbol and very vew asian symbol. Could you try it again with the 1.7.0 version ?
There are new built-in symbols in master/1.7.0 that may be interfering. I'm able to get mostly Chinese characters with –symbols space+wide or (more complete, but more unwieldy) –symbols 0..fffff-block-border-stipple-dot-geometric-sextant-wedge.
You can also exclude the symbols you don't want to appear. Just copy/paste the symbol from the terminal into a Unicode search engine to look up its hex code, and subtract it from the symbol set. E.g. to use fullwidth symbols, but exclude the fullwidth macron, use –symbols wide-ffe3.
If you're still getting poor results, feel free to report it as an issue on GitHub or directly to me by e-mail!
What terminal emulator do you use ? And how do you've configured it ? Because, if you want to display some symbols from a particular font, you have to use it in your terminal.
I mostly use gnome-terminal and xfce4-terminal, which are both based on the VTE library. You're quite right: VTE is able to fall back to alternate fonts for each symbol, as long as the fonts are installed in the system path and findable by fontconfig.
Can chafa read in sixel images and output ascii-art? Basically, I'm hoping to update the tmux-sixel branch with chafa library support for processing a sixel data stream so that tmux can output sixel to the controlling device ttys and generate a fallback ascii-art representation for the scroll-back buffer.
https://github.com/tmux/tmux/issues/1613#issuecomment-562139529
The command-line utility can read most image formats, but the library backend only takes raw raster data (8-bit RGBA in its various permutations) as input. You'll have to find an image library or code snippet to decode the sixels. Since it's not a huge amount of code, it's probably easier to do the latter.
Take a look at how mintty integrated the parser based on libsixel's from_sixel.c here:
https://github.com/mintty/mintty/blob/master/src/sixel.c
Hans, the skyscrapers picture is the greatest terminal rendering of an image I have ever seen. Your software is amazing. Thanks.
Thanks for the kind comment!