POSTS PROJECTS
27 May 2013

How and… WHY?!

If you know the shell I’m sure you know what cat is. Well this is the same but for pictures! >There is already something to see pictures, it’s called an Image Viewer…

Yeah, I know… Does it change anything? No, it doesn’t. Printin pictures to the standard output is just so funny. Thanks to the 256 colors we can represent the picture very well! Look at this:

Mario

I told you it was nice!

I though… >It would be so cool to have pictures printed right into the prompt… And actually it wasn’t that hard. I’m sure there are faster ways, you just need to do it in C, but as a shell script it is really cool.

How does it work

### Colors in shell To print color in the shell we use an escape code. Putting the right numbers makes it highlight the background on the color I needed. I actually did many tests with for loops to find out the one I needed. It turned out to be this one echo -e "\e[48;05;<color>m" where <color> is a value between 0 and 255 to select the color.

Picture conversion

As you may guess, you need to transform the picture in order to use the same color pallette used by the 256 colors shell. This is where ImageMagick comes in handy. convert will allow you to resize the picture to fit the console size, change the pallette to one of your choice and epxort the result in a very shell friendy format: text. After googling quite a bit it turned out that I needed a picture of the pallette colors. At first I though to echo all the colors but I won’t have their hexadecimal value. So I dearched up in Google again and found a webpage with the colors and the hexadecimal values here. The problem was that I couldn’t take a screenshot and use it because the text interpolation was causing new colors and the pallette was wrong. Therefore I took the source code in vim and tuned it up with some sed until it had no text at all. So I came from this:

original

to this

new

Then I just removed a bit of the picture to have the transparent color too. At the I just tested ot with many pictures, corrected some bugs (there were some hexadecimal codes that were wrongs)

Output the picture!

Here is where the tricky thing comes: thanks to the txt file that convert gives us, we can find in our list of colors the line, and that line is the numerical value we must use. Here is the line:

N=$(grep -n "$C" "$COLOR_CODE" | head -n1 | sed 's/:.*//g')
L=$(expr $N - 1 2>/dev/null)

Although, this is not fast at all. Many months later I found on the internet another version fo calculating the code. It was missing the grays so I added them. It looks like that:

convert "$IMG" -resize $COLS\> +dither `echo $REMAP` txt:- |
sed -e 's/.*none.*/NO NO NO/g' -e '1d;s/^.*(\(.*\)[,)].*$/\1/g;y/,/ /' |
while read R G B f; do
  if [ ! "$R" = "NO" ]; then
    if [ "$R" -eq "$G" -a "$G" -eq "$B" ]; then
      ((
      I++,
      IDX = 232 + R * 23 / 255
      ))
    else
      ((
      I++,
      IDX = 16
      + R * 5 / 255 * 36
      + G * 5 / 255 * 6
      + B * 5 / 255
      ))
    fi
    #echo "$R,$G,$B: $IDX"
    echo -ne "\e[48;5;${IDX}m${CHAR}"
  else
    (( I++ ))
    echo -ne "\e[0m${CHAR}"
  fi
  # New lines
  (( $I % $WIDTH )) || echo -e "\e[0m"
done

I need to use the NO to allow transparency.

Source Code

You can check the source at https://github.com/posva/catimg.

Have fun!


Twitter Facebook Google+