From 13d74ddc233be6f2de0286bb4caaf904dd07024e Mon Sep 17 00:00:00 2001 From: shirshasa Date: Fri, 20 Aug 2021 16:14:11 +0300 Subject: [PATCH] epub converter: add rgb2closest_color.py --- src/util/rgb2closest_color.py | 126 ++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 src/util/rgb2closest_color.py diff --git a/src/util/rgb2closest_color.py b/src/util/rgb2closest_color.py new file mode 100644 index 0000000..3cbcd88 --- /dev/null +++ b/src/util/rgb2closest_color.py @@ -0,0 +1,126 @@ +from webcolors import html4_hex_to_names, hex_to_rgb + +# 16 основных цветов, hex соответвуют hex цветам livecarta +# названия другие +html4_hex_to_names = {'#00ffff': 'aqua', '#000000': 'black', '#0000ff': 'blue', '#ff00ff': 'fuchsia', + '#008000': 'green', '#808080': 'grey', '#00ff00': 'lime', '#800000': 'maroon', '#000080': 'navy', + '#808000': 'olive', '#800080': 'purple', '#ff0000': 'red', '#c0c0c0': 'silver', '#008080': 'teal', + '#ffffff': 'white', '#ffff00': 'yellow'} + + +def rgb2hsv(r, g, b): + r /= 255 + g /= 255 + b /= 255 + max_c = max(r, g, b) + min_c = min(r, g, b) + value = max_c + if min_c == max_c: + return 0.0, 0.0, value * 100 + + saturation = (max_c - min_c) / max_c + rc = (max_c - r) / (max_c - min_c) + gc = (max_c - g) / (max_c - min_c) + bc = (max_c - b) / (max_c - min_c) + + if r == max_c: + hue = 0.0 + bc - gc + elif g == max_c: + hue = 2.0 + rc - bc + else: + hue = 4.0 + gc - rc + + hue0 = (hue / 6.0) % 1.0 + hue2 = ((hue + 6) / 6.0) if (hue < 0) else (hue / 6.0) + + return hue2 * 360, saturation * 100, value * 100 + + +HTML_COLORS_HSV = {} +for key, name in html4_hex_to_names.items(): + r, g, b = hex_to_rgb(key) + h, s, v = rgb2hsv(r, g, b) + HTML_COLORS_HSV[name] = (h, s, v) + + +def rgb2closest_html_color_name(color): + """ + + + - get color in hsv (hue, saturation, value) + - try to match with black, grey, silver (black, darkGray, lightGray) as this colors matches badly even in hsv model + + - calc hue difference between color and all base colors + - if for new base color hue diff same as for any other, try to measure saturation and value + (it happens for similar colors like red - pink, blue - dark blue) + + :param color: str, color in hex + :return: base color name that matches best to a given color + """ + + if color == (255, 255, 255): + return 'white' + + diff2base_color_dict = {} + rgb = hex_to_rgb(color) + hue_request, s_request, v_request = rgb2hsv(*rgb) + if v_request <= 30: + return 'black' + if v_request <= 50 and s_request <= 25: # ** + return 'gray' + if s_request <= 10 and (90 <= v_request <= 100): + return 'white' + if s_request <= 40: + return 'silver' + + for _, name in html4_hex_to_names.items(): + if name in ['white', 'black', 'grey', 'silver']: + continue + hue_html, s_html, v_html = HTML_COLORS_HSV[name] + + hue_diff = abs(hue_html - hue_request) + + if hue_diff == 20: + pass + + if hue_diff in diff2base_color_dict: + dist_cur_color = (s_request - s_html) ** 2 + (v_request - v_html) ** 2 + hue_prev, s_prev, v_prev = HTML_COLORS_HSV[diff2base_color_dict[hue_diff]] + dist_prev_color = (s_request - s_prev) ** 2 + (v_request - v_prev) ** 2 + # print(name, diff2base_color_dict[hue_diff],) + # print(dist_cur_color, dist_prev_color) + # print() + if dist_cur_color < dist_prev_color: + diff2base_color_dict[hue_diff] = name + else: + diff2base_color_dict[hue_diff] = name + + # print(diff2base_color_dict) + return diff2base_color_dict[min(diff2base_color_dict.keys())] + + +if __name__ == '__main__': + + hex_colors = [ + #'#945893', + # '#96F', + # '#000', # black + # '#4C4C4C', # black + # '#A00', + # '#99F', + '#f89921', + + # '#f89921', '#EFF8F6' + # '#e5c099', # yellow + # '#008b90', # teal + # '#c4762a', # red + # '#996A95', '#70416F', # purple + # '#D5C9D3', '#E9E2E8', # silver + # '#FFD472', '#F47B4D', '#FFFBEF', '#F47B4D', # yellow, red ,yellow, red + # '#B0DFD7', '#EFF8F6', '#5CC4B7' + ] + + for c in hex_colors: + n = rgb2closest_html_color_name(c) + print(n) # "Actual colour:", c, ", closest colour name:", + # print()