image by flag
[rainbowstream.git] / rainbowstream / pure_image.py
... / ...
CommitLineData
1from PIL import Image
2from functools import partial
3
4import sys
5import os
6
7CLUT = [ # color look-up table
8 # 8-bit, RGB hex
9
10 # Primary 3-bit (8 colors). Unique representation!
11 ('00', '000000'),
12 ('01', '800000'),
13 ('02', '008000'),
14 ('03', '808000'),
15 ('04', '000080'),
16 ('05', '800080'),
17 ('06', '008080'),
18 ('07', 'c0c0c0'),
19
20 # Equivalent "bright" versions of original 8 colors.
21 ('08', '808080'),
22 ('09', 'ff0000'),
23 ('10', '00ff00'),
24 ('11', 'ffff00'),
25 ('12', '0000ff'),
26 ('13', 'ff00ff'),
27 ('14', '00ffff'),
28 ('15', 'ffffff'),
29
30 # Strictly ascending.
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'),
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
275
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
283RGB2SHORT_DICT, SHORT2RGB_DICT = _create_dicts()
284
285
286def short2rgb(short):
287 return SHORT2RGB_DICT[short]
288
289
290def pixel_print(ansicolor):
291 sys.stdout.write('\033[48;5;%sm \033[0m' % (ansicolor))
292
293
294def hex_to_rgb(value):
295 value = value.lstrip('#')
296 lv = len(value)
297 return tuple(int(value[i:i + lv / 3], 16) for i in range(0, lv, lv / 3))
298
299
300def rgb_to_hex(rgb):
301 return '%02x%02x%02x' % rgb
302
303
304def rgb2short(r, g, b):
305 dist = lambda s, d: (s[0] - d[0]) ** 2 + \
306 (s[1] - d[1]) ** 2 + (s[2] - d[2]) ** 2
307 ary = [hex_to_rgb(hex) for hex in RGB2SHORT_DICT]
308 m = min(ary, key=partial(dist, (r, g, b)))
309 return RGB2SHORT_DICT[rgb_to_hex(m)]
310
311
312def image_to_display(path):
313 i = Image.open(path)
314 i = i.convert('RGBA')
315 w, h = i.size
316 i.load()
317 rows, columns = os.popen('stty size', 'r').read().split()
318 width = min(w, int(columns) - 2 * 6)
319 height = int(float(h) * (float(width) / float(w)))
320 height //= 2
321 i = i.resize((width, height), Image.BICUBIC)
322 height = min(height, 30)
323
324 for y in xrange(height):
325 print ' ' * 6,
326 for x in xrange(width):
327 p = i.getpixel((x, y))
328 r, g, b = p[:3]
329 pixel_print(rgb2short(r, g, b))
330 print ''
331
332if __name__ == '__main__':
333 image_to_display(sys.argv[1])