| 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 | sys.stdout.write(' ' * 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 | sys.stdout.write('\n') |
| 342 | |
| 343 | if __name__ == '__main__': |
| 344 | image_to_display(sys.argv[1]) |