import re from webcolors import html4_hex_to_names, hex_to_rgb, rgb_to_name, rgb_percent_to_hex, rgb_to_hex, css3_names_to_hex from colorsys import hls_to_rgb def closest_colour_rgb(requested_color): min_colours = {} for key, name in html4_hex_to_names.items(): r_c, g_c, b_c = hex_to_rgb(key) rd = (r_c - requested_color[0]) ** 2 gd = (g_c - requested_color[1]) ** 2 bd = (b_c - requested_color[2]) ** 2 min_colours[(rd + gd + bd)] = name return min_colours[min(min_colours.keys())] def get_rgb_color_name(color): try: closest_name = actual_name = rgb_to_name(color, 'html4') except ValueError: closest_name = closest_colour_rgb(color) actual_name = None if actual_name: return actual_name else: return closest_name def get_hex_color_name(color): try: color = hex_to_rgb(color) except ValueError: return '' try: closest_name = actual_name = rgb_to_name(color, 'html4') except ValueError: closest_name = closest_colour_rgb(color) actual_name = None if actual_name: return actual_name else: return closest_name def str2closest_html_color_name(s: str): if 'rgb' in s: rgb_str = 'rgba' if ('rgba' in s) else 'rgb' s = s.replace(rgb_str, '').replace('(', '').replace(')', '') try: rgb = [int(x) for x in s.split(',')[:3]] rgb = tuple(rgb) except ValueError: return '' if len(rgb) != 3: return '' name = get_rgb_color_name(rgb) return name elif '#' in s: if s in ['#996A95', '#D5C9D3', '#E9E2E8', '#70416F']: return 'purple' if s in ['#FFD472', '#F47B4D', '#FFFBEF', '#F47B4D']: return 'olive' if s in ['#B0DFD7', '#EFF8F6', '#5CC4B7']: return 'teal' name = get_hex_color_name(s) if (name == 'white') and (s.lower() not in ['#ffffff', '#fff']): name = 'gray' return name elif s in html4_hex_to_names.items(): return s else: return '' def str2hex(s: str): if '#' in s: return s if ('rgb' in s) and ('%' in s): rgb_str = 'rgba' if ('rgba' in s) else 'rgb' s = s.replace(rgb_str, '').replace('(', '').replace(')', '') rgb_percent = s.split(',')[:3] hex_color = rgb_percent_to_hex(rgb_percent) return hex_color if 'rgb' in s: rgb_str = 'rgba' if ('rgba' in s) else 'rgb' s = s.replace(rgb_str, '').replace('(', '').replace(')', '') try: rgb = [int(x) for x in s.split(',')[:3]] rgb = tuple(rgb) except ValueError: return '' hex_color = rgb_to_hex(rgb) return hex_color if 'hsl' in s: # hsl(hue in {0,360}, saturation [0, 100%], lightness [0, 100%]) match = re.search(r'hsla*\(((\d+), *(\d+)%, *(\d+)%(, \d\.\d)*)\)', s) if match: h, s, l = match.group(2), match.group(3), match.group(4) h /= 360 s /= 10 l /= 100 rgb = tuple(hls_to_rgb(h, s, l)) return rgb_to_hex(rgb) if s.lower() in css3_names_to_hex: return css3_names_to_hex[s.lower()] return '' if __name__ == '__main__': str2color_name('rgb(139, 0, 0)') colors = [ (75, 0, 130), (255, 0, 255), (139, 69, 19), (46, 139, 87), (221, 160, 221) ] hex_colors = [ '#96F', '#000', '#4C4C4C', '#A00', '#99F' ] for c in colors: n = get_rgb_color_name(c) print("Actual colour:", c, ", closest colour name:", n) for c in hex_colors: n = get_hex_color_name(c) print("Actual colour:", c, ", closest colour name:", n) print()