Coverage for /usr/lib/python3/dist-packages/PIL/ImageColor.py: 14%

64 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-14 15:55 +0200

1# 

2# The Python Imaging Library 

3# $Id$ 

4# 

5# map CSS3-style colour description strings to RGB 

6# 

7# History: 

8# 2002-10-24 fl Added support for CSS-style color strings 

9# 2002-12-15 fl Added RGBA support 

10# 2004-03-27 fl Fixed remaining int() problems for Python 1.5.2 

11# 2004-07-19 fl Fixed gray/grey spelling issues 

12# 2009-03-05 fl Fixed rounding error in grayscale calculation 

13# 

14# Copyright (c) 2002-2004 by Secret Labs AB 

15# Copyright (c) 2002-2004 by Fredrik Lundh 

16# 

17# See the README file for information on usage and redistribution. 

18# 

19from __future__ import annotations 

20 

21import re 

22from functools import lru_cache 

23 

24from . import Image 

25 

26 

27@lru_cache 

28def getrgb(color): 

29 """ 

30 Convert a color string to an RGB or RGBA tuple. If the string cannot be 

31 parsed, this function raises a :py:exc:`ValueError` exception. 

32 

33 .. versionadded:: 1.1.4 

34 

35 :param color: A color string 

36 :return: ``(red, green, blue[, alpha])`` 

37 """ 

38 if len(color) > 100: 

39 msg = "color specifier is too long" 

40 raise ValueError(msg) 

41 color = color.lower() 

42 

43 rgb = colormap.get(color, None) 

44 if rgb: 

45 if isinstance(rgb, tuple): 

46 return rgb 

47 colormap[color] = rgb = getrgb(rgb) 

48 return rgb 

49 

50 # check for known string formats 

51 if re.match("#[a-f0-9]{3}$", color): 

52 return int(color[1] * 2, 16), int(color[2] * 2, 16), int(color[3] * 2, 16) 

53 

54 if re.match("#[a-f0-9]{4}$", color): 

55 return ( 

56 int(color[1] * 2, 16), 

57 int(color[2] * 2, 16), 

58 int(color[3] * 2, 16), 

59 int(color[4] * 2, 16), 

60 ) 

61 

62 if re.match("#[a-f0-9]{6}$", color): 

63 return int(color[1:3], 16), int(color[3:5], 16), int(color[5:7], 16) 

64 

65 if re.match("#[a-f0-9]{8}$", color): 

66 return ( 

67 int(color[1:3], 16), 

68 int(color[3:5], 16), 

69 int(color[5:7], 16), 

70 int(color[7:9], 16), 

71 ) 

72 

73 m = re.match(r"rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$", color) 

74 if m: 

75 return int(m.group(1)), int(m.group(2)), int(m.group(3)) 

76 

77 m = re.match(r"rgb\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)$", color) 

78 if m: 

79 return ( 

80 int((int(m.group(1)) * 255) / 100.0 + 0.5), 

81 int((int(m.group(2)) * 255) / 100.0 + 0.5), 

82 int((int(m.group(3)) * 255) / 100.0 + 0.5), 

83 ) 

84 

85 m = re.match( 

86 r"hsl\(\s*(\d+\.?\d*)\s*,\s*(\d+\.?\d*)%\s*,\s*(\d+\.?\d*)%\s*\)$", color 

87 ) 

88 if m: 

89 from colorsys import hls_to_rgb 

90 

91 rgb = hls_to_rgb( 

92 float(m.group(1)) / 360.0, 

93 float(m.group(3)) / 100.0, 

94 float(m.group(2)) / 100.0, 

95 ) 

96 return ( 

97 int(rgb[0] * 255 + 0.5), 

98 int(rgb[1] * 255 + 0.5), 

99 int(rgb[2] * 255 + 0.5), 

100 ) 

101 

102 m = re.match( 

103 r"hs[bv]\(\s*(\d+\.?\d*)\s*,\s*(\d+\.?\d*)%\s*,\s*(\d+\.?\d*)%\s*\)$", color 

104 ) 

105 if m: 

106 from colorsys import hsv_to_rgb 

107 

108 rgb = hsv_to_rgb( 

109 float(m.group(1)) / 360.0, 

110 float(m.group(2)) / 100.0, 

111 float(m.group(3)) / 100.0, 

112 ) 

