forked from LiveCarta/BookConverter
epub converter: add rgb2closest_color.py
This commit is contained in:
126
src/util/rgb2closest_color.py
Normal file
126
src/util/rgb2closest_color.py
Normal file
@@ -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()
|
||||
Reference in New Issue
Block a user