forked from LiveCarta/BookConverter
155 lines
4.4 KiB
Python
155 lines
4.4 KiB
Python
import re
|
|
|
|
from colorsys import hls_to_rgb
|
|
from webcolors import html4_hex_to_names, hex_to_rgb, rgb_to_name, rgb_percent_to_hex, rgb_to_hex, css3_names_to_hex
|
|
|
|
|
|
|
|
def closest_colour_rgb(requested_color):
|
|
""" Function finds closes colour rgb """
|
|
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 rgb2color_name(color):
|
|
""" Transform rgb -> color name """
|
|
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 hex2color_name(color):
|
|
""" Transform hex -> color name """
|
|
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):
|
|
""" Transform str -> closest color name """
|
|
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 = rgb2color_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 = hex2color_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 rgba2rgb(r, g, b, alpha):
|
|
""" Transform rgba -> rgb """
|
|
r_background, g_background, b_background = 255, 255, 255
|
|
r_new = int((1 - alpha) * r_background + alpha * r)
|
|
g_new = int((1 - alpha) * g_background + alpha * g)
|
|
b_new = int((1 - alpha) * b_background + alpha * b)
|
|
return r_new, g_new, b_new
|
|
|
|
|
|
def str2hex(s: str):
|
|
""" Transform str -> hex """
|
|
if '#' in s and (len(s) <= 7):
|
|
return s.lower()
|
|
|
|
if ('rgb' in s) and ('%' in s):
|
|
match = re.search(r'rgba*\(((\d+)%, *(\d+)%, *(\d+)%(, \d\.\d+)*)\)', s)
|
|
if match:
|
|
r, g, b = int(match.group(2)), int(match.group(3)), int(match.group(4))
|
|
return rgb_percent_to_hex((r, g, b))
|
|
|
|
if 'rgb' in s:
|
|
match = re.search(r'rgba*\(((\d+), *(\d+), *(\d+), (\d\.\d+)*)\)', s)
|
|
if match:
|
|
r, g, b = int(match.group(2)), int(match.group(3)), int(match.group(4))
|
|
if match.group(5):
|
|
alpha = float(match.group(5))
|
|
r, g, b = rgba2rgb(r, g, b, alpha)
|
|
return rgb_to_hex((r, g, b))
|
|
|
|
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 = int(match.group(2)), int(match.group(3)), int(match.group(4))
|
|
h /= 360
|
|
s /= 10
|
|
l /= 100
|
|
rgb = tuple(hls_to_rgb(h, s, l))
|
|
if match.group(5):
|
|
alpha = match.group(5)
|
|
rgb = rgba2rgb(*rgb, alpha)
|
|
return rgb_to_hex(rgb)
|
|
|
|
if s.lower() in css3_names_to_hex:
|
|
return css3_names_to_hex[s.lower()]
|
|
|
|
return ''
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
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 = rgb2color_name(c)
|
|
print("Actual colour:", c, ", closest colour name:", n)
|
|
|
|
for c in hex_colors:
|
|
n = hex2color_name(c)
|
|
print("Actual colour:", c, ", closest colour name:", n)
|
|
print()
|