--- /dev/null
+from PIL import Image,ImageFilter
+from functools import partial
+from os.path import join, dirname, getmtime, exists, expanduser
+
+import ctypes, sys, os
+
+def call_c():
+ library = expanduser('~/.image.so')
+ sauce = join(dirname(__file__), 'image.c')
+ if not exists(library) or getmtime(sauce) > getmtime(library):
+ build = "gcc -fPIC -shared -o %s %s" % (library, sauce)
+ assert os.system(build + " >/dev/null 2>&1") == 0
+ image_c= ctypes.cdll.LoadLibrary(library)
+ image_c.init()
+ return image_c.rgb_to_ansi
+
+rgb2short = call_c()
+
+def pixel_print(ansicolor):
+ sys.stdout.write('\033[48;5;%sm \033[0m' % (ansicolor))
+
+def image_to_display(path):
+ i = Image.open(path)
+ i = i.convert('RGBA')
+ w,h = i.size
+ i.load()
+ rows, columns = os.popen('stty size', 'r').read().split()
+ width = min(w, int(columns)-2*6)
+ height = int(float(h) * (float(width) / float(w)))
+ height //= 2
+ i = i.resize((width, height), Image.BICUBIC)
+ height = min(height,30)
+
+ for y in xrange(height):
+ print ' '*6 ,
+ for x in xrange(width):
+ p = i.getpixel((x,y))
+ r, g, b = p[:3]
+ pixel_print(rgb2short(r,g,b))
+ print ''
+
+if __name__ == '__main__':
+ image_to_display(sys.argv[1])
--- /dev/null
+typedef struct {
+ int r;
+ int g;
+ int b;
+} rgb_t;
+int CUBE_STEPS[] = { 0x00, 0x5F, 0x87, 0xAF, 0xD7, 0xFF };
+rgb_t BASIC16[] =
+ { { 0, 0, 0 }, { 205, 0, 0}, { 0, 205, 0 },
+ { 205, 205, 0 }, { 0, 0, 238}, { 205, 0, 205 },
+ { 0, 205, 205 }, { 229, 229, 229}, { 127, 127, 127 },
+ { 255, 0, 0 }, { 0, 255, 0}, { 255, 255, 0 },
+ { 92, 92, 255 }, { 255, 0, 255}, { 0, 255, 255 },
+ { 255, 255, 255 } };
+rgb_t COLOR_TABLE[256];
+
+
+rgb_t xterm_to_rgb(int xcolor)
+{
+ rgb_t res;
+ if (xcolor < 16) {
+ res = BASIC16[xcolor];
+ } else if (16 <= xcolor && xcolor <= 231) {
+ xcolor -= 16;
+ res.r = CUBE_STEPS[(xcolor / 36) % 6];
+ res.g = CUBE_STEPS[(xcolor / 6) % 6];
+ res.b = CUBE_STEPS[xcolor % 6];
+ } else if (232 <= xcolor && xcolor <= 255) {
+ res.r = res.g = res.b = 8 + (xcolor - 232) * 0x0A;
+ }
+ return res;
+}
+
+int init()
+{
+ int c;
+ for (c = 0; c < 256; c++) {
+ COLOR_TABLE[c] = xterm_to_rgb(c);
+ }
+ return 0;
+}
+
+int rgb_to_ansi(int r, int g, int b)
+{
+ int best_match = 0;
+ int smallest_distance = 1000000000;
+ int c, d;
+ for (c = 16; c < 256; c++) {
+ d = (COLOR_TABLE[c].r - r)*(COLOR_TABLE[c].r - r) +
+ (COLOR_TABLE[c].g - g)*(COLOR_TABLE[c].g - g) +
+ (COLOR_TABLE[c].b - b)*(COLOR_TABLE[c].b - b);
+ if (d < smallest_distance) {
+ smallest_distance = d;
+ best_match = c;
+ }
+ }
+ return best_match;
+}
from PIL import Image,ImageFilter
-import sys,os
from functools import partial
-""" Convert values between RGB hex codes and xterm-256 color codes.
-
-Nice long listing of all 256 colors and their codes. Useful for
-developing console color themes, or even script output schemes.
-
-Resources:
-* http://en.wikipedia.org/wiki/8-bit_color
-* http://en.wikipedia.org/wiki/ANSI_escape_code
-* /usr/share/X11/rgb.txt
-
-I'm not sure where this script was inspired from. I think I must have
-written it from scratch, though it's been several years now.
-"""
-
-__author__ = 'Micah Elliott http://MicahElliott.com'
-__version__ = '0.1'
-__copyright__ = 'Copyright (C) 2011 Micah Elliott. All rights reserved.'
-__license__ = 'WTFPL http://sam.zoy.org/wtfpl/'
-
-#---------------------------------------------------------------------
-
-import sys, re
+import sys,os
CLUT = [ # color look-up table
# 8-bit, RGB hex
('238', '444444'),
('239', '4e4e4e'),
('240', '585858'),
-
('241', '626262'),
('242', '6c6c6c'),
('243', '767676'),
('244', '808080'),
-
('245', '8a8a8a'),
('246', '949494'),
('247', '9e9e9e'),
('248', 'a8a8a8'),
-
('249', 'b2b2b2'),
('250', 'bcbcbc'),
('251', 'c6c6c6'),
('252', 'd0d0d0'),
('253', 'dadada'),
-
('254', 'e4e4e4'),
('255', 'eeeeee'),
]
-def _strip_hash(rgb):
- # Strip leading `#` if exists.
- if rgb.startswith('#'):
- rgb = rgb.lstrip('#')
- return rgb
-
def _create_dicts():
short2rgb_dict = dict(CLUT)
rgb2short_dict = {}
rgb2short_dict[v] = k
return rgb2short_dict, short2rgb_dict
+RGB2SHORT_DICT, SHORT2RGB_DICT = _create_dicts()
+
+
def short2rgb(short):
return SHORT2RGB_DICT[short]
+
def pixel_print(ansicolor):
sys.stdout.write('\033[48;5;%sm \033[0m' % (ansicolor))
+
def hex_to_rgb(value):
value = value.lstrip('#')
lv = len(value)
return tuple(int(value[i:i+lv/3], 16) for i in range(0, lv, lv/3))
+
def rgb_to_hex(rgb):
- return '#%02x%02x%02x' % rgb
+ return '%02x%02x%02x' % rgb
-def binary_search(ary,(r,g,b)):
- ary.sort()
- if len(ary) == 1 : return ary[0]
- mid = len(ary)//2
- left = binary_search(ary[:mid],(r,g,b))
- right = binary_search(ary[mid:],(r,g,b))
- ld = (left[0]-r)**2 + (left[1]-g)**2 + (left[2]-b)**2
- rd = (right[0]-r)**2 + (right[1]-g)**2 + (right[2]-b)**2
- if ld < rd :
- return left
- else:
- return right
-
-def rgb2short(rgb):
- """ Find the closest xterm-256 approximation to the given RGB value.
- @param rgb: Hex code representing an RGB value, eg, 'abcdef'
- @returns: String between 0 and 255, compatible with xterm.
- """
- rgb = _strip_hash(rgb)
- r = int(rgb[:2],16)
- g = int(rgb[2:4],16)
- b = int(rgb[4:],16)
+def rgb2short(r, g, b):
dist = lambda s,d: (s[0]-d[0])**2+(s[1]-d[1])**2+(s[2]-d[2])**2
ary = [hex_to_rgb(hex) for hex in RGB2SHORT_DICT]
- m = binary_search(ary,(r,g,b))
m = min(ary, key=partial(dist, (r,g,b)))
- return RGB2SHORT_DICT[_strip_hash(rgb_to_hex(m))]
-
-
-# incs = (0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff)
-# parts = [ int(h, 16) for h in re.split(r'(..)(..)(..)', rgb)[1:4] ]
-# res = []
-# for part in parts:
-# i = 0
-# while i < len(incs)-1:
-# s, b = incs[i], incs[i+1] # smaller, bigger
-# if s <= part <= b:
-# s1 = abs(s - part)
-# b1 = abs(b - part)
-# if s1 < b1: closest = s
-# else: closest = b
-# res.append(closest)
-# break
-# i += 1
-# #print '***', res
-# res = ''.join([ ('%02.x' % i) for i in res ])
-# equiv = RGB2SHORT_DICT[ res ]
-# #print '***', res, equiv
-# return equiv
-#
-RGB2SHORT_DICT, SHORT2RGB_DICT = _create_dicts()
+ return RGB2SHORT_DICT[rgb_to_hex(m)]
def image_to_display(path):
i = Image.open(path)
height = int(float(h) * (float(width) / float(w)))
height //= 2
i = i.resize((width, height), Image.BICUBIC)
+ height = min(height,30)
for y in xrange(height):
print ' '*6 ,
for x in xrange(width):
p = i.getpixel((x,y))
r, g, b = p[:3]
- hex = rgb_to_hex((r,g,b))
- pixel_print(rgb2short(hex))
+ pixel_print(rgb2short(r,g,b))
print ''
-#---------------------------------------------------------------------
-
if __name__ == '__main__':
- path = sys.argv[1]
- image_to_display(path)
+ image_to_display(sys.argv[1])