Spaces:
Runtime error
Runtime error
# | |
# The Python Imaging Library | |
# $Id$ | |
# | |
# map CSS3-style colour description strings to RGB | |
# | |
# History: | |
# 2002-10-24 fl Added support for CSS-style color strings | |
# 2002-12-15 fl Added RGBA support | |
# 2004-03-27 fl Fixed remaining int() problems for Python 1.5.2 | |
# 2004-07-19 fl Fixed gray/grey spelling issues | |
# 2009-03-05 fl Fixed rounding error in grayscale calculation | |
# | |
# Copyright (c) 2002-2004 by Secret Labs AB | |
# Copyright (c) 2002-2004 by Fredrik Lundh | |
# | |
# See the README file for information on usage and redistribution. | |
# | |
import re | |
from . import Image | |
def getrgb(color): | |
""" | |
Convert a color string to an RGB or RGBA tuple. If the string cannot be | |
parsed, this function raises a :py:exc:`ValueError` exception. | |
.. versionadded:: 1.1.4 | |
:param color: A color string | |
:return: ``(red, green, blue[, alpha])`` | |
""" | |
if len(color) > 100: | |
msg = "color specifier is too long" | |
raise ValueError(msg) | |
color = color.lower() | |
rgb = colormap.get(color, None) | |
if rgb: | |
if isinstance(rgb, tuple): | |
return rgb | |
colormap[color] = rgb = getrgb(rgb) | |
return rgb | |
# check for known string formats | |
if re.match("#[a-f0-9]{3}$", color): | |
return int(color[1] * 2, 16), int(color[2] * 2, 16), int(color[3] * 2, 16) | |
if re.match("#[a-f0-9]{4}$", color): | |
return ( | |
int(color[1] * 2, 16), | |
int(color[2] * 2, 16), | |
int(color[3] * 2, 16), | |
int(color[4] * 2, 16), | |
) | |
if re.match("#[a-f0-9]{6}$", color): | |
return int(color[1:3], 16), int(color[3:5], 16), int(color[5:7], 16) | |
if re.match("#[a-f0-9]{8}$", color): | |
return ( | |
int(color[1:3], 16), | |
int(color[3:5], 16), | |
int(color[5:7], 16), | |
int(color[7:9], 16), | |
) | |
m = re.match(r"rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$", color) | |
if m: | |
return int(m.group(1)), int(m.group(2)), int(m.group(3)) | |
m = re.match(r"rgb\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)$", color) | |
if m: | |
return ( | |
int((int(m.group(1)) * 255) / 100.0 + 0.5), | |
int((int(m.group(2)) * 255) / 100.0 + 0.5), | |
int((int(m.group(3)) * 255) / 100.0 + 0.5), | |
) | |
m = re.match( | |
r"hsl\(\s*(\d+\.?\d*)\s*,\s*(\d+\.?\d*)%\s*,\s*(\d+\.?\d*)%\s*\)$", color | |
) | |
if m: | |
from colorsys import hls_to_rgb | |
rgb = hls_to_rgb( | |
float(m.group(1)) / 360.0, | |
float(m.group(3)) / 100.0, | |
float(m.group(2)) / 100.0, | |
) | |
return ( | |
int(rgb[0] * 255 + 0.5), | |
int(rgb[1] * 255 + 0.5), | |
int(rgb[2] * 255 + 0.5), | |
) | |
m = re.match( | |
r"hs[bv]\(\s*(\d+\.?\d*)\s*,\s*(\d+\.?\d*)%\s*,\s*(\d+\.?\d*)%\s*\)$", color | |
) | |
if m: | |
from colorsys import hsv_to_rgb | |
rgb = hsv_to_rgb( | |
float(m.group(1)) / 360.0, | |
float(m.group(2)) / 100.0, | |
float(m.group(3)) / 100.0, | |
) | |
return ( | |
int(rgb[0] * 255 + 0.5), | |
int(rgb[1] * 255 + 0.5), | |
int(rgb[2] * 255 + 0.5), | |
) | |
m = re.match(r"rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$", color) | |
if m: | |
return int(m.group(1)), int(m.group(2)), int(m.group(3)), int(m.group(4)) | |
msg = f"unknown color specifier: {repr(color)}" | |
raise ValueError(msg) | |
def getcolor(color, mode): | |
""" | |
Same as :py:func:`~PIL.ImageColor.getrgb` for most modes. However, if | |
``mode`` is HSV, converts the RGB value to a HSV value, or if ``mode`` is | |
not color or a palette image, converts the RGB value to a greyscale value. | |
If the string cannot be parsed, this function raises a :py:exc:`ValueError` | |
exception. | |
.. versionadded:: 1.1.4 | |
:param color: A color string | |
:param mode: Convert result to this mode | |
:return: ``(graylevel[, alpha]) or (red, green, blue[, alpha])`` | |
""" | |
# same as getrgb, but converts the result to the given mode | |
color, alpha = getrgb(color), 255 | |
if len(color) == 4: | |
color, alpha = color[:3], color[3] | |
if mode == "HSV": | |
from colorsys import rgb_to_hsv | |
r, g, b = color | |
h, s, v = rgb_to_hsv(r / 255, g / 255, b / 255) | |
return int(h * 255), int(s * 255), int(v * 255) | |
elif Image.getmodebase(mode) == "L": | |
r, g, b = color | |
# ITU-R Recommendation 601-2 for nonlinear RGB | |
# scaled to 24 bits to match the convert's implementation. | |
color = (r * 19595 + g * 38470 + b * 7471 + 0x8000) >> 16 | |
if mode[-1] == "A": | |
return color, alpha | |
else: | |
if mode[-1] == "A": | |
return color + (alpha,) | |
return color | |
colormap = { | |
# X11 colour table from https://drafts.csswg.org/css-color-4/, with | |
# gray/grey spelling issues fixed. This is a superset of HTML 4.0 | |
# colour names used in CSS 1. | |
"aliceblue": "#f0f8ff", | |
"antiquewhite": "#faebd7", | |
"aqua": "#00ffff", | |
"aquamarine": "#7fffd4", | |
"azure": "#f0ffff", | |
"beige": "#f5f5dc", | |
"bisque": "#ffe4c4", | |
"black": "#000000", | |
"blanchedalmond": "#ffebcd", | |
"blue": "#0000ff", | |
"blueviolet": "#8a2be2", | |
"brown": "#a52a2a", | |
"burlywood": "#deb887", | |
"cadetblue": "#5f9ea0", | |
"chartreuse": "#7fff00", | |
"chocolate": "#d2691e", | |
"coral": "#ff7f50", | |
"cornflowerblue": "#6495ed", | |
"cornsilk": "#fff8dc", | |
"crimson": "#dc143c", | |
"cyan": "#00ffff", | |
"darkblue": "#00008b", | |
"darkcyan": "#008b8b", | |
"darkgoldenrod": "#b8860b", | |
"darkgray": "#a9a9a9", | |
"darkgrey": "#a9a9a9", | |
"darkgreen": "#006400", | |
"darkkhaki": "#bdb76b", | |
"darkmagenta": "#8b008b", | |
"darkolivegreen": "#556b2f", | |
"darkorange": "#ff8c00", | |
"darkorchid": "#9932cc", | |
"darkred": "#8b0000", | |
"darksalmon": "#e9967a", | |
"darkseagreen": "#8fbc8f", | |
"darkslateblue": "#483d8b", | |
"darkslategray": "#2f4f4f", | |
"darkslategrey": "#2f4f4f", | |
"darkturquoise": "#00ced1", | |
"darkviolet": "#9400d3", | |
"deeppink": "#ff1493", | |
"deepskyblue": "#00bfff", | |
"dimgray": "#696969", | |
"dimgrey": "#696969", | |
"dodgerblue": "#1e90ff", | |
"firebrick": "#b22222", | |
"floralwhite": "#fffaf0", | |
"forestgreen": "#228b22", | |
"fuchsia": "#ff00ff", | |
"gainsboro": "#dcdcdc", | |
"ghostwhite": "#f8f8ff", | |
"gold": "#ffd700", | |
"goldenrod": "#daa520", | |
"gray": "#808080", | |
"grey": "#808080", | |
"green": "#008000", | |
"greenyellow": "#adff2f", | |
"honeydew": "#f0fff0", | |
"hotpink": "#ff69b4", | |
"indianred": "#cd5c5c", | |
"indigo": "#4b0082", | |
"ivory": "#fffff0", | |
"khaki": "#f0e68c", | |
"lavender": "#e6e6fa", | |
"lavenderblush": "#fff0f5", | |
"lawngreen": "#7cfc00", | |
"lemonchiffon": "#fffacd", | |
"lightblue": "#add8e6", | |
"lightcoral": "#f08080", | |
"lightcyan": "#e0ffff", | |
"lightgoldenrodyellow": "#fafad2", | |
"lightgreen": "#90ee90", | |
"lightgray": "#d3d3d3", | |
"lightgrey": "#d3d3d3", | |
"lightpink": "#ffb6c1", | |
"lightsalmon": "#ffa07a", | |
"lightseagreen": "#20b2aa", | |
"lightskyblue": "#87cefa", | |
"lightslategray": "#778899", | |
"lightslategrey": "#778899", | |
"lightsteelblue": "#b0c4de", | |
"lightyellow": "#ffffe0", | |
"lime": "#00ff00", | |
"limegreen": "#32cd32", | |
"linen": "#faf0e6", | |
"magenta": "#ff00ff", | |
"maroon": "#800000", | |
"mediumaquamarine": "#66cdaa", | |
"mediumblue": "#0000cd", | |
"mediumorchid": "#ba55d3", | |
"mediumpurple": "#9370db", | |
"mediumseagreen": "#3cb371", | |
"mediumslateblue": "#7b68ee", | |
"mediumspringgreen": "#00fa9a", | |
"mediumturquoise": "#48d1cc", | |
"mediumvioletred": "#c71585", | |
"midnightblue": "#191970", | |
"mintcream": "#f5fffa", | |
"mistyrose": "#ffe4e1", | |
"moccasin": "#ffe4b5", | |
"navajowhite": "#ffdead", | |
"navy": "#000080", | |
"oldlace": "#fdf5e6", | |
"olive": "#808000", | |
"olivedrab": "#6b8e23", | |
"orange": "#ffa500", | |
"orangered": "#ff4500", | |
"orchid": "#da70d6", | |
"palegoldenrod": "#eee8aa", | |
"palegreen": "#98fb98", | |
"paleturquoise": "#afeeee", | |
"palevioletred": "#db7093", | |
"papayawhip": "#ffefd5", | |
"peachpuff": "#ffdab9", | |
"peru": "#cd853f", | |
"pink": "#ffc0cb", | |
"plum": "#dda0dd", | |
"powderblue": "#b0e0e6", | |
"purple": "#800080", | |
"rebeccapurple": "#663399", | |
"red": "#ff0000", | |
"rosybrown": "#bc8f8f", | |
"royalblue": "#4169e1", | |
"saddlebrown": "#8b4513", | |
"salmon": "#fa8072", | |
"sandybrown": "#f4a460", | |
"seagreen": "#2e8b57", | |
"seashell": "#fff5ee", | |
"sienna": "#a0522d", | |
"silver": "#c0c0c0", | |
"skyblue": "#87ceeb", | |
"slateblue": "#6a5acd", | |
"slategray": "#708090", | |
"slategrey": "#708090", | |
"snow": "#fffafa", | |
"springgreen": "#00ff7f", | |
"steelblue": "#4682b4", | |
"tan": "#d2b48c", | |
"teal": "#008080", | |
"thistle": "#d8bfd8", | |
"tomato": "#ff6347", | |
"turquoise": "#40e0d0", | |
"violet": "#ee82ee", | |
"wheat": "#f5deb3", | |
"white": "#ffffff", | |
"whitesmoke": "#f5f5f5", | |
"yellow": "#ffff00", | |
"yellowgreen": "#9acd32", | |
} | |