3. API - Color

The colorzero library includes a comprehensive Color class which is capable of converting between numerous color representations and calculating color differences. Various ancillary classes can be used to manipulate aspects of a color.

3.1. Color Class

This the primary class in the package, and often the only class you’ll need or want to interact with. It has an extremely flexible constructor, along with numerous explicit constructors, and attributes for conversion to other color systems.

class colorzero.Color(*args, **kwargs)[source]

The Color class is a tuple which represents a color as linear red, green, and blue components.

The class has a flexible constructor which allows you to create an instance from any built-in color system. There are also explicit constructors for every known system that can convert (directly or indirectly) to linear RGB. For example, an instance of Color can be constructed in any of the following ways:

>>> Color('#f00')
<Color html='#ff0000' rgb=(1, 0, 0)>
>>> Color('green')
<Color html='#008000' rgb=(0.0, 0.501961, 0.0)>
>>> Color(0, 0, 1)
<Color html='#0000ff' rgb=(0, 0, 1)>
>>> Color(h=0, s=1, v=0.5)
<Color html='#800000' rgb=(0.5, 0, 0)>
>>> Color(y=0.4, u=-0.05, v=0.615)
<Color html='#ff104c' rgb=(1, 0.0626644, 0.298394)>

The specific forms that the default constructor will accept are enumerated below:

Style

Description

Single scalar parameter

Equivalent to calling Color.from_string(), or Color.from_rgb24().

Three positional parameters or a 3-tuple with no field names

Equivalent to calling Color.from_rgb() if all three parameters are between 0.0 and 1.0, or Color.from_rgb_bytes() otherwise.

Three named parameters, or a 3-tuple with fields “r”, “g”, “b”

Three named parameters, or a 3-tuple with fields “red”, “green”, “blue”

Three named parameters, or a 3-tuple with fields “y”, “u”, “v”

Equivalent to calling Color.from_yuv() if “y” is between 0.0 and 1.0, “u” is between -0.436 and 0.436, and “v” is between -0.615 and 0.615, or Color.from_yuv_bytes() otherwise.

Three named parameters, or a 3-tuple with fields “y”, “i”, “q”

Equivalent to calling Color.from_yiq().

Three named parameters, or a 3-tuple with fields “h”, “l”, “s”

Equivalent to calling Color.from_hls().

Three named parameters, or a 3-tuple with fields “hue”, “lightness”, “saturation”

Three named parameters, or a 3-tuple with fields “h”, “s”, “v”

Equivalent to calling Color.from_hsv()

Three named parameters, or a 3-tuple with fields “hue”, “saturation”, “value”

Three named parameters, or a 3-tuple with fields “x”, “y”, “z”

Equivalent to calling Color.from_xyz()

Three named parameters, or a 3-tuple with fields “l”, “a”, “b”

Equivalent to calling Color.from_lab()

Three named parameters, or a 3-tuple with fields “l”, “u”, “v”

Equivalent to calling Color.from_luv()

If the constructor parameters do not conform to any of the variants in the table above, a ValueError will be raised.

Internally, the color is always represented as 3 float values corresponding to the red, green, and blue components of the color. These values take a value from 0.0 to 1.0 (least to full intensity). The class provides several attributes which can be used to convert one color system into another:

>>> Color('#f00').hls
HLS(h=0.0, l=0.5, s=1.0)
>>> Color.from_string('green').hue
Hue(deg=120.0)
>>> Color.from_rgb_bytes(0, 0, 255).yuv
YUV(y=0.114, u=0.436, v=-0.10001426533523537)

As Color derives from tuple, instances are immutable. While this provides the advantage that they can be used in a set or as keys of a dict, it does mean that colors themselves cannot be directly manipulated (e.g. by setting the red component).

However, several auxilliary classes in the module provide the ability to perform simple transformations of colors via operators which produce a new Color instance. For example, you can add, subtract, and multiply colors directly:

>>> Color('red') + Color('blue')
<Color html='#ff00ff' rgb=(1, 0, 1)>
>>> Color('magenta') - Color('red')
<Color html='#0000ff' rgb=(0, 0, 1)>

Values are clipped to ensure the resulting color is still valid:

