Color Spaces: Classes and Utilities

Overview

At the core of the colorspace package are various utilities for computing with color spaces [CS6], as the name conveys. Thus, the package helps to map various three-dimensional representations of color to each other [CS2]. A particularly important mapping is the one from the perceptually-based and device-independent color model HCL (Hue-Chroma-Luminance) to standard Red-Green-Blue (sRGB) which is the basis for color specifications in many systems based on the corresponding hex codes [CS7], e.g., in HTML but also in Python. For completeness further standard color models are included as well in the package. Their connections are illustrated in the following graph:

Color spaces and their connection.

Color models that are (or try to be) perceptually-based are displayed with circles and models that are not are displayed with rectangles. The corresponding classes in colorspace are:

  • RGB for the classic Red-Green-Blue color model, which mixes three primary colors with different intensities to obtain a spectrum of colors. The advantage of this color model is (or was) that it corresponded to how computer and TV screens generated colors, hence it was widely adopted and still is the basis for color specifications in many systems. For example, hex color codes are employed in HTML but also in Python. However, the RGB model also has some important drawbacks: It does not take into account the output device properties, it is not perceptually uniform (a unit step within RGB does not produce a constant perceptual change in color), and it is unintuitive for humans to specify colors (say brown or pink) in this space. [CS6]

  • sRGB addresses the issue of device dependency by adopting a so-called gamma correction. Therefore, the gamma-corrected standard RGB (sRGB), as opposed to the linearized RGB above, is a good model for specifying colors in software and for hardware. But it is still unintuitive for humans to work directly with this color space. Therefore, sRGB is a good place to end up in a color space manipulation but it is not a good place to start. [CS11]

  • HSV is a simple transformation of the (s)RGB space that tries to capture the perceptual axes: hue (dominant wavelength, the type of color), saturation (colorfulness), and value (brightness, i.e., light vs. dark). Unfortunately, the three axes in the HSV model are confounded so that, e.g., brightness changes dramatically with hue. [CS7]

  • HSL (Hue-Lightness-Saturation) is another transformation of (s)RGB that tries to capture the perceptual axes. It does a somewhat better job but the dimensions are still strongly confounded. [CS10]

  • CIEXYZ was established by the CIE (Commission Internationale de l’Eclairage) based on experiments with human subjects. It provides a unique triplet of XYZ values, coding the standard observer’s perception of the color. It is device-independent but it is not perceptually uniform and the XYZ coordinates have no intuitive meaning. [CS8]

  • CIELUV and CIELAB were therefore proposed by the CIE as perceptually uniform color spaces where the former is typically preferred for emissive technologies (such as screens and monitors) whereas the latter is usually preferred when working with dyes and pigments. The L coordinate in both spaces has the same meaning and captures luminance (light-dark contrasts). Both the U and V coordinates as well as the A and B coordinates measure positions on red/green and yellow/blue axes, respectively, albeit in somewhat different ways. While this corresponds to how human color vision likely evolved (see the next section), these two color models still not correspond to perceptual axes that humans use to describe colors. [CS10, 13]

  • polarLUV (= HCL) and polarLAB therefore take polar coordinates in the UV plane and AB plane, respectively. Specifically, the polar coordinates of the LUV model are known as the HCL (Hue-Chroma-Luminance) model (see Wikipedia [CS9], which points out that the LAB-based polar coordinates are also sometimes referred to as HCL). The HCL model captures the human perceptual axes very well without confounding effects as in the HSV or HLS approaches (more details follow below).

Human color vision and the HCL color model

It has been hypothesized that human color vision has evolved in three distinct stages:

  1. Perception of light/dark contrasts (monochrome only).

  2. Yellow/blue contrasts (usually associated with our notion of warm/cold colors).

  3. Green/red contrasts (helpful for assessing the ripeness of fruit).

