allretweet
[rainbowstream.git] / rainbowstream / pure_image.py
1 from PIL import Image
2 from functools import partial
3 from .config import *
4
5 import sys
6 import os
7
8 """
9 This file is borrowed from following gist:
10 https://gist.github.com/MicahElliott/719710
11 It's too slow in compare with C program.
12 """
13
14 CLUT = [ # color look-up table
15 # 8-bit, RGB hex
16
17 # Primary 3-bit (8 colors). Unique representation!
18 ('00', '000000'),
19 ('01', '800000'),
20 ('02', '008000'),
21 ('03', '808000'),
22 ('04', '000080'),
23 ('05', '800080'),
24 ('06', '008080'),
25 ('07', 'c0c0c0'),
26
27 # Equivalent "bright" versions of original 8 colors.
28 ('08', '808080'),
29 ('09', 'ff0000'),
30 ('10', '00ff00'),
31 ('11', 'ffff00'),
32 ('12', '0000ff'),
33 ('13', 'ff00ff'),
34 ('14', '00ffff'),
35 ('15', 'ffffff'),
36
37 # Strictly ascending.
38 ('16', '000000'),
39 ('17', '00005f'),
40 ('18', '000087'),
41 ('19', '0000af'),
42 ('20', '0000d7'),
43 ('21', '0000ff'),
44 ('22', '005f00'),
45 ('23', '005f5f'),
46 ('24', '005f87'),
47 ('25', '005faf'),
48 ('26', '005fd7'),
49 ('27', '005fff'),
50 ('28', '008700'),
51 ('29', '00875f'),
52 ('30', '008787'),
53 ('31', '0087af'),
54 ('32', '0087d7'),
55 ('33', '0087ff'),
56 ('34', '00af00'),
57 ('35', '00af5f'),
58 ('36', '00af87'),
59 ('37', '00afaf'),
60 ('38', '00afd7'),
61 ('39', '00afff'),
62 ('40', '00d700'),
63 ('41', '00d75f'),
64 ('42', '00d787'),
65 ('43', '00d7af'),
66 ('44', '00d7d7'),
67 ('45', '00d7ff'),
68 ('46', '00ff00'),
69 ('47', '00ff5f'),
70 ('48', '00ff87'),
71 ('49', '00ffaf'),
72 ('50', '00ffd7'),
73 ('51', '00ffff'),
74 ('52', '5f0000'),
75 ('53', '5f005f'),
76 ('54', '5f0087'),
77 ('55', '5f00af'),
78 ('56', '5f00d7'),
79 ('57', '5f00ff'),
80 ('58', '5f5f00'),
81 ('59', '5f5f5f'),
82 ('60', '5f5f87'),
83 ('61', '5f5faf'),
84 ('62', '5f5fd7'),
85 ('63', '5f5fff'),
86 ('64', '5f8700'),
87 ('65', '5f875f'),
88 ('66', '5f8787'),
89 ('67', '5f87af'),
90 ('68', '5f87d7'),
91 ('69', '5f87ff'),
92 ('70', '5faf00'),
93 ('71', '5faf5f'),
94 ('72', '5faf87'),
95 ('73', '5fafaf'),
96 ('74', '5fafd7'),
97 ('75', '5fafff'),
98 ('76', '5fd700'),
99 ('77', '5fd75f'),
100 ('78', '5fd787'),
101 ('79', '5fd7af'),
102 ('80', '5fd7d7'),
103 ('81', '5fd7ff'),
104 ('82', '5fff00'),
105 ('83', '5fff5f'),
106 ('84', '5fff87'),
107 ('85', '5fffaf'),
108 ('86', '5fffd7'),
109 ('87', '5fffff'),
110 ('88', '870000'),
111 ('89', '87005f'),
112 ('90', '870087'),
113 ('91', '8700af'),
114 ('92', '8700d7'),
115 ('93', '8700ff'),
116 ('94', '875f00'),
117 ('95', '875f5f'),
118 ('96', '875f87'),
119 ('97', '875faf'),
120 ('98', '875fd7'),
121 ('99', '875fff'),
122 ('100', '878700'),
123 ('101', '87875f'),
124 ('102', '878787'),
125 ('103', '8787af'),
126 ('104', '8787d7'),
127 ('105', '8787ff'),
128 ('106', '87af00'),
129 ('107', '87af5f'),
130 ('108', '87af87'),
131 ('109', '87afaf'),
132 ('110', '87afd7'),
133 ('111', '87afff'),
134 ('112', '87d700'),
135 ('113', '87d75f'),
136 ('114', '87d787'),
137 ('115', '87d7af'),
138 ('116', '87d7d7'),
139 ('117', '87d7ff'),
140 ('118', '87ff00'),
141 ('119', '87ff5f'),
142 ('120', '87ff87'),
143 ('121', '87ffaf'),
144 ('122', '87ffd7'),
145 ('123', '87ffff'),
146 ('124', 'af0000'),
147 ('125', 'af005f'),
148 ('126', 'af0087'),
149 ('127', 'af00af'),
150 ('128', 'af00d7'),
151 ('129', 'af00ff'),
152 ('130', 'af5f00'),
153 ('131', 'af5f5f'),
154 ('132', 'af5f87'),
155 ('133', 'af5faf'),
156 ('134', 'af5fd7'),
157 ('135', 'af5fff'),
158 ('136', 'af8700'),
159 ('137', 'af875f'),
160 ('138', 'af8787'),
161 ('139', 'af87af'),
162 ('140', 'af87d7'),
163 ('141', 'af87ff'),
164 ('142', 'afaf00'),
165 ('143', 'afaf5f'),
166 ('144', 'afaf87'),
167 ('145', 'afafaf'),
168 ('146', 'afafd7'),
169 ('147', 'afafff'),
170 ('148', 'afd700'),
171 ('149', 'afd75f'),
172 ('150', 'afd787'),
173 ('151', 'afd7af'),
174 ('152', 'afd7d7'),
175 ('153', 'afd7ff'),
176 ('154', 'afff00'),
177 ('155', 'afff5f'),
178 ('156', 'afff87'),
179 ('157', 'afffaf'),
180 ('158', 'afffd7'),
181 ('159', 'afffff'),
182 ('160', 'd70000'),
183 ('161', 'd7005f'),
184 ('162', 'd70087'),
185 ('163', 'd700af'),
186 ('164', 'd700d7'),
187 ('165', 'd700ff'),
188 ('166', 'd75f00'),
189 ('167', 'd75f5f'),
190 ('168', 'd75f87'),
191 ('169', 'd75faf'),
192 ('170', 'd75fd7'),
193 ('171', 'd75fff'),
194 ('172', 'd78700'),
195 ('173', 'd7875f'),
196 ('174', 'd78787'),
197 ('175', 'd787af'),
198 ('176', 'd787d7'),
199 ('177', 'd787ff'),
200 ('178', 'd7af00'),
201 ('179', 'd7af5f'),
202 ('180', 'd7af87'),
203 ('181', 'd7afaf'),
204 ('182', 'd7afd7'),
205 ('183', 'd7afff'),
206 ('184', 'd7d700'),
207 ('185', 'd7d75f'),
208 ('186', 'd7d787'),
209 ('187', 'd7d7af'),
210 ('188', 'd7d7d7'),
211 ('189', 'd7d7ff'),
212 ('190', 'd7ff00'),
213 ('191', 'd7ff5f'),
214 ('192', 'd7ff87'),
215 ('193', 'd7ffaf'),
216 ('194', 'd7ffd7'),
217 ('195', 'd7ffff'),
218 ('196', 'ff0000'),
219 ('197', 'ff005f'),
220 ('198', 'ff0087'),
221 ('199', 'ff00af'),
222 ('200', 'ff00d7'),
223 ('201', 'ff00ff'),
224 ('202', 'ff5f00'),
225 ('203', 'ff5f5f'),
226 ('204', 'ff5f87'),
227 ('205', 'ff5faf'),
228 ('206', 'ff5fd7'),
229 ('207', 'ff5fff'),
230 ('208', 'ff8700'),
231 ('209', 'ff875f'),
232 ('210', 'ff8787'),
233 ('211', 'ff87af'),
234 ('212', 'ff87d7'),
235 ('213', 'ff87ff'),
236 ('214', 'ffaf00'),
237 ('215', 'ffaf5f'),
238 ('216', 'ffaf87'),
239 ('217', 'ffafaf'),
240 ('218', 'ffafd7'),
241 ('219', 'ffafff'),
242 ('220', 'ffd700'),
243 ('221', 'ffd75f'),
244 ('222', 'ffd787'),
245 ('223', 'ffd7af'),
246 ('224', 'ffd7d7'),
247 ('225', 'ffd7ff'),
248 ('226', 'ffff00'),
249 ('227', 'ffff5f'),
250 ('228', 'ffff87'),
251 ('229', 'ffffaf'),
252 ('230', 'ffffd7'),
253 ('231', 'ffffff'),
254
255 # Gray-scale range.
256 ('232', '080808'),
257 ('233', '121212'),
258 ('234', '1c1c1c'),
259 ('235', '262626'),
260 ('236', '303030'),
261 ('237', '3a3a3a'),
262 ('238', '444444'),
263 ('239', '4e4e4e'),
264 ('240', '585858'),
265 ('241', '626262'),
266 ('242', '6c6c6c'),
267 ('243', '767676'),
268 ('244', '808080'),
269 ('245', '8a8a8a'),
270 ('246', '949494'),
271 ('247', '9e9e9e'),
272 ('248', 'a8a8a8'),
273 ('249', 'b2b2b2'),
274 ('250', 'bcbcbc'),
275 ('251', 'c6c6c6'),
276 ('252', 'd0d0d0'),
277 ('253', 'dadada'),
278 ('254', 'e4e4e4'),
279 ('255', 'eeeeee'),
280 ]
281
282
283 def _create_dicts():
284 short2rgb_dict = dict(CLUT)
285 rgb2short_dict = {}
286 for k, v in short2rgb_dict.items():
287 rgb2short_dict[v] = k
288 return rgb2short_dict, short2rgb_dict
289
290 RGB2SHORT_DICT, SHORT2RGB_DICT = _create_dicts()
291
292
293 def short2rgb(short):
294 return SHORT2RGB_DICT[short]
295
296
297 def pixel_print(ansicolor):
298 sys.stdout.write('\033[48;5;%sm \033[0m' % (ansicolor))
299
300
301 def hex_to_rgb(value):
302 value = value.lstrip('#')
303 lv = len(value)
304 return tuple(int(value[i:i + lv / 3], 16) for i in range(0, lv, lv / 3))
305
306
307 def rgb_to_hex(rgb):
308 return '%02x%02x%02x' % rgb
309
310
311 def rgb2short(r, g, b):
312 dist = lambda s, d: (s[0] - d[0]) ** 2 + \
313 (s[1] - d[1]) ** 2 + (s[2] - d[2]) ** 2
314 ary = [hex_to_rgb(hex) for hex in RGB2SHORT_DICT]
315 m = min(ary, key=partial(dist, (r, g, b)))
316 return RGB2SHORT_DICT[rgb_to_hex(m)]
317
318
319 def image_to_display(path,start=None,length=None):
320 rows, columns = os.popen('stty size', 'r').read().split()
321 if not start:
322 start = IMAGE_SHIFT
323 if not length:
324 length = int(columns) - 2 * start
325 i = Image.open(path)
326 i = i.convert('RGBA')
327 w, h = i.size
328 i.load()
329 width = min(w, length)
330 height = int(float(h) * (float(width) / float(w)))
331 height //= 2
332 i = i.resize((width, height), Image.BICUBIC)
333 height = min(height, IMAGE_MAX_HEIGHT)
334
335 for y in xrange(height):
336 print ' ' * start,
337 for x in xrange(width):
338 p = i.getpixel((x, y))
339 r, g, b = p[:3]
340 pixel_print(rgb2short(r, g, b))
341 print ''
342
343 if __name__ == '__main__':
344 image_to_display(sys.argv[1])