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