Merge pull request #185 from Jorick/master
[rainbowstream.git] / rainbowstream / c_image.py
CommitLineData
f70d3477 1# -*- coding: utf-8 -*-
0418d443 2from PIL import Image
60431c3b 3from os.path import join, dirname, getmtime, exists, expanduser
816e305f 4from .config import *
13e6b275 5from .py3patch import *
60431c3b 6
991c30af
O
7import ctypes
8import sys
9import os
10
60431c3b 11
12def call_c():
531f5682
O
13 """
14 Call the C program for converting RGB to Ansi colors
15 """
60431c3b 16 library = expanduser('~/.image.so')
17 sauce = join(dirname(__file__), 'image.c')
18 if not exists(library) or getmtime(sauce) > getmtime(library):
4a885ebf 19 build = "cc -fPIC -shared -o %s %s" % (library, sauce)
bb68c687 20 os.system(build + " >/dev/null 2>&1")
991c30af 21 image_c = ctypes.cdll.LoadLibrary(library)
60431c3b 22 image_c.init()
23 return image_c.rgb_to_ansi
24
25rgb2short = call_c()
991c30af
O
26
27
45ff44d2 28def pixel_print(pixel):
531f5682
O
29 """
30 Print a pixel with given Ansi color
31 """
45ff44d2 32 r, g, b = pixel[:3]
e9c756ae
JH
33
34 if c['24BIT'] is True:
35 sys.stdout.write('\033[48;2;%d;%d;%dm \033[0m'
36 % (r, g, b))
37 else:
38 ansicolor = rgb2short(r, g, b)
39 sys.stdout.write('\033[48;5;%sm \033[0m' % (ansicolor))
991c30af
O
40
41
69b6ab70 42def block_print(higher, lower):
a3cf675b
JH
43 """
44 Print two pixels arranged above each other with Ansi color.
45 Abuses Unicode to print two pixels in the space of one terminal block.
46 """
69b6ab70
JH
47 r0, g0, b0 = lower[:3]
48 r1, g1, b1 = higher[:3]
49
50 if c['24BIT'] is True:
51 sys.stdout.write('\033[38;2;%d;%d;%dm\033[48;2;%d;%d;%dm▄\033[0m'
52 % (r1, g1, b1, r0, g0, b0))
53 else:
54 i0 = rgb2short(r0, g0, b0)
55 i1 = rgb2short(r1, g1, b1)
56 sys.stdout.write('\033[38;5;%sm\033[48;5;%sm▄\033[0m' % (i1, i0))
a3cf675b
JH
57
58
422dd385 59def image_to_display(path, start=None, length=None):
531f5682
O
60 """
61 Display an image
62 """
4592d231 63 rows, columns = os.popen('stty size', 'r').read().split()
64 if not start:
632c6fa5 65 start = c['IMAGE_SHIFT']
4592d231 66 if not length:
67 length = int(columns) - 2 * start
991c30af 68 i = Image.open(path)
60431c3b 69 i = i.convert('RGBA')
991c30af 70 w, h = i.size
60431c3b 71 i.load()
4592d231 72 width = min(w, length)
60431c3b 73 height = int(float(h) * (float(width) / float(w)))
992c5266
JH
74
75 if c['IMAGE_RESIZE_TO_FIT'] is True:
76 # If it image won't fit in the terminal without scrolling shrink it
77 # Subtract 3 from rows so the tweet message fits in too.
78 h = 2 * (int(rows) - 3)
79 if height >= h:
80 width = int(float(width) * (float(h) / float(height)))
81 height = h
82 if (height <= 0) or (width <= 0):
83 raise ValueError("image has negative dimensions")
84
f5677fb1 85 i = i.resize((width, height), Image.ANTIALIAS)
632c6fa5 86 height = min(height, c['IMAGE_MAX_HEIGHT'])
60431c3b 87
99aa4140
O
88 for real_y in xrange(height // 2):
89 sys.stdout.write(' ' * start)
90 for x in xrange(width):
91 y = real_y * 2
92 p0 = i.getpixel((x, y))
fd2da0c3 93 p1 = i.getpixel((x, y + 1))
99aa4140
O
94 block_print(p1, p0)
95 sys.stdout.write('\n')
96
531f5682
O
97
98"""
99For direct using purpose
100"""
60431c3b 101if __name__ == '__main__':
102 image_to_display(sys.argv[1])