#!/usr/bin/env ruby require 'RMagick' class XtermPeg def initialize( filename ) @filename = filename @cache = {} @colormap = {} File.open( "colors.txt" ) do |f| f.each do |l| a = l.strip.split( / / ) @colormap[ a[0].to_i ] = [ a[1].to_i(16), a[2].to_i(16), a[3].to_i(16) ] end end end def find_best_color( r, g, b ) m = r*65536+g*256+b return @cache[ m ] if @cache[ m ] bestidx = nil best = 256*256*256 # Find the best fit for the pixel @colormap.each do |k, v| # Calculate the distance between the colour we want, and the colour we're considering d = ( ( ( v[0] - r ).abs**2 + ( v[1] - g ).abs**2 + ( v[2] - b ).abs**2 ) ** 0.5 ).to_i if d < best bestidx = k best = d end end @cache[ m ] = bestidx end def run pic = Magick::Image.read( @filename )[0] (0...pic.rows).each do |r| next if r%2 == 1 # Terminal characters are usually (and roughly) twice as high as they are wide. pic.get_pixels( 0, r, pic.columns, 1 ).each_with_index do |pixel, c| print 27.chr + "[48;5;" + find_best_color( pixel.red/256, pixel.green/256, pixel.blue/256 ).to_s + "m " end print 27.chr + "[48;5;0m" puts end end end xterm = XtermPeg.new( ARGV[0] ) xterm.run