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