113 return ( 

114 int(rgb[0] * 255 + 0.5), 

115 int(rgb[1] * 255 + 0.5), 

116 int(rgb[2] * 255 + 0.5), 

117 ) 

118 

119 m = re.match(r"rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$", color) 

120 if m: 

121 return int(m.group(1)), int(m.group(2)), int(m.group(3)), int(m.group(4)) 

122 msg = f"unknown color specifier: {repr(color)}" 

123 raise ValueError(msg) 

124 

125 

126@lru_cache 

127def getcolor(color, mode): 

128 """ 

129 Same as :py:func:`~PIL.ImageColor.getrgb` for most modes. However, if 

130 ``mode`` is HSV, converts the RGB value to a HSV value, or if ``mode`` is 

131 not color or a palette image, converts the RGB value to a grayscale value. 

132 If the string cannot be parsed, this function raises a :py:exc:`ValueError` 

133 exception. 

134 

135 .. versionadded:: 1.1.4 

136 

137 :param color: A color string 

138 :param mode: Convert result to this mode 

139 :return: ``(graylevel[, alpha]) or (red, green, blue[, alpha])`` 

140 """ 

141 # same as getrgb, but converts the result to the given mode 

142 color, alpha = getrgb(color), 255 

143 if len(color) == 4: 

144 color, alpha = color[:3], color[3] 

145 

146 if mode == "HSV": 

147 from colorsys import rgb_to_hsv 

148 

149 r, g, b = color 

150 h, s, v = rgb_to_hsv(r / 255, g / 255, b / 255) 

151 return int(h * 255), int(s * 255), int(v * 255) 

152 elif Image.getmodebase(mode) == "L": 

153 r, g, b = color 

154 # ITU-R Recommendation 601-2 for nonlinear RGB 

155 # scaled to 24 bits to match the convert's implementation. 

156 color = (r * 19595 + g * 38470 + b * 7471 + 0x8000) >> 16 

157 if mode[-1] == "A": 

158 return color, alpha 

159 else: 

160 if mode[-1] == "A": 

161 return color + (alpha,) 

162 return color 

163 

164 

165colormap = { 

166 # X11 colour table from https://drafts.csswg.org/css-color-4/, with 

167 # gray/grey spelling issues fixed. This is a superset of HTML 4.0 

168 # colour names used in CSS 1. 

169 "aliceblue": "#f0f8ff", 

170 "antiquewhite": "#faebd7", 

171 "aqua": "#00ffff", 

172 "aquamarine": "#7fffd4", 

173 "azure": "#f0ffff", 

174 "beige": "#f5f5dc", 

175 "bisque": "#ffe4c4", 

176 "black": "#000000", 

177 "blanchedalmond": "#ffebcd", 

178 "blue": "#0000ff", 

179 "blueviolet": "#8a2be2", 

180 "brown": "#a52a2a", 

181 "burlywood": "#deb887", 

182 "cadetblue": "#5f9ea0", 

183 "chartreuse": "#7fff00", 

184 "chocolate": "#d2691e", 

185 "coral": "#ff7f50", 

186 "cornflowerblue": "#6495ed", 

187 "cornsilk": "#fff8dc", 

188 "crimson": "#dc143c", 

189 "cyan": "#00ffff", 

190 "darkblue": "#00008b", 

191 "darkcyan": "#008b8b", 

192 "darkgoldenrod": "#b8860b", 

193 "darkgray": "#a9a9a9", 

194 "darkgrey": "#a9a9a9", 

195 "darkgreen": "#006400", 

196 "darkkhaki": "#bdb76b", 

197 "darkmagenta": "#8b008b", 

198 "darkolivegreen": "#556b2f", 

199 "darkorange": "#ff8c00", 

200 "darkorchid": "#9932cc", 

201 "darkred": "#8b0000", 

202 "darksalmon": "#e9967a", 

203 "darkseagreen": "#8fbc8f", 

204 "darkslateblue": "#483d8b", 

205 "darkslategray": "#2f4f4f", 

206 "darkslategrey": "#2f4f4f", 

207 "darkturquoise": "#00ced1", 

208 "darkviolet": "#9400d3", 

209 "deeppink": "#ff1493", 

210 "deepskyblue": "#00bfff", 

211 "dimgray": "#696969", 

212 "dimgrey": "#696969", 

213 "dodgerblue": "#1e90ff", 

214 "firebrick": "#b22222", 

215 "floralwhite": "#fffaf0", 

216 "forestgreen": "#228b22", 

217 "fuchsia": "#ff00ff", 

218 "gainsboro": "#dcdcdc", 

219 "ghostwhite": "#f8f8ff", 

220 "gold": "#ffd700", 

221 "goldenrod": "#daa520", 

222 "gray": "#808080", 

223 "grey": "#808080", 

224 "green": "#008000", 

225 "greenyellow": "#adff2f", 

226 "honeydew": "#f0fff0", 

227 "hotpink": "#ff69b4", 

228 "indianred": "#cd5c5c", 

229 "indigo": "#4b0082", 

230 "ivory": "#fffff0", 

231 "khaki": "#f0e68c", 

232 "lavender": "#e6e6fa", 

233 "lavenderblush": "#fff0f5", 

234 "lawngreen": "#7cfc00", 

235 "lemonchiffon": "#fffacd", 

236 "lightblue": "#add8e6", 

237 "lightcoral": "#f08080", 

238 "lightcyan": "#e0ffff", 

239 "lightgoldenrodyellow": "#fafad2", 

240 "lightgreen": "#90ee90", 

241 "lightgray": "#d3d3d3", 

242 "lightgrey": "#d3d3d3", 

243 "lightpink": "#ffb6c1", 

244 "lightsalmon": "#ffa07a", 

245 "lightseagreen": "#20b2aa", 

246 "lightskyblue": "#87cefa", 

247 "lightslategray": "#778899", 

248 "lightslategrey": "#778899", 

249 "lightsteelblue": "#b0c4de", 

250 "lightyellow": "#ffffe0", 

251 "lime": "#00ff00", 

252 "limegreen": "#32cd32", 

253 "linen": "#faf0e6", 

254 "magenta": "#ff00ff", 

255 "maroon": "#800000", 

256 "mediumaquamarine": "#66cdaa", 

257 "mediumblue": "#0000cd", 

258 "mediumorchid": "#ba55d3", 

259 "mediumpurple": "#9370db", 

260 "mediumseagreen": "#3cb371", 

261 "mediumslateblue": "#7b68ee", 

262 "mediumspringgreen": "#00fa9a", 

263 "mediumturquoise": "#48d1cc", 

264 "mediumvioletred": "#c71585", 

265 "midnightblue": "#191970", 

266 "mintcream": "#f5fffa", 

267 "mistyrose": "#ffe4e1", 

268 "moccasin": "#ffe4b5", 

269 "navajowhite": "#ffdead", 

270 "navy": "#000080", 

271 "oldlace": "#fdf5e6", 

272 "olive": "#808000", 

273 "olivedrab": "#6b8e23", 

274 "orange": "#ffa500", 

275 "orangered": "#ff4500", 

276 "orchid": "#da70d6", 

277 "palegoldenrod": "#eee8aa", 

278 "palegreen": "#98fb98", 

279 "paleturquoise": "#afeeee", 

280 "palevioletred": "#db7093", 

281 "papayawhip": "#ffefd5", 

282 "peachpuff": "#ffdab9", 

283 "peru": "#cd853f", 

284 "pink": "#ffc0cb", 

285 "plum": "#dda0dd", 

286 "powderblue": "#b0e0e6", 

287 "purple": "#800080", 

288 "rebeccapurple": "#663399", 

289 "red": "#ff0000", 

290 "rosybrown": "#bc8f8f", 

291 "royalblue": "#4169e1", 

292 "saddlebrown": "#8b4513", 

293 "salmon": "#fa8072", 

294 "sandybrown": "#f4a460", 

295 "seagreen": "#2e8b57", 

296 "seashell": "#fff5ee", 

297 "sienna": "#a0522d", 

298 "silver": "#c0c0c0", 

299 "skyblue": "#87ceeb", 

300 "slateblue": "#6a5acd", 

301 "slategray": "#708090", 

302 "slategrey": "#708090", 

303 "snow": "#fffafa", 

304 "springgreen": "#00ff7f", 

305 "steelblue": "#4682b4", 

306 "tan": "#d2b48c", 

307 "teal": "#008080", 

308 "thistle": "#d8bfd8", 

309 "tomato": "#ff6347", 

310 "turquoise": "#40e0d0", 

311 "violet": "#ee82ee", 

312 "wheat": "#f5deb3", 

313 "white": "#ffffff", 

314 "whitesmoke": "#f5f5f5", 

315 "yellow": "#ffff00", 

316 "yellowgreen": "#9acd32", 

317}