| # We did not author this file nor mantain it. Skip linting it. |
| #pylint: skip-file |
| """ Convert values between RGB hex codes and xterm-256 color codes. |
| |
| Nice long listing of all 256 colors and their codes. Useful for |
| developing console color themes, or even script output schemes. |
| |
| Resources: |
| * http://en.wikipedia.org/wiki/8-bit_color |
| * http://en.wikipedia.org/wiki/ANSI_escape_code |
| * /usr/share/X11/rgb.txt |
| |
| I'm not sure where this script was inspired from. I think I must have |
| written it from scratch, though it's been several years now. |
| """ |
| |
| __author__ = 'Micah Elliott http://MicahElliott.com' |
| __version__ = '0.1' |
| __copyright__ = 'Copyright (C) 2011 Micah Elliott. All rights reserved.' |
| __license__ = 'WTFPL http://sam.zoy.org/wtfpl/' |
| |
| #--------------------------------------------------------------------- |
| |
| import sys, re |
| |
| CLUT = [ # color look-up table |
| # 8-bit, RGB hex |
| |
| # Primary 3-bit (8 colors). Unique representation! |
| ('00', '000000'), |
| ('01', '800000'), |
| ('02', '008000'), |
| ('03', '808000'), |
| ('04', '000080'), |
| ('05', '800080'), |
| ('06', '008080'), |
| ('07', 'c0c0c0'), |
| |
| # Equivalent "bright" versions of original 8 colors. |
| ('08', '808080'), |
| ('09', 'ff0000'), |
| ('10', '00ff00'), |
| ('11', 'ffff00'), |
| ('12', '0000ff'), |
| ('13', 'ff00ff'), |
| ('14', '00ffff'), |
| ('15', 'ffffff'), |
| |
| # Strictly ascending. |
| ('16', '000000'), |
| ('17', '00005f'), |
| ('18', '000087'), |
| ('19', '0000af'), |
| ('20', '0000d7'), |
| ('21', '0000ff'), |
| ('22', '005f00'), |
| ('23', '005f5f'), |
| ('24', '005f87'), |
| ('25', '005faf'), |
| ('26', '005fd7'), |
| ('27', '005fff'), |
| ('28', '008700'), |
| ('29', '00875f'), |
| ('30', '008787'), |
| ('31', '0087af'), |
| ('32', '0087d7'), |
| ('33', '0087ff'), |
| ('34', '00af00'), |
| ('35', '00af5f'), |
| ('36', '00af87'), |
| ('37', '00afaf'), |
| ('38', '00afd7'), |
| ('39', '00afff'), |
| ('40', '00d700'), |
| ('41', '00d75f'), |
| ('42', '00d787'), |
| ('43', '00d7af'), |
| ('44', '00d7d7'), |
| ('45', '00d7ff'), |
| ('46', '00ff00'), |
| ('47', '00ff5f'), |
| ('48', '00ff87'), |
| ('49', '00ffaf'), |
| ('50', '00ffd7'), |
| ('51', '00ffff'), |
| ('52', '5f0000'), |
| ('53', '5f005f'), |
| ('54', '5f0087'), |
| ('55', '5f00af'), |
| ('56', '5f00d7'), |
| ('57', '5f00ff'), |
| ('58', '5f5f00'), |
| ('59', '5f5f5f'), |
| ('60', '5f5f87'), |
| ('61', '5f5faf'), |
| ('62', '5f5fd7'), |
| ('63', '5f5fff'), |
| ('64', '5f8700'), |
| ('65', '5f875f'), |
| ('66', '5f8787'), |
| ('67', '5f87af'), |
| ('68', '5f87d7'), |
| ('69', '5f87ff'), |
| ('70', '5faf00'), |
| ('71', '5faf5f'), |
| ('72', '5faf87'), |
| ('73', '5fafaf'), |
| ('74', '5fafd7'), |
| ('75', '5fafff'), |
| ('76', '5fd700'), |
| ('77', '5fd75f'), |
| ('78', '5fd787'), |
| ('79', '5fd7af'), |
| ('80', '5fd7d7'), |
| ('81', '5fd7ff'), |
| ('82', '5fff00'), |
| ('83', '5fff5f'), |
| ('84', '5fff87'), |
| ('85', '5fffaf'), |
| ('86', '5fffd7'), |
| ('87', '5fffff'), |
| ('88', '870000'), |
| ('89', '87005f'), |
| ('90', '870087'), |
| ('91', '8700af'), |
| ('92', '8700d7'), |
| ('93', '8700ff'), |
| ('94', '875f00'), |
| ('95', '875f5f'), |
| ('96', '875f87'), |
| ('97', '875faf'), |
| ('98', '875fd7'), |
| ('99', '875fff'), |
| ('100', '878700'), |
| ('101', '87875f'), |
| ('102', '878787'), |
| ('103', '8787af'), |
| ('104', '8787d7'), |
| ('105', '8787ff'), |
| ('106', '87af00'), |
| ('107', '87af5f'), |
| ('108', '87af87'), |
| ('109', '87afaf'), |
| ('110', '87afd7'), |
| ('111', '87afff'), |
| ('112', '87d700'), |
| ('113', '87d75f'), |
| ('114', '87d787'), |
| ('115', '87d7af'), |
| ('116', '87d7d7'), |
| ('117', '87d7ff'), |
| ('118', '87ff00'), |
| ('119', '87ff5f'), |
| ('120', '87ff87'), |
| ('121', '87ffaf'), |
| ('122', '87ffd7'), |
| ('123', '87ffff'), |
| ('124', 'af0000'), |
| ('125', 'af005f'), |
| ('126', 'af0087'), |
| ('127', 'af00af'), |
| ('128', 'af00d7'), |
| ('129', 'af00ff'), |
| ('130', 'af5f00'), |
| ('131', 'af5f5f'), |
| ('132', 'af5f87'), |
| ('133', 'af5faf'), |
| ('134', 'af5fd7'), |
| ('135', 'af5fff'), |
| ('136', 'af8700'), |
| ('137', 'af875f'), |
| ('138', 'af8787'), |
| ('139', 'af87af'), |
| ('140', 'af87d7'), |
| ('141', 'af87ff'), |
| ('142', 'afaf00'), |
| ('143', 'afaf5f'), |
| ('144', 'afaf87'), |
| ('145', 'afafaf'), |
| ('146', 'afafd7'), |
| ('147', 'afafff'), |
| ('148', 'afd700'), |
| ('149', 'afd75f'), |
| ('150', 'afd787'), |
| ('151', 'afd7af'), |
| ('152', 'afd7d7'), |
| ('153', 'afd7ff'), |
| ('154', 'afff00'), |
| ('155', 'afff5f'), |
| ('156', 'afff87'), |
| ('157', 'afffaf'), |
| ('158', 'afffd7'), |
| ('159', 'afffff'), |
| ('160', 'd70000'), |
| ('161', 'd7005f'), |
| ('162', 'd70087'), |
| ('163', 'd700af'), |
| ('164', 'd700d7'), |
| ('165', 'd700ff'), |
| ('166', 'd75f00'), |
| ('167', 'd75f5f'), |
| ('168', 'd75f87'), |
| ('169', 'd75faf'), |
| ('170', 'd75fd7'), |
| ('171', 'd75fff'), |
| ('172', 'd78700'), |
| ('173', 'd7875f'), |
| ('174', 'd78787'), |
| ('175', 'd787af'), |
| ('176', 'd787d7'), |
| ('177', 'd787ff'), |
| ('178', 'd7af00'), |
| ('179', 'd7af5f'), |
| ('180', 'd7af87'), |
| ('181', 'd7afaf'), |
| ('182', 'd7afd7'), |
| ('183', 'd7afff'), |
| ('184', 'd7d700'), |
| ('185', 'd7d75f'), |
| ('186', 'd7d787'), |
| ('187', 'd7d7af'), |
| ('188', 'd7d7d7'), |
| ('189', 'd7d7ff'), |
| ('190', 'd7ff00'), |
| ('191', 'd7ff5f'), |
| ('192', 'd7ff87'), |
| ('193', 'd7ffaf'), |
| ('194', 'd7ffd7'), |
| ('195', 'd7ffff'), |
| ('196', 'ff0000'), |
| ('197', 'ff005f'), |
| ('198', 'ff0087'), |
| ('199', 'ff00af'), |
| ('200', 'ff00d7'), |
| ('201', 'ff00ff'), |
| ('202', 'ff5f00'), |
| ('203', 'ff5f5f'), |
| ('204', 'ff5f87'), |
| ('205', 'ff5faf'), |
| ('206', 'ff5fd7'), |
| ('207', 'ff5fff'), |
| ('208', 'ff8700'), |
| ('209', 'ff875f'), |
| ('210', 'ff8787'), |
| ('211', 'ff87af'), |
| ('212', 'ff87d7'), |
| ('213', 'ff87ff'), |
| ('214', 'ffaf00'), |
| ('215', 'ffaf5f'), |
| ('216', 'ffaf87'), |
| ('217', 'ffafaf'), |
| ('218', 'ffafd7'), |
| ('219', 'ffafff'), |
| ('220', 'ffd700'), |
| ('221', 'ffd75f'), |
| ('222', 'ffd787'), |
| ('223', 'ffd7af'), |
| ('224', 'ffd7d7'), |
| ('225', 'ffd7ff'), |
| ('226', 'ffff00'), |
| ('227', 'ffff5f'), |
| ('228', 'ffff87'), |
| ('229', 'ffffaf'), |
| ('230', 'ffffd7'), |
| ('231', 'ffffff'), |
| |
| # Gray-scale range. |
| ('232', '080808'), |
| ('233', '121212'), |
| ('234', '1c1c1c'), |
| ('235', '262626'), |
| ('236', '303030'), |
| ('237', '3a3a3a'), |
| ('238', '444444'), |
| ('239', '4e4e4e'), |
| ('240', '585858'), |
| ('241', '626262'), |
| ('242', '6c6c6c'), |
| ('243', '767676'), |
| ('244', '808080'), |
| ('245', '8a8a8a'), |
| ('246', '949494'), |
| ('247', '9e9e9e'), |
| ('248', 'a8a8a8'), |
| ('249', 'b2b2b2'), |
| ('250', 'bcbcbc'), |
| ('251', 'c6c6c6'), |
| ('252', 'd0d0d0'), |
| ('253', 'dadada'), |
| ('254', 'e4e4e4'), |
| ('255', 'eeeeee'), |
| ] |
| |
| |
| def _str2hex(hexstr): |
| return int(hexstr, 16) |
| |
| |
| def _strip_hash(rgb): |
| # Strip leading `#` if exists. |
| if rgb.startswith('#'): |
| rgb = rgb.lstrip('#') |
| return rgb |
| |
| |
| def _create_dicts(): |
| short2rgb_dict = dict(CLUT) |
| rgb2short_dict = {} |
| for k, v in short2rgb_dict.items(): |
| rgb2short_dict[v] = k |
| return rgb2short_dict, short2rgb_dict |
| |
| |
| def short2rgb(short): |
| return SHORT2RGB_DICT[short] |
| |
| |
| def print_all(): |
| """ Print all 256 xterm color codes. |
| """ |
| for short, rgb in CLUT: |
| sys.stdout.write('\033[48;5;%sm%s:%s' % (short, short, rgb)) |
| sys.stdout.write('\033[0m ') |
| sys.stdout.write('\033[38;5;%sm%s:%s' % (short, short, rgb)) |
| sys.stdout.write('\033[0m\n') |
| print 'Printed all codes.' |
| print 'You can translate a hex or 0-255 code by providing an argument.' |
| |
| |
| def rgb2short(rgb): |
| """ Find the closest xterm-256 approximation to the given RGB value. |
| @param rgb: Hex code representing an RGB value, eg, 'abcdef' |
| @returns: String between 0 and 255, compatible with xterm. |
| >>> rgb2short('123456') |
| ('23', '005f5f') |
| >>> rgb2short('ffffff') |
| ('231', 'ffffff') |
| >>> rgb2short('0DADD6') # vimeo logo |
| ('38', '00afd7') |
| """ |
| rgb = _strip_hash(rgb) |
| incs = (0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff) |
| # Break 6-char RGB code into 3 integer vals. |
| parts = [int(h, 16) for h in re.split(r'(..)(..)(..)', rgb)[1:4]] |
| res = [] |
| for part in parts: |
| i = 0 |
| while i < len(incs) - 1: |
| s, b = incs[i], incs[i + 1] # smaller, bigger |
| if s <= part <= b: |
| s1 = abs(s - part) |
| b1 = abs(b - part) |
| if s1 < b1: |
| closest = s |
| else: |
| closest = b |
| res.append(closest) |
| break |
| i += 1 |
| #print '***', res |
| res = ''.join([('%02.x' % i) for i in res]) |
| equiv = RGB2SHORT_DICT[res] |
| #print '***', res, equiv |
| return equiv, res |
| |
| |
| RGB2SHORT_DICT, SHORT2RGB_DICT = _create_dicts() |
| |
| #--------------------------------------------------------------------- |
| |
| if __name__ == '__main__': |
| import doctest |
| doctest.testmod() |
| if len(sys.argv) == 1: |
| print_all() |
| raise SystemExit |
| arg = sys.argv[1] |
| if len(arg) < 4 and int(arg) < 256: |
| rgb = short2rgb(arg) |
| sys.stdout.write( |
| 'xterm color \033[38;5;%sm%s\033[0m -> RGB exact \033[38;5;%sm%s\033[0m' |
| % (arg, arg, arg, rgb)) |
| sys.stdout.write('\033[0m\n') |
| else: |
| short, rgb = rgb2short(arg) |
| sys.stdout.write('RGB %s -> xterm color approx \033[38;5;%sm%s (%s)' % |
| (arg, short, short, rgb)) |
| sys.stdout.write('\033[0m\n') |