See Ihaka [CS2], Kaiser and Boynton [CS3], Knoblauch [CS4], Lumley [CS5] and/or Zeileis et al. [15] for more details and references. Thus, colors can be described using a 3-dimensional space:

Representation of the three axis of human color vision.

However, for describing colors in such a space, it is more natural for humans to employ polar coordinates in the color plane (yellow/blue vs. green/red, visualized by the dashed circle above) plus a third light/dark axis. Hence, color models that attempt to capture these perceptual axes are also called perceptually-based color spaces. As already argued above, the HCL model captures these dimensions very well, calling them: hue, chroma, and luminance.

The corresponding sRGB gamut, i.e., the HCL colors that can also be represented in sRGB, is visualized in the animation below [CS1].

The shape of the HCL space is a distorted double cone which is seen best by looking at vertical slices, i.e., chroma-luminance planes for given hues. For example, the left panel below depicts the chroma-luminance plane for a certain blue (hue = 255). Along with luminance the colors change from dark to light. With increasing chroma the colors become more colorful, where the highest chroma is possible for intermediate luminance.

As some colors are relatively dark (e.g., blue and red assume their maximum chroma for relatively low luminances) while others are relatively light (e.g., yellow and green), horizontal slices of hue-chroma planes for given hue have somewhat irregular shapes. The right panel below shows such a hue-chroma plane for moderately light colors (luminance = 70). At that luminance, green and orange can become much more colorful compared to blue or red.

../_images/hcl-projections-1.png

Illustration of basic colorspace functionality

As an example a vector of colors x can be specified in the HCL (or polar LUV) model:

In [1]: from colorspace.colorlib import HCL

In [2]: x = HCL(H = [0, 120, 240], C = [50.] * 3, L = [70.] * 3)

In [3]: print(x)
polarLUV color object (3 colors)
           H       C       L
  1:    0.00   50.00   70.00
      120.00   50.00   70.00
      240.00   50.00   70.00

The resulting three colors are pastel red (hue = 0), green (hue = 120), and blue (hue = 240) with moderate chroma and luminance. For display in other systems an sRGB representation might be needed:

In [4]: x.to("sRGB")    # Convert to sRGB coordinates

In [5]: print(x)
sRGB color object (3 colors)
           R       G       B
  1:    0.89    0.59    0.65
        0.53    0.72    0.46
        0.49    0.69    0.87

The displayed coordinates can also be extracted as numeric matrices by x.get() to get the values of all or a specific coordinate of the color space the colorobject is currently in. As an example we convert the three colors to the HSV color space and extract the saturation coordinate only by calling x.get("S"):

In [6]: x.to("HSV")

In [7]: print(x)
HSV color object (3 colors)
           H       S       V
  1:  348.07    0.34    0.89
      104.61    0.36    0.72
      208.07    0.43    0.87

In [8]: print(x.get("S"))     # Saturation dimension only
[0.34460077 0.36458245 0.4341857 ]

For display in many systems hex color codes based on the sRGB coordinates can be created:

In [9]: print(x.colors())     # Automatically converts to hex
['#E495A5', '#86B875', '#7DB0DD']

Color library

The workhorse of these transformations is the colorlib class which allows to transform colorobject objects into each other.

colorlib

Color Handling Superclass

colorobject

Superclass for All Color Objects

The following classes (all inheriting from colorobject) are available to create colors in different color spaces. Colors can be transformed from and to (mostly all) color spaces using the .to(\<name of color space\>) method (see e.g., hexcols.to()).

CIELAB

Create CIELAB Color Object

CIELUV

Create CIELUV Color Object

CIEXYZ

Create CIEXYZ Color Object

HLS

Create HLS Color Object

HSV

Create HSV Color Object

RGB

Create RGB Color Object

hexcols

Create Hex Color Object

polarLAB

Create Polar LAB Color Object

HCL

alias of polarLUV

polarLUV

Create polarLUV (HCL) Color Object

sRGB