>>> Color('#ff00ff') + Color('#ff0000')
<Color html='#ff00ff' rgb=(1, 0, 1)>

You can wrap numbers in constructors like Red (or obtain elements of existing colors), then add, subtract, or multiply them with a Color:

>>> Color('red') - Red(0.5)
<Color html='#800000' rgb=(0.5, 0, 0)>
>>> Color('green') + Color('grey').red
<Color html='#808000' rgb=(0.501961, 0.501961, 0)>

You can even manipulate non-primary attributes like hue, saturation, and lightness with standard addition, subtraction or multiplication operators:

>>> Color.from_hls(0.5, 0.5, 1.0)
<Color html='#00ffff' rgb=(0, 1, 1)>
>>> Color.from_hls(0.5, 0.5, 1.0) * Lightness(0.8)
<Color html='#00cccc' rgb=(0, 0.8, 0.8)>
>>> (Color.from_hls(0.5, 0.5, 1.0) * Lightness(0.8)).hls
HLS(h=0.5, l=0.4, s=1.0)

In the last example above, a Color instance is constructed from HLS (hue, lightness, saturation) values with a lightness of 0.5. This is multiplied by a Lightness a value of 0.8 which constructs a new Color with the same hue and saturation, but a lightness of 0.4 (0.8 × 0.5).

If an instance is converted to a string (with str()) it will return a string containing the 7-character HTML code for the color (e.g. “#ff0000” for red). As can be seen in the examples above, a similar representation is included for the output of repr(). The output of repr() can be customized by assigning values to Color.repr_style.

red

Return the red value as a Red instance

green

Return the green value as a Green instance

blue

Return the blue value as a Blue instance

repr_style

Specifies the style of output returned when using repr() against a Color instance. This is an attribute of the class, not of instances. For example:

>>> Color('#f00')
<Color html='#ff0000' rgb=(1, 0, 0)>
>>> Color.repr_style = 'html'
>>> Color('#f00')
Color('#ff0000')

The following values are valid:

  • ‘default’ - The style shown above

  • ‘term16m’ - Similar to the default style, but instead of the HTML style being included, a swatch previewing the color is output. Note that the terminal must support 24-bit color ANSI codes for this to work.

  • ‘term256’ - Similar to ‘term16m’, but uses the closest color that can be found in the standard 256-color xterm palette. Note that the terminal must support 8-bit color ANSI codes for this to work.

  • ‘html’ - Outputs a valid Color constructor using the HTML style, e.g. Color('#ff99bb')

  • ‘rgb’ - Outputs a valid Color constructor using the floating point RGB values, e.g. Color(1, 0.25, 0)

difference(other, method='euclid')[source]

Determines the difference between this color and other using the specified method.

Parameters
  • other (Color) – The color to compare this color to.

  • method (str) –

    The algorithm to use in the comparison. Valid values are:

    • ’euclid’ - This is the default method. Calculate the Euclidian distance. This is by far the fastest method, but also the least accurate in terms of human perception.

    • ’cie1976’ - Use the CIE 1976 formula for calculating the difference between two colors in CIE Lab space.

    • ’cie1994g’ - Use the CIE 1994 formula with the “graphic arts” bias for calculating the difference.

    • ’cie1994t’ - Use the CIE 1994 forumula with the “textiles” bias for calculating the difference.

    • ’ciede2000’ - Use the CIEDE 2000 formula for calculating the difference.

Returns

A float indicating how different the two colors are. Note that the Euclidian distance will be significantly different to the other calculations; effectively this just measures the distance between the two colors by treating them as coordinates in a three dimensional Euclidian space. All other methods are means of calculating a Delta E value in which 2.3 is considered a just-noticeable difference (JND).

For example:

>>> Color('red').difference(Color('red'))
0.0
>>> Color('red').difference(Color('red'), method='cie1976')
0.0
>>> Color('red').difference(Color('#900'))
0.4
>>> Color('red').difference(Color('#900'), method='cie1976')
40.17063087142142
>>> Color('red').difference(Color('#900'), method='ciede2000')
21.078146289272155
>>> Color('red').difference(Color('blue'))
1.4142135623730951
>>> Color('red').difference(Color('blue'), method='cie1976')
176.31403908880046

Note

Instead of using this method, you may wish to simply use the various difference functions (euclid(), cie1976(), etc.) directly.

classmethod from_cmy(c, m, y)[source]

Construct a Color from CMY (cyan, magenta, yellow) floats between 0.0 and 1.0.

Note

This conversion uses the basic subtractive method which is not accurate for color reproduction on print devices. See the Color FAQ for more information.

classmethod from_cmyk(c, m, y, k)[source]

Construct a Color from CMYK (cyan, magenta, yellow, black) floats between 0.0 and 1.0.

Note

This conversion uses the basic subtractive method which is not accurate for color reproduction on print devices. See the Color FAQ for more information.

classmethod from_hls(h, l, s)[source]

Construct a Color from HLS (hue, lightness, saturation) floats between 0.0 and 1.0.

classmethod from_hsv(h, s, v)[source]

Construct a Color from HSV (hue, saturation, value) floats between 0.0 and 1.0.

classmethod from_lab(l, a, b)[source]

Construct a Color from (L*, a*, b*) float values representing a color in the CIE Lab color space. The conversion assumes the sRGB working space with reference white D65.

classmethod from_luv(l, u, v)[source]

Construct a Color from (L*, u*, v*) float values representing a color in the CIE Luv color space. The conversion assumes the sRGB working space with reference white D65.

classmethod from_rgb(r, g, b)[source]

Construct a Color from three linear RGB float values between 0.0 and 1.0.

classmethod from_rgb24(n)[source]

Construct a Color from an unsigned 24-bit integer number of the form 0x00BBGGRR.

classmethod from_rgb565(n)[source]

Construct a Color from an unsigned 16-bit integer number in RGB565 format.

classmethod from_rgb_bytes(r, g, b)[source]

Construct a Color from three RGB byte values between 0 and 255.

classmethod from_string(s)[source]

Construct a Color from a 4 or 7 character CSS-like representation (e.g. “#f00” or “#ff0000” for red), or from one of the named colors (e.g. “green” or “wheat”) from the CSS standard. Any other string format will result in a ValueError.

classmethod from_xyz(x, y, z)[source]

Construct a Color from (X, Y, Z) float values representing a color in the CIE 1931 color space. The conversion assumes the sRGB working space with reference white D65.

classmethod from_yiq(y, i, q)[source]

Construct a Color from three Y’IQ float values. Y’ can be between 0.0 and 1.0, while I and Q can be between -1.0 and 1.0.

classmethod from_yuv(y, u, v)[source]

Construct a Color from three Y’UV float values. The Y value may be between 0.0 and 1.0. U may be between -0.436 and 0.436, while V may be between -0.615 and 0.615.

classmethod from_yuv_bytes(y, u, v)[source]

Construct a Color from three Y’UV byte values between 0 and 255. The U and V values are biased by 128 to prevent negative values as is typical in video applications. The Y value is biased by 16 for the same purpose.

gradient(other, steps=10, easing=<function linear>)[source]

Returns a generator which fades between this color and other in the specified number of steps.

Parameters
  • other (Color) – The color that will end the gradient (with the color the method is called upon starting the gradient)

  • steps (int) – The unqiue number of colors to include in the generated gradient. Defaults to 10 if unspecified.

  • easing (callable) – A function which controls the speed of the progression. If specified, if must be a function which takes a single parameter, the number of steps, and yields a sequence of values between 0.0 (representing the start of the gradient) and 1.0 (representing the end). The default is linear().

Returns

A generator yielding steps Color instances which fade from this color to other.

For example:

>>> Color.repr_style = 'html'
>>> print('\n'.join(
... repr(c) for c in
... Color('red').gradient(Color('green'))
... ))
Color('#ff0000')
Color('#e30e00')
Color('#c61c00')
Color('#aa2b00')
Color('#8e3900')
Color('#714700')
Color('#555500')
Color('#396400')
Color('#1c7200')
Color('#008000')

New in version 1.1.

property cmy

Returns a 3-tuple of (cyan, magenta, yellow) float values (between 0.0 and 1.0).

Note

This conversion uses the basic subtractive method which is not accurate for color reproduction on print devices. See the Color FAQ for more information.

property cmyk

Returns a 4-tuple of (cyan, magenta, yellow, black) float values (between 0.0 and 1.0).

Note

This conversion uses the basic subtractive method which is not accurate for color reproduction on print devices. See the Color FAQ for more information.

property hls

Returns a 3-tuple of (hue, lightness, saturation) float values (between 0.0 and 1.0).

property hsv

Returns a 3-tuple of (hue, saturation, value) float values (between 0.0 and 1.0).

property html

Returns the color as a string in HTML #RRGGBB format.

property hue

Returns the hue of the color as a Hue instance which can be used in operations with other Color instances.

property lab

Returns a 3-tuple of (L*, a*, b*) float values representing the color in the CIE Lab color space with the D65 standard illuminant.

property lightness

Returns the lightness of the color as a Lightness instance which can be used in operations with other Color instances.

property luma

Returns the luma of the color as a Luma instance which can be used in operations with other Color instances.

property luv

Returns a 3-tuple of (L*, u*, v*) float values representing the color in the CIE Luv color space with the D65 standard illuminant.

property rgb

Return a simple 3-tuple of (r, g, b) float values in the range 0.0 <= n <= 1.0.

Note

The Color class can already be treated as such a 3-tuple but for the cases where you want a straight namedtuple() this property is available.

property rgb565

Returns an unsigned 16-bit integer number representing the color in the RGB565 encoding.

property rgb_bytes

Returns a 3-tuple of (red, green, blue) byte values.

property saturation

Returns the saturation of the color as a Saturation instance which can be used in operations with other Color instances.

property xyz

Returns a 3-tuple of (X, Y, Z) float values representing the color in the CIE 1931 color space. The conversion assumes the sRGB working space, with reference white D65.

property yiq

Returns a 3-tuple of (y, i, q) float values; y values can be between 0.0 and 1.0, whilst i and q values can be between -1.0 and 1.0.

property yuv

Returns a 3-tuple of (y, u, v) float values; Y values can be between 0.0 and 1.0, U values are between -0.436 and 0.436, and V values are between -0.615 and 0.615.

property yuv_bytes

Returns a 3-tuple of (y, u, v) byte values. Y values are biased by 16 in the result to prevent negatives. U and V values are biased by 128 for the same purpose.

3.2. Format Strings

Instances of Color can be used in format strings to output various representations of a color, including HTML sequences and ANSI escape sequences to color terminal output. Format specifications can be used to modify the output to support different terminal types. For example:

>>> red = Color('red')
>>> green = Color('green')
>>> blue = Color('#47b')
>>> print(f"{red:html}")
#ff0000
>>> print(repr(f"{red}Red{red:0} Alert!"))
'\\x1b[1;31mRed\\x1b[0m Alert!'
>>> print(repr(f"The grass is {green:16m}greener{green:0}."))
'The grass is \\x1b[38;2;0;128;0mgreener\\x1b[0m.'
>>> print(repr(f"{blue:b16m}Blue skies{blue:0}"))
'\\x1b[48;2;68;119;187mBlue skies\\x1b[0m'

The format specification is one of:

  • “html” - the color will be output as the common 7-character HTML represention of #RRGGBB where RR, GG, and BB are the red, green and blue components expressed as a single hexidecimal byte

  • “css” or “cssrgb” - the color will be output in CSS’ functional notation rgb(r, g, b) where r, g, and b are decimal representations of the red, green, and blue components in the range 0 to 255

  • “csshsl” - the color will be output in CSS’ function notation hue(hdeg, s%, l%) where h, s, and l are the hue (expressed in degrees), saturation, and lightness (expressed as percentages)

  • One of the ANSI format specifications which consist of an optional foreground / background specifier (the letters “f” or “b”) followed by an optional terminal type identifer, which is one of:

    • “8” - the default, indicating only the original 8 DOS colors (black, red, green, yellow, blue, magenta, cyan, and white) are supported. Technically, 16 foreground colors are supported via use of the “bold” style for “intense” colors, if the terminal supports this.

    • “256” - indicates the terminal supports 256 colors via 8-bit color ANSI codes

    • “16m” - indicating the terminal supports ~16 million colors via 24-bit color ANSI codes

“0” can also be specified to indicate that the style should be reset, but this is deprecated. If specified with the optional foreground / background specifier, “0” resets only the foreground / background color. If specified alone it resets all styles. More formally:

<term_fore_back> ::= "" | "f" | "b"
<term_type>      ::= "" | "0" | "8" | "256" | "16m"
<term>           ::= <term_fore_back> <term_type>
<html>           ::= "html"
<css>            ::= "css" ("rgb" | "hsl")?
<format_spec>    ::= <html> | <css> | <term>

New in version 1.1: The ability to output ANSI codes via format strings, and the customization of repr() output.

New in version 1.2: The ability to output HTML and CSS representations via format strings

Deprecated since version 2.1: Use of “0” as a reset indicator; use the new Default singleton instead

3.3. Default Singleton

The Default singleton exists as a color which represents the “default” for whatever environment it’s rendered in. For example, when using in a format string for CSS, it renders as “inherit” (which is the CSS keyword indicating that a block should inherit its color from its enclosing parent, which is the default). Alternatively, when used with the terminal format strings (“8”, “256”, “16m”) it outputs the ANSI sequence to reset colors to the terminal’s default (whatever that may be).

colorzero.Default = <Color Default>

The Default singleton is a special value representing the default color for whatever context it is used within. Typically this is only useful in combination with a Style.

3.4. Manipulation Classes

These manipulation classes are used in conjunction with the standard arithmetic addition, subtraction, and multiplication operators to calculate new Color instances.

class colorzero.Red(x=0, /)[source]

Represents the red component of a Color for use in transformations. Instances of this class can be constructed directly with a float value, or by querying the Color.red attribute. Addition, subtraction, and multiplication are supported with Color instances. For example:

>>> Color.from_rgb(0, 0, 0) + Red(0.5)
<Color html='#800000' rgb=(0.5, 0, 0)>
>>> Color('#f00') - Color('#900').red
<Color html='#660000' rgb=(0.4, 0, 0)>
>>> (Red(0.1) * Color('red')).red
Red(0.1)
class colorzero.Green(x=0, /)[source]

Represents the green component of a Color for use in transformations. Instances of this class can be constructed directly with a float value, or by querying the Color.green attribute. Addition, subtraction, and multiplication are supported with Color instances. For example:

>>> Color(0, 0, 0) + Green(0.1)
<Color html='#001a00' rgb=(0, 0.1, 0)>
>>> Color.from_yuv(1, -0.4, -0.6) - Green(1)
<Color html='#510030' rgb=(0.316098, 0, 0.187156)>
>>> (Green(0.5) * Color('white')).rgb
RGB(r=1.0, g=0.5, b=1.0)
class colorzero.Blue(x=0, /)[source]

Represents the blue component of a Color for use in transformations. Instances of this class can be constructed directly with a float value, or by querying the Color.blue attribute. Addition, subtraction, and multiplication are supported with Color instances. For example:

>>> Color(0, 0, 0) + Blue(0.2)
<Color html='#000033' rgb=(0, 0, 0.2)>
>>> Color.from_hls(0.5, 0.5, 1.0) - Blue(1)
<Color html='#00ff00' rgb=(0, 1, 0)>
>>> Blue(0.9) * Color('white')
<Color html='#ffffe6' rgb=(1, 1, 0.9)>
class colorzero.Hue(n=None, deg=None, rad=None)[source]

Represents the hue of a Color for use in transformations. Instances of this class can be constructed directly with a float value in the range [0.0, 1.0) representing an angle around the HSL hue wheel. As this is a circular mapping, 0.0 and 1.0 effectively mean the same thing, i.e. out of range values will be normalized into the range [0.0, 1.0).

The class can also be constructed with the keyword arguments deg or rad if you wish to specify the hue value in degrees or radians instead, respectively. Instances can also be constructed by querying the Color.hue attribute.

Addition, subtraction, and multiplication are supported with Color instances. For example:

>>> Color(1, 0, 0).hls
HLS(h=0.0, l=0.5, s=1.0)
>>> (Color(1, 0, 0) + Hue(deg=180)).hls
HLS(h=0.5, l=0.5, s=1.0)

Note that whilst multiplication by a Hue doesn’t make much sense, it is still supported. However, the circular nature of a hue value can lead to suprising effects. In particular, since 1.0 is equivalent to 0.0 the following may be observed:

>>> (Hue(1.0) * Color.from_hls(0.5, 0.5, 1.0)).hls
HLS(h=0.0, l=0.5, s=1.0)
property deg

Returns the hue as a value in degrees with the range 0.0 <= n < 360.0.

property rad

Returns the hue as a value in radians with the range 0.0 <= n < 2π.

class colorzero.Saturation(x=0, /)[source]

Represents the saturation of a Color for use in transformations. Instances of this class can be constructed directly with a float value, or by querying the Color.saturation attribute. Addition, subtraction, and multiplication are supported with Color instances. For example:

>>> Color(0.9, 0.9, 0.6) + Saturation(0.1)
<Color html='#ecec93' rgb=(0.925, 0.925, 0.575)>
>>> Color('red') - Saturation(1)
<Color html='#808080' rgb=(0.5, 0.5, 0.5)>
>>> Saturation(0.5) * Color('wheat')
<Color html='#e4d9c3' rgb=(0.896078, 0.85098, 0.766667)>
class colorzero.Lightness(x=0, /)[source]

Represents the lightness of a Color for use in transformations. Instances of this class can be constructed directly with a float value, or by querying the Color.lightness attribute. Addition, subtraction, and multiplication are supported with Color instances. For example:

>>> Color(0, 0, 0) + Lightness(0.1)
<Color html='#1a1a1a' rgb=(0.1, 0.1, 0.1)>
>>> Color.from_rgb_bytes(0x80, 0x80, 0) - Lightness(0.2)
<Color html='#1a1a00' rgb=(0.101961, 0.101961, 0)>
>>> Lightness(0.9) * Color('wheat')
<Color html='#f0ce8e' rgb=(0.94145, 0.806785, 0.555021)>
class colorzero.Luma(x=0, /)[source]

Represents the luma of a Color for use in transformations. Instances of this class can be constructed directly with a float value, or by querying the Color.yuv.y attribute. Addition, subtraction, and multiplication are supported with Color instances. For example:

>>> Color(0, 0, 0) + Luma(0.1)
<Color html='#1a1a1a' rgb=(0.1, 0.1, 0.1)>
>>> Color('red') * Luma(0.5)
<Color html='#d90000' rgb=(0.8505, 0, 0)>

3.5. Difference Functions

colorzero.euclid(color1, color2)[source]

Calculates color difference as a simple Euclidean distance by treating the three components as spatial dimensions.

Note

This function will return considerably different values to the other difference functions. In particular, the maximum “difference” will be \sqrt{3} which is much smaller than the output of the CIE functions.

colorzero.cie1976(color1, color2)[source]

Calculates color difference according to the CIE 1976 formula. Effectively this is the Euclidean formula, but with CIE L*a*b* components instead of RGB.

colorzero.cie1994g(color1, color2)[source]

Calculates color difference according to the CIE 1994 formula with the “textile” bias. See cie1994() for further information.

colorzero.cie1994t(color1, color2)[source]

Calculates color difference according to the CIE 1994 formula with the “graphics” bias. See cie1994() for further information.

colorzero.ciede2000(color1, color2)[source]

Calculates color difference according to the CIEDE 2000 formula. This is the most accurate algorithm currently implemented but also the most complex and slowest. Like CIE1994 it is largely based in CIE L*C*h* space, but with several modifications to account for perceptual uniformity flaws.

3.6. Easing Functions

These functions can be used with the Color.gradient() method to control the progression of the fade between the two colors.

colorzero.linear(steps)[source]

Linear easing function; yields steps values between 0.0 and 1.0

colorzero.ease_in(steps)[source]

Quadratic ease-in function; yields steps values between 0.0 and 1.0

colorzero.ease_out(steps)[source]

Quadratic ease-out function; yields steps values between 0.0 and 1.0

colorzero.ease_in_out(steps)[source]

Quadratic ease-in-out function; yields steps values between 0.0 and 1.0