Last active

  • Download Gist

Displaying images in the terminal with tput and echo


Requires ImageMagick, easily available from your favorite package manager. Tested on Linux and OSX
convert image.png -resize 40 txt:-|sed -E 's/://;s/\( ? ?//;s/, ? ?/,/g;s/\)//;s/([0-9]+,[0-9]+,[0-9]+),[0-9]+/\1/g;s/255/254/g;/mage/d'|awk '{print $1,$2}'|sed -E 's/^0,[0-9]+ /print "echo;tput setaf "\;/;s/^[0-9]+,[0-9]+ /print "tput setaf ";/;s/(.+),(.+),(.+)/\1\/42.5*36+\2\/42.5*6+\3\/42.5+16/'|bc|sed 's/$/;echo -n "  ";/'|tr '\n' ' '|sed 's/^/tput rev;/;s/; /;/g;s/$/tput sgr0;echo/'|bash

Old way, with python (cheating):

convert image.png -resize 40 txt:-|sed -E 's/://;s/\( ? ?//;s/, ? ?/,/g;s/\)//;s/(\w,\w,\w),\w/\1/g;/mage/d'|awk '{print $1,$2}'|python -c "import sys;'\n');f=filter(None,f);print 'tput rev;'+''.join([''.join(map(str,('echo;' if x.split(' ')[0].split(',')[0] is '0' else '','tput setaf '+str(sum(p*q for p,q in zip([36,6,1],[int(min(int(c),254)/42.5) for c in x.split(' ')[1].split(',')]))+16)+';echo -n \"  \";'))) for x in f])+'echo;tput sgr0'"|bash

Or, in your profile:

# Display image with tput
function image() {
convert $1 -resize 40 txt:-|sed -E 's/://;s/\( ? ?//;s/, ? ?/,/g;s/\)//;s/([0-9]+,[0-9]+,[0-9]+),[0-9]+/\1/g;s/255/254/g;/mage/d'|awk '{print $1,$2}'|sed -E 's/^0,[0-9]+ /print "echo;tput setaf "\;/;s/^[0-9]+,[0-9]+ /print "tput setaf ";/;s/(.+),(.+),(.+)/\1\/42.5*36+\2\/42.5*6+\3\/42.5+16/'|bc|sed 's/$/;echo -n "  ";/'|tr '\n' ' '|sed 's/^/tput rev;/;s/; /;/g;s/$/tput sgr0;echo/'|bash

then, on file or url:
image image.png

If you want to be able to specify a resolution, change image() as follows:
convert "$1" -resize "$2" txt:-...

This one-liner has ImageMagick resize and convert the image into a list of pixel data, which are filtered and piped into inline python ( UPDATE: now without python! ) as a raw list of x,y r,g,b where rgb values are mapped to a terminal color space and then rendered into a string of tput and echo commands, which are finally executed by bash. Note that this violates every conceived notion of efficiency, practicality, readability and maintainability. If you have mission-critical terminal imaging needs, the caca-utils package can probably help.

On OSX, if you use a higher resolution (passing 80 to convert), the sheer number of commands piped to bash may cause a segfault. In that case you need to increase the stack size (ulimit -s 32768) for the session. This issue does not occur on Linux for me even though the default ulimit parameters are the same.
For layered gifs, pass -layers flatten to convert.

I am not responsible if you get fired for using this to dynamically change your boss' MOTD to questionable content.

The colors, which are the 'web-safe' colors, can be viewed here without ImageMagick:

n=6;for r in $(seq 16 $n 231);do echo "$(for c in $(seq $n);do v=$(($r + $c - 1));tput setaf $v && echo -ne $(printf "%03d" $v);echo -n ' '; done)";done



Another fun example, <140 chars (no ImageMagick):

n=16;for r in $(seq 0 $n 255);do echo "$(for c in $(seq $n);do tput setaf $(($r + $c - 1)) && echo -ne '\xE2\x98\x85 ';done)";done


Please sign in to comment on this gist.

Something went wrong with that request. Please try again.