True Color Interpolation

Michael Michailidis
5 min readAug 16, 2018

I recently finished writing a Tween Engine for iOS Views, in which I aimed to add all the features that I felt were missing from other (great) libraries.

From these features, and if I had to pick only one, I would say that the one I feel was really needed was a true color interpolation strategy. And when I say “true,” I mean true to the human eye. So let me explain:

Color Spaces

Like anything else inside a computer’s memory, colors are stored as numbers. The way it’s done is by breaking each color into separate components, each represented by a single numerical value. These components can be thought of as dimensions in an n-dimensional space, called a color space, where n is the number of components. Since most color systems break down color into 3 components, they can be visualized as 3-dimensional cubes. Perhaps the better known of these systems — even to non-programmers — is the “red, green, and blue” or RGB, which visualised below:

RGB is the most native system of color since it captures the way computer screens synthesize colors by using three tiny spotlights, one red one blue, and one green on every pixel!

LED screen close up

Interpolating

Breaking a color down into components helps enormously in interpolation, as we now have only three numbers that we need to move in-between values. This means three linear interpolations, one for each component, following a well known formula. Given two colors A and B, each with components r, g and b, we can derive the in-between color C at time T (t is normalised and moves between 0 and 1)

Looking at the formula above we can intuitively understand that when t is 0 then Cr = Ar, our derived color in other words is the same as the start color, which is about right. When t = 1 at the end of our animation, Ar - Ar get eliminated and Cr = Br, which is the end color.

Notice that we can do exactly the same using any color space, RGB, HLV, CMYK (the last is what printers use as it applies to pigments spread on a white sheet of paper).

The Problem with RGB

Although RGB is found on all platforms and will always provide a common language between languages, operating systems and data interchange formats, it is not without limitations. One such problem occurs in our case when we try to interpolate between values. Have a look at the center of the cube above: It is gray. Imagine then what happens when we are moving linearly between the bottom left and top right corner within the RGB cube: we pass through a color that we do not see as belonging to the gradient between red and turquoise. Another illustration might help to clarify:

Above we see that pure colors work well but blended ones don’t to create a good mix as we did not expect the middle of dark green and violet to be gray! This will never affect the beginning and end colors of the interpolation of course but the mid points might be disappointing as they might contain little to no chroma value.

HCL to the Rescue

Interpolating in different color spaces will have different results as we will be passing from whatever colors happen to lie in between our start and end values in the given space. The creation of a color space is a scientific process as mathematical transformations of one space to another need to be created in combination with both the properties of light and the human visual system. So, long story short, we are not going to be creating our own color space any time soon.

There are however spaces which are optimised not for the physics of light but for the subjective perception of color. One such space is the Hue-Chroma-Luminance (HCL) color space. Have a look at the comparison between RGB (top) and HCL (bottom) below:

What happens with RGB is what I explained above. Trace the cube in the first digram form the top right to the bottom left corners and see how it passes through a middle of gray before reaching its target. This is visually unexpected but is of course, mathematically correct! HCL on the other hand passes through what we would expect, more or less of course, as there is no objective way to agree on what an intermediary should look to the eye.

The problem with HCL is that it is computationally expensive to use, as an RGB value needs to pass through a number of transformations until it is expressed in HCL and then back from that to RGB. An interesting strategy therefore is to use HLC in order to generate intermediate colors that will then be interpolated in native RGB space.

Further Reading

Alan Zucconi wrote the article that became the original inspiration for my work.

--

--

Michael Michailidis

I am a software engineer working in Node.js + iOS with an eye for blockchain applications!