Color spaces

The sRGB color space

A usual display contains pixels which are composed of a red, green and blue subpixel light source. Each subpixel light source supports 256 distinct brightness levels L ranging from L=0 to L=255. This results in approximately 16 million (256^3 = 16777216) distinct colors that can be represented by a single pixel.

If the red, green and blue subpixel are turned off (L = 0), the pixel is as dark as possible, which our eyes perceive as black. A pixel with the red, green and blue subpixel turned up to full brightness (L = 255) is perceived as white.

Most displays operate in the sRGB color space. Within the sRGB color space the level L is non-linearly mapped to the light intensity I such that small light intensities can be expressed more precisely – to the expense of expressing large light intensities with less precision. This is motivated by our eyes being more sensitive to the dark, i.e., small light intensities.

The graph below shows the sRGB mapping using red dots. For comparison, the linear RGB color space is shown using the grey dots.

A simple test to rudimentarily check whether your monitor uses sRGB is to look at a checkerboard pattern consisting of black and white pixels from far away, such that the checkerboard pattern blurs into a grey area. The grey results from half of the pixels emitting white light, while the other half emits no light. Thus, the resulting light intensity is 50 % of the maximum light intensity I.

According to the above sRGB mapping, a solid color with a light intensity I=0.5 is encoded using a brightness level of L=188. Since the mapping is non-linear, a brightness level of L=128 would lead to a significantly smaller light intensity than half.

Light intensity I=0.5
(by definition)
73 % grey in sRGB, L=188
Light intensity I=0.5
(on sRGB displays)
50 % grey in sRGB, L=128
Light intensity I=0.22
(shown for comparison)

Incorrect color mixing in most applications

Please note that many applications (including browsers) scale, filter and interpolate color directly within the sRGB color space, which leads to perceptually incorrect results. For example, if the above checkerboard is scaled down to half its size, an image with a light intensity of I=0.5 is expected, as this is the average light intensity resulting from the combination of a black and a white pixel.

To directly test the filtering in the browser, please compare the following black-and-white checkerboard in its original size (left) and as a scaled-down image (right). In most browsers, the scaled-down image looks too dark, as the browser mixes the color within the sRGB space, meaning that the browser averages the black and white color to a grey with L=128 and, therefore, an incorrect intensity of I=0.22.

Similar color space considerations arise when performing other color blending operations such as applying blur, interpolation between two colors as well as rotating and filtering images.

Color space compensation in Kontrast for correct color blending

By default, all Kontrast visualizations assume that they are rendered on an sRGB display. For all internal color operations such as interpolation, blending and filtering, the colors are first converted to the linear color space, operated upon, and then converted back to the sRGB color space. Thus, in Kontrast the blending, interpolation and filtering of colors results in perceptually correct results. The default value for the color space compensation method is therefore kontrast.colorSpaceCompensation = 'sRGB'.

If your screen uses a different color space, you can use the setting kontrast.colorSpaceCompensation = 'gamma'. When using this setting, the internal color space compensation is performed using a exponential relationship between brightness level and light intensity. The value of the gamma exponent is taken from the global kontrast.screenGamma property.

If you wand to blend colors directly within the sRGB space without any compensation (for example to be compatible with the native way the browser or other applications deal with color) you can disable the color space compensation by setting kontrast.colorSpaceCompensation = 'none'.

Note that all color properties within Kontrast are always assumed to be in the sRGB color space (to be consistent with the way colors are specified in CSS). Thus, any color you specified directly using a color property is not affected by the color compensation method and always looks the same.

Examples using Kontrast

The following tile plot shows 200 by 100 pixels. The left-hand side of the tile plot shows pixels with a color value that alternates between 0 and 1 in a checkerboard-like arrangement. The right-hand side shows a uniform value of 0.5. Using the correct color space compensation, the color of both sides should match.

Color interpolation: The following graph shows a tile plot, point plot and bar plot with linearly increasing data mapped to the color axis. The color axis ranges from green to red.

Color blending: The following tile plot, point plot and bar plot show linearly increasing data mapped to the opacity axis over a solid green background.

Filtering: The following graph shows a tile plot with 1000 by 1000 tiles. Each tile is either colored red or green, depending on whether a random number between 0 and 1 is smaller than x. In the default view on this page, the screen resolution is likely smaller than the data resolution of 1000 by 1000 pixels, leading to linear filtering.