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