Create Standard RGB (sRGB) Color Object

Matplotlib color maps

In addition many objects provided by the colorspace package allow to convert a series of colors (color palette) into a matplotlib.colors.LinearSegmentedColormap ‘cmap’ used by matplotlib. As an example using the object x from above:

In [10]: from colorspace import palette

In [11]: cmap = palette(x, "custom palette").cmap()

In [12]: print(cmap.N)
3

Please note that matplotlib performs linear interpolation in the sRGB color space between the colors specified. This allows us to draw more than 3 colors from the color map above. However, this may result in skewed color gradients!

The better way to go is to define/design your custom palette in the HCL color space using qualitative_hcl, diverging_hcl, sequential_hcl among others (see HCL-Based Color Palettes for details).

These classes define color palettes via functions in the HCL color space and allow to draw large numbers of colors along the function space. The .cmap() method will still return a LinearSegmentedColormap but (by default) based on N = 101 distinct colors which will require less linear interpolation.

In [13]: from colorspace import diverging_hcl

In [14]: pal  = diverging_hcl("Green-Orange")

In [15]: cmap = pal.cmap()

In [16]: print(cmap.N)
101

A simple example using matplotlib.pyplot.contourf() with a custom HCL based color palette (sequential_hcl("Rocket").cmap()):

(Source code, png, hires.png, pdf)

../_images/color_spaces-1.png

References

[CS1]

Michael Horvath and Christoph Lipka. sRGB gamut within CIELCHuv color space isosurface. 2016. Wikimedia Commons. URL: https://commons.wikimedia.org/wiki/File:SRGB_gamut_within_CIELCHuv_color_space_isosurface.png.

[CS2] (1,2)

Ross Ihaka. Colour for presentation graphics. In Kurt Hornik, Friedrich Leisch, and Achim Zeileis, editors, Proceedings of the 3rd International Workshop on Distributed Statistical Computing, Vienna, Austria. 2003. ISSN 1609-395X. URL: http://www.ci.tuwien.ac.at/Conferences/DSC-2003/Proceedings/.

[CS3]

Peter K. Kaiser and Robert M. Boynton. Human Color Vision. Optical Society of America, Washington, DC, 2nd edition, 1996.

[CS4]

Kenneth Knoblauch. Color vision. In Steven Yantis and Hal Pashler, editors, Steven's Handbook of Experimental Psychology – Sensation and Perception, volume 1, pages 41–75. John Wiley & Sons, New York, third edition, 2002.

[CS5]

Thomas Lumley. \textit dichromat: Color Schemes for Dichromats. 2013. \textsf R package version 2.0-0. URL: https://CRAN.R-project.org/package=dichromat.

[CS6] (1,2)

Wikipedia. Color space — Wikipedia, the free encyclopedia. 2021. Accessed 2021-06-09. URL: https://en.wikipedia.org/wiki/Color_space.

[CS7] (1,2)

Wikipedia. Web colors — Wikipedia, the free encyclopedia. 2021. Accessed 2021-06-09. URL: https://en.wikipedia.org/wiki/Web_colors.

[CS8]

Wikipedia. CIE 1931 color space — Wikipedia, the free encyclopedia. 2021. Accessed 2021-06-09. URL: https://en.wikipedia.org/wiki/CIE_1931_color_space.

[CS9]

Wikipedia. HCL color space — Wikipedia, the free encyclopedia. 2021. Accessed 2021-06-09. URL: https://en.wikipedia.org/wiki/HCL_color_space.

[CS10] (1,2)

Wikipedia. HSL and HSV — Wikipedia, the free encyclopedia. 2021. Accessed 2021-06-09. URL: https://en.wikipedia.org/wiki/HSL_and_HSV.

[CS11]

Wikipedia. sRGB — Wikipedia, the free encyclopedia. 2021. Accessed 2021-06-09. URL: https://en.wikipedia.org/wiki/sRGB.