#!/usr/local/bin/python2 # encoding: UTF-8 import sys import argparse from PIL import Image class conf(object): pad = True bw = False file = None class Color(object): CLEAR = "\033[0m" ALPHA_LIMIT = 1 GREYSCALE_BEGIN = 232 COLOR_BEGIN = 16 def __init__(self, rgba): r, g, b, a = rgba self.r = r self.g = g self.b = b self.a = a def escape(self, value): return "\033[48;5;%dm" % value def code(self): is_clear = self.a < self.ALPHA_LIMIT if is_clear: return self.CLEAR elif conf.bw: return self.bw_code() else: return self.color_code() def color_code(self): ratio = 5.0 / 255.0 r = int(round(ratio * self.r)) g = int(round(ratio * self.g)) b = int(round(ratio * self.b)) return self.escape( r * 6 * 6 + g * 6 + b + self.COLOR_BEGIN ) def bw_code(self): ratio = 24.0 / 255.0 avg = (self.r + self.g + self.b)/3.0 shade = int(round(ratio * avg)) return self.escape(shade + self.GREYSCALE_BEGIN) def calc_size(img): iw, ih = img.size aspect = float(iw) / float(ih) # image aspect font = 2.0 # font aspect h = ih w = h * aspect * font w = int(round(w)) return (w, h) def main(**kwargs): img = Image.open(conf.file) w, h = calc_size(img) img = img.resize(calc_size(img)) img = img.convert("RGBA") pix = img.load() write = sys.stdout.write if conf.pad: write("\n") for y in xrange(h): sys.stdout.write(Color.CLEAR) if conf.pad: write(" ") write(" ") for x in xrange(w): rgba = pix[x, y] code = Color(rgba).code() write(code) write(" ") write(Color.CLEAR) write("\n") parser = argparse.ArgumentParser( description="Print ANSI art for an image to standard output." ) parser.add_argument( "file", type=str, help="File to convert" ) parser.add_argument( "--bw", action="store_const", const=True, default=False, help="Enable greyscale mode" ) parser.add_argument( "--no-pad", action="store_const", const=True, default=False, help="Disable padding" ) args = parser.parse_args() conf.bw = args.bw conf.pad = not args.no_pad conf.file = args.file main()