I will probably write some posts and tutorials about this topic, becaue color differences are very useful when designing a color scheme or some elements to be placed on a given background color.

And for a wide range of applications working with color spaces.

Anyway, at the moment just know Wikipedia says there is a **International Commission on Illumination (CIE)** who calls distance between colors `dE`

.

Obviously the meaning is removing subjectivity… I can see two colors “almost identical” while you can see the same ones “slighty different”.

In theory, a `dE`

of under 1.0 is supposed to be indistinguishable unless the samples are adjacent to one another

To make things a little bit harder, there are different ways to calculate color difference… three formulas the CIE refined during the years… **CIE76**, **CIE94** and **CIEDE2000**.

If you want to study in depth color difference, or even small color differences may be critical for your work, then the CIEDE2000 is the most advanced way to determine color difference, and the one with the most complex formula.

Complex formulas aren’t what I am looking for because I have in mind something a little bit complicated than just measuring color difference, and the CIE76 is maybe too basic, so at the moment I am testing the CIE94 formula.

Before examining the formula, let me introduce you some ways to define colors.

If you are used to web design, you’ll probably know the **RGB** color model. The name of the model comes from the initials of the three additive primary colors, Red, Green, and Blue, that are added to reproduce all colors.

But RGB is not the only way you can code colors.

**Color models**

Here it is a brief list of color models… some of them are useful, some others not that useful, anyway let’s see them…

**RGB**: The most famous color encoding, as explained before

**CMY**: The complement of `RGB`

, named after Cyan, Magenta and Yellow.

**CMYK**: Same as `CMY`

with the added `K`

parameter which is blacK. It is the system used by printers.

**HSV** or **HSB**: A system which represents color as Hue, Saturation and Value. `Hue`

is what is seen as the color. `Saturation`

is how “pure” is the color. 0% is grey and 100% is a pure color. `Value`

represents the Brightness.

**HSL**: Just like `HSV`

but instead of Value we have lightness. This time, maximum saturation is at the mid-point (50%). 0% is black and 100% is white.

**XYZ**: This is also called “norm color system” and it’s a superset of `RGB`

. It uses **tristimulus values** when encoding. `X`

, `Y`

and `Z`

are all calculated through color-matching functions and are always positive.

The human eye has receptors (called cone cells) for short (S), middle (M), and long (L) wavelengths. Thus in principle, three parameters describe a color sensation. The tristimulus values of a color are the amounts of three primary colors in a three-component additive color model needed to match that test color.

**Yxy**: Known as the Trichromatic coordinates. `Y`

represents the brightness and `(x,y)`

hue and saturation.

**CIE Lab**: This color scale is based on the opponent color theory. `L`

represents light-dark, `a`

represents red-green and `b`

represents yellow-blue.

There are some more systems, anyway, at the moment we are interested in **Lab** color space that unlike the `RGB`

and `CMYK`

color models, is designed to approximate human vision.

Since we are used to `RGB`

(and eventually to `CYMK`

if you work in print), we need to convert these formats into `Lab`

color space, and in order to do it we must first convert them in `XYZ`

color space, and then convert them again to `Lab`

values.

**RGB -> XYZ conversion**

On the Standard Default Color Space for the Internet page on the “Colorimetric definitions and digital encodings” chapter you will find the matrix used for color conversion and the previous adjustments to do.

So, having a `RGB`

value with red, green and blue values as base 10 integers from 0 to 255, you can convert `RGB`

to `XYZ`

this way:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
<?php // RGB values $red = 39; $green = 176; $blue = 165; // same values, from 0 to 1 $_red = $red/255; $_green = $green/255; $_blue = $blue/255; // adjusting values if($_red>0.04045){ $_red = ($_red+0.055)/1.055; $_red = pow($_red,2.4); } else{ $_red = $_red/12.92; } if($_green>0.04045){ $_green = ($_green+0.055)/1.055; $_green = pow($_green,2.4); } else{ $_green = $_green/12.92; } if($_blue>0.04045){ $_blue = ($_blue+0.055)/1.055; $_blue = pow($_blue,2.4); } else{ $_blue = $_blue/12.92; } $_red *= 100; $_green *= 100; $_blue *= 100; // applying the matrix $x = $_red * 0.4124 + $_green * 0.3576 + $_blue * 0.1805; $y = $_red * 0.2126 + $_green * 0.7152 + $_blue * 0.0722; $z = $_red * 0.0193 + $_green * 0.1192 + $_blue * 0.9505; // displaying the values echo "$x $y $z"; ?> |

Now, next step:

**XYZ -> Lab conversion**

In order to convert `XYZ`

to `Lab`

, first we must set the **white point**, that is a set of tristimulus values or chromaticity coordinates that serve to define the color “white” in image capture, encoding, or reproduction.

Then, following the formula found on this page, we can solve the problem this way:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
<?php $_x = $x/95.047; $_y = $y/100; $_z = $z/108.883; // adjusting the values if($_x>0.008856){ $_x = pow($_x,1/3); } else{ $_x = 7.787*$_x + 16/116; } if($_y>0.008856){ $_y = pow($_y,1/3); } else{ $_y = (7.787*$_y) + (16/116); echo $_y."<br>"; } if($_z>0.008856){ $_z = pow($_z,1/3); } else{ $_z = 7.787*$_z + 16/116; } $l= 116*$_y -16; $a= 500*($_x-$_y); $b= 200*($_y-$_z); // displaying the values echo "$l $a $b"; ?> |

And in the end, the orginal `RGB 39,176,165`

is converted in `Lab 65.12, -37.39, -4.54`

that is very close to Photoshop CS4 `Lab 65,-38,-5`

that probably uses a different white point.

Next time we’ll see something interesting to do with these formulas.

Tweet
## Comments 13

Nice article. Pretty usefull in understanding color models.

Just saying but … you could use more functions.

Pingback: Weekly Shared Items – 1. September, 2009 | TOXIN LABS - weblog of a german design student from wuerzburg

Pingback: Color difference algorithm – part 2 : Emanuele Feronato

Pingback: pic2col – extract color schemes from a picture : Emanuele Feronato

Excellent article. Very helpful, especially to find some useful code examples that demonstrate these conversions.

A question and a note. First, what white point did you use for your calculations? I know that Photoshop’s color matching algorithms are balanced on a D50 white point. As for a simple note, I am doubtful that the difference between your final numbers and Photoshops are due to a white point difference. It looks like a simple rounding to me: 65.12 -> 65 (round down, valid), -37.39 -> -38 (round up, rather than round down, but that could be due to precision differences in the calculation), -4.54 -> -5 (round up, valid).

Again, thanks for the example code.

I think the $z color is far less than that it would be …

Cordially.

In fact, In RGB 2 XYZ, I don’t understand why we have to adjust values before applying the matrix ?

Could someone explain me ?

You do not explain of the in put RGB values are linear RGB, sRGB or RGB with a 2.2 gamma.

You formulas seems to assume linear RGB, but typical (non-mathematical) images are more usually sRGB. The difference is important and quite massive!

Pingback: How to Choose Colours Procedurally (Algorithms) ยป devmag.org.za

Pingback: Xterm 256 colors??????? | SanRin?

Thanks a lot, :)

Pingback: Lukasz Krawczyk blog | Colour detection algorithm

Pingback: Comparison of colours in Actionscript 3 | Code Lab