Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/webcolors/_conversion.py: 42%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""
2Functions which convert between various types of color values.
4"""
6# SPDX-License-Identifier: BSD-3-Clause
8from ._definitions import CSS3, _get_hex_to_name_map, _get_name_to_hex_map
9from ._normalization import (
10 _percent_to_integer,
11 normalize_hex,
12 normalize_integer_triplet,
13 normalize_percent_triplet,
14)
15from ._types import IntegerRGB, IntTuple, PercentRGB, PercentTuple
17# Conversions from color names to other formats.
18# --------------------------------------------------------------------------------
21def name_to_hex(name: str, spec: str = CSS3) -> str:
22 """
23 Convert a color name to a normalized hexadecimal color value.
25 The color name will be normalized to lower-case before being looked up.
27 Examples:
29 .. doctest::
31 >>> name_to_hex("white")
32 '#ffffff'
33 >>> name_to_hex("navy")
34 '#000080'
35 >>> name_to_hex("goldenrod")
36 '#daa520'
37 >>> name_to_hex("goldenrod", spec=HTML4)
38 Traceback (most recent call last):
39 ...
40 ValueError: "goldenrod" is not defined as a named color in html4.
42 :param name: The color name to convert.
43 :param spec: The specification from which to draw the list of color names. Default
44 is :data:`CSS3`.
45 :raises ValueError: when the given name has no definition in the given spec.
47 """
48 color_map = _get_name_to_hex_map(spec)
49 if hex_value := color_map.get(name.lower()):
50 return hex_value
51 raise ValueError(f'"{name}" is not defined as a named color in {spec}')
54def name_to_rgb(name: str, spec: str = CSS3) -> IntegerRGB:
55 """
56 Convert a color name to a 3-:class:`tuple` of :class:`int` suitable for use in
57 an ``rgb()`` triplet specifying that color.
59 The color name will be normalized to lower-case before being looked up.
61 Examples:
63 .. doctest::
65 >>> name_to_rgb("white")
66 IntegerRGB(red=255, green=255, blue=255)
67 >>> name_to_rgb("navy")
68 IntegerRGB(red=0, green=0, blue=128)
69 >>> name_to_rgb("goldenrod")
70 IntegerRGB(red=218, green=165, blue=32)
72 :param name: The color name to convert.
73 :param spec: The specification from which to draw the list of color names. Default
74 is :data:`CSS3.`
75 :raises ValueError: when the given name has no definition in the given spec.
77 """
78 return hex_to_rgb(name_to_hex(name, spec=spec))
81def name_to_rgb_percent(name: str, spec: str = CSS3) -> PercentRGB:
82 """
83 Convert a color name to a 3-:class:`tuple` of percentages suitable for use in an
84 ``rgb()`` triplet specifying that color.
86 The color name will be normalized to lower-case before being looked up.
88 Examples:
90 .. doctest::
92 >>> name_to_rgb_percent("white")
93 PercentRGB(red='100%', green='100%', blue='100%')
94 >>> name_to_rgb_percent("navy")
95 PercentRGB(red='0%', green='0%', blue='50%')
96 >>> name_to_rgb_percent("goldenrod")
97 PercentRGB(red='85.49%', green='64.71%', blue='12.5%')
99 :param name: The color name to convert.
100 :param spec: The specification from which to draw the list of color names. Default
101 is :data:`CSS3`.
102 :raises ValueError: when the given name has no definition in the given spec.
104 """
105 return rgb_to_rgb_percent(name_to_rgb(name, spec=spec))
108# Conversions from hexadecimal color values to other formats.
109# --------------------------------------------------------------------------------
112def hex_to_name(hex_value: str, spec: str = CSS3) -> str:
113 """
114 Convert a hexadecimal color value to its corresponding normalized color name, if
115 any such name exists.
117 The hexadecimal value will be normalized before being looked up.
119 .. note:: **Spelling variants**
121 Some values representing named gray colors can map to either of two names in
122 CSS3, because it supports both ``"gray"`` and ``"grey"`` spelling variants for
123 those colors. This function will always return the variant spelled ``"gray"``
124 (such as ``"lightgray"`` instead of ``"lightgrey"``). See :ref:`the documentation
125 on name conventions <color-name-conventions>` for details.
127 Examples:
129 .. doctest::
131 >>> hex_to_name("#ffffff")
132 'white'
133 >>> hex_to_name("#fff")
134 'white'
135 >>> hex_to_name("#000080")
136 'navy'
137 >>> hex_to_name("#daa520")
138 'goldenrod'
139 >>> hex_to_name("#daa520", spec=HTML4)
140 Traceback (most recent call last):
141 ...
142 ValueError: "#daa520" has no defined color name in html4.
144 :param hex_value: The hexadecimal color value to convert.
145 :param spec: The specification from which to draw the list of color names. Default
146 is :data:`CSS3`.
147 :raises ValueError: when the given color has no name in the given spec, or when the
148 supplied hex value is invalid.
150 """
151 color_map = _get_hex_to_name_map(spec)
152 if name := color_map.get(normalize_hex(hex_value)):
153 return name
154 raise ValueError(f'"{hex_value}" has no defined color name in {spec}.')
157def hex_to_rgb(hex_value: str) -> IntegerRGB:
158 """
159 Convert a hexadecimal color value to a 3-:class:`tuple` of :class:`int` suitable
160 for use in an ``rgb()`` triplet specifying that color.
162 The hexadecimal value will be normalized before being converted.
164 Examples:
166 .. doctest::
168 >>> hex_to_rgb("#fff")
169 IntegerRGB(red=255, green=255, blue=255)
170 >>> hex_to_rgb("#000080")
171 IntegerRGB(red=0, green=0, blue=128)
173 :param hex_value: The hexadecimal color value to convert.
174 :raises ValueError: when the supplied hex value is invalid.
176 """
177 int_value = int(normalize_hex(hex_value)[1:], 16)
178 return IntegerRGB(int_value >> 16, int_value >> 8 & 0xFF, int_value & 0xFF)
181def hex_to_rgb_percent(hex_value: str) -> PercentRGB:
182 """
183 Convert a hexadecimal color value to a 3-:class:`tuple` of percentages suitable
184 for use in an ``rgb()`` triplet representing that color.
186 The hexadecimal value will be normalized before being converted.
188 Examples:
190 .. doctest::
192 >>> hex_to_rgb_percent("#ffffff")
193 PercentRGB(red='100%', green='100%', blue='100%')
194 >>> hex_to_rgb_percent("#000080")
195 PercentRGB(red='0%', green='0%', blue='50%')
197 :param hex_value: The hexadecimal color value to convert.
198 :raises ValueError: when the supplied hex value is invalid.
200 """
201 return rgb_to_rgb_percent(hex_to_rgb(hex_value))
204# Conversions from integer rgb() triplets to other formats.
205# --------------------------------------------------------------------------------
208def rgb_to_name(rgb_triplet: IntTuple, spec: str = CSS3) -> str:
209 """
210 Convert a 3-:class:`tuple` of :class:`int`, suitable for use in an ``rgb()``
211 color triplet, to its corresponding normalized color name, if any such name exists.
213 To determine the name, the triplet will be converted to a normalized hexadecimal
214 value.
216 .. note:: **Spelling variants**
218 Some values representing named gray colors can map to either of two names in
219 CSS3, because it supports both ``"gray"`` and ``"grey"`` spelling variants for
220 those colors. This function will always return the variant spelled ``"gray"``
221 (such as ``"lightgray"`` instead of ``"lightgrey"``). See :ref:`the documentation
222 on name conventions <color-name-conventions>` for details.
224 Examples:
226 .. doctest::
228 >>> rgb_to_name((255, 255, 255))
229 'white'
230 >>> rgb_to_name((0, 0, 128))
231 'navy'
233 :param rgb_triplet: The ``rgb()`` triplet.
234 :param spec: The specification from which to draw the list of color names. Default
235 is :data:`CSS3`.
236 :raises ValueError: when the given color has no name in the given spec.
238 """
239 return hex_to_name(rgb_to_hex(normalize_integer_triplet(rgb_triplet)), spec=spec)
242def rgb_to_hex(rgb_triplet: IntTuple) -> str:
243 """
244 Convert a 3-:class:`tuple` of :class:`int`, suitable for use in an ``rgb()``
245 color triplet, to a normalized hexadecimal value for that color.
247 Examples:
249 .. doctest::
251 >>> rgb_to_hex((255, 255, 255))
252 '#ffffff'
253 >>> rgb_to_hex((0, 0, 128))
254 '#000080'
256 :param rgb_triplet: The ``rgb()`` triplet.
258 """
259 red, green, blue = normalize_integer_triplet(rgb_triplet)
260 return f"#{red:02x}{green:02x}{blue:02x}"
263def rgb_to_rgb_percent(rgb_triplet: IntTuple) -> PercentRGB:
264 """
265 Convert a 3-:class:`tuple` of :class:`int`, suitable for use in an ``rgb()``
266 color triplet, to a 3-:class:`tuple` of percentages suitable for use in representing
267 that color.
269 .. note:: **Floating-point precision**
271 This function makes some trade-offs in terms of the accuracy of the final
272 representation. For some common integer values, special-case logic is used to
273 ensure a precise result (e.g., integer 128 will always convert to ``"50%"``,
274 integer 32 will always convert to ``"12.5%"``), but for all other values a
275 standard Python :class:`float` is used and rounded to two decimal places, which
276 may result in a loss of precision for some values due to the inherent imprecision
277 of `IEEE floating-point numbers <https://en.wikipedia.org/wiki/IEEE_754>`_.
279 Examples:
281 .. doctest::
283 >>> rgb_to_rgb_percent((255, 255, 255))
284 PercentRGB(red='100%', green='100%', blue='100%')
285 >>> rgb_to_rgb_percent((0, 0, 128))
286 PercentRGB(red='0%', green='0%', blue='50%')
287 >>> rgb_to_rgb_percent((218, 165, 32))
288 PercentRGB(red='85.49%', green='64.71%', blue='12.5%')
290 :param rgb_triplet: The ``rgb()`` triplet.
292 """
293 # In order to maintain precision for common values,
294 # special-case them.
295 specials = {
296 255: "100%",
297 128: "50%",
298 64: "25%",
299 32: "12.5%",
300 16: "6.25%",
301 0: "0%",
302 }
303 return PercentRGB._make(
304 specials.get(d, f"{d / 255.0 * 100:.02f}%")
305 for d in normalize_integer_triplet(rgb_triplet)
306 )
309# Conversions from percentage rgb() triplets to other formats.
310# --------------------------------------------------------------------------------
313def rgb_percent_to_name(rgb_percent_triplet: PercentTuple, spec: str = CSS3) -> str:
314 """
315 Convert a 3-:class:`tuple` of percentages, suitable for use in an ``rgb()``
316 color triplet, to its corresponding normalized color name, if any such name exists.
318 To determine the name, the triplet will be converted to a normalized hexadecimal
319 value.
321 .. note:: **Spelling variants**
323 Some values representing named gray colors can map to either of two names in
324 CSS3, because it supports both ``"gray"`` and ``"grey"`` spelling variants for
325 those colors. This function will always return the variant spelled ``"gray"``
326 (such as ``"lightgray"`` instead of ``"lightgrey"``). See :ref:`the documentation
327 on name conventions <color-name-conventions>` for details.
329 Examples:
331 .. doctest::
333 >>> rgb_percent_to_name(("100%", "100%", "100%"))
334 'white'
335 >>> rgb_percent_to_name(("0%", "0%", "50%"))
336 'navy'
337 >>> rgb_percent_to_name(("85.49%", "64.71%", "12.5%"))
338 'goldenrod'
340 :param rgb_percent_triplet: The ``rgb()`` triplet.
341 :param spec: The specification from which to draw the list of color names. Default
342 is :data:`CSS3`.
343 :raises ValueError: when the given color has no name in the given spec.
345 """
346 return rgb_to_name(
347 rgb_percent_to_rgb(normalize_percent_triplet(rgb_percent_triplet)),
348 spec=spec,
349 )
352def rgb_percent_to_hex(rgb_percent_triplet: PercentTuple) -> str:
353 """
354 Convert a 3-:class:`tuple` of percentages, suitable for use in an ``rgb()``
355 color triplet, to a normalized hexadecimal color value for that color.
357 Examples:
359 .. doctest::
361 >>> rgb_percent_to_hex(("100%", "100%", "0%"))
362 '#ffff00'
363 >>> rgb_percent_to_hex(("0%", "0%", "50%"))
364 '#000080'
365 >>> rgb_percent_to_hex(("85.49%", "64.71%", "12.5%"))
366 '#daa520'
368 :param rgb_percent_triplet: The ``rgb()`` triplet.
370 """
371 return rgb_to_hex(
372 rgb_percent_to_rgb(normalize_percent_triplet(rgb_percent_triplet))
373 )
376def rgb_percent_to_rgb(rgb_percent_triplet: PercentTuple) -> IntegerRGB:
377 """
378 Convert a 3-:class:`tuple` of percentages, suitable for use in an ``rgb()``
379 color triplet, to a 3-:class:`tuple` of :class:`int` suitable for use in
380 representing that color.
382 Some precision may be lost in this conversion. See the note regarding precision for
383 :func:`~webcolors.rgb_to_rgb_percent` for details.
385 Examples:
387 .. doctest::
389 >>> rgb_percent_to_rgb(("100%", "100%", "100%"))
390 IntegerRGB(red=255, green=255, blue=255)
391 >>> rgb_percent_to_rgb(("0%", "0%", "50%"))
392 IntegerRGB(red=0, green=0, blue=128)
393 >>> rgb_percent_to_rgb(("85.49%", "64.71%", "12.5%"))
394 IntegerRGB(red=218, green=165, blue=32)
396 :param rgb_percent_triplet: The ``rgb()`` triplet.
398 """
399 return IntegerRGB._make(
400 map(
401 _percent_to_integer, # pylint: disable=protected-access
402 normalize_percent_triplet(rgb_percent_triplet),
403 )
404 )