Printing images in the terminal with 9 lines of Ruby
There are many ways to bringing graphics into the text-based environment of the terminal. They range from libraries like curses to ASCII art, clever use of characters based on their visual intensity and terminal colours. This one is based on the last approach and makes it as simple as 9 lines of Ruby.
Let’s go straight to the code:
require "tco"
require "rmagick"
img = Magick::Image::read(ARGV[0]).first
img.each_pixel do |pixel, col, row|
c = [pixel.red, pixel.green, pixel.blue].map { |v| 256 * (v / 65535.0) }
pixel.opacity == 65535 ? print(" ") : print(" ".bg c)
puts if col >= img.columns - 1
end
This example combines two gems: rmagick to read the images and tco to map their pixels from RGB to the extended colour palette available in most terminals. It goes through each pixel and just writes it out using tco’s string extension that sets the appropriate background colour. A pixel is approximated with two blank spaces, so the results depends on the proportions of your console font.
The conditional on line 7 will leave out all completely opaque pixels, in case your image is a PNG with transparent background.
And this is how it looks:
The catpix
gem
I extended the above code with a few more features like automatic downsizing of the image based on the width of the terminal window, centering and adding custom background colours and turned it into a small gem called catpix.
require 'catpix'
Catpix::print_image "pokemon.png",
:limit_x => 1.0,
:limit_y => 0,
:center_x => true,
:center_y => true,
:bg => "white",
:bg_fill => true
Find the full description of the API at RubyDoc.
Here’s one more example with a photo of some flowers in my window, straight from my phone that was downsized to fit by catpix:
Is this really good for anything?
The possibilities are endless! Although the resolution of terminal screens usually isn’t that good, which is somewhat limiting. Still, here are a few ideas you might or might not want to use.
1. Rickroll people in the terminal
People won’t fall for your Rickrolls as easily nowadays. Like this guy on Reddit, you need to be increasingly more creative to pull one off. From now on, you can bring them into the terminal, where people expect them the least:
2. Access denied
Do you feel that the one-line error just isn’t enough to make it clear to users that credentials are required to perform this operation? Let Gandalf do the talking instead:
3. Wrong usage
People keep getting the command line options wrong, even through they make
perfect sense? Like -d
to create a file or -r
to write into it. Maybe
they’ll learn faster if you add this:
4. Something went wrong?
Indeed, some error messages aren’t easy to pass to the user. No matter how many times you ask them to back up their files, they’ll never do it. If something like this happens, take some pressure off your customer service team by sugarcoating the message a little:
What’s next?
I would love to see your ideas on using images in the terminal. Post them in the comments below or tweet at @radekpazdera.
You’ll find the catpix and tco gems on GitHub, both licensed under MIT. Enjoy!