# Color difference algorithm – part 2

It’s time to see how to calculate difference between two colors.

I am using the **CIE1994** formula because it’s quite accurate and not that complex to calculate.

Here it is, assuming I have two colors in Lab format

where

(thanx to **Bruce Lindbloom**)

First, I am turning the scripts explained at Color difference algorithm into functions, 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 |
function rgb_to_xyz($rgb){ $red = $rgb[0]; $green = $rgb[1]; $blue = $rgb[2]; $_red = $red/255; $_green = $green/255; $_blue = $blue/255; 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; $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; return(array($x,$y,$z)); } |

and…

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 |
function xyz_to_lab($xyz){ $x = $xyz[0]; $y = $xyz[1]; $z = $xyz[2]; $_x = $x/95.047; $_y = $y/100; $_z = $z/108.883; 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); } 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); return(array($l,$a,$b)); } |

Now, it’s time to determine color difference, using the above formula:

1 2 3 4 5 6 7 8 9 10 11 12 13 |
function de_1994($lab1,$lab2){ $c1 = sqrt($lab1[1]*$lab1[1]+$lab1[2]*$lab1[2]); $c2 = sqrt($lab2[1]*$lab2[1]+$lab2[2]*$lab2[2]); $dc = $c1-$c2; $dl = $lab1[0]-$lab2[0]; $da = $lab1[1]-$lab2[1]; $db = $lab1[2]-$lab2[2]; $dh = sqrt(($da*$da)+($db*$db)-($dc*$dc)); $first = $dl; $second = $dc/(1+0.045*$c1); $third = $dh/(1+0.015*$c1); return(sqrt($first*$first+$second*$second+$third*$third)); } |

And you’ll find the difference between colors.

Next time, a real application using all this boring theory… (you will be surprised…)

**successful commercial Flash game from a real world example**: get the fully commented source code of Globez, a Flash game played millions of times which generated a four figure income.

**Limited copies available**.

**Get it now**

## This post has 12 comments

## dim

great snippet … i will love to see a function that can generate lighter or darker color by a given color value through parameter

this will be very handy when we want to auto generate color themes bye given color value by user

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

[…] http://www.emanueleferonato.com/2009/09/08/color-difference-algorithm-part-2/ […]

## Eduardo

I trying to transfer this code to pascal. I don’t understan the following operation:

$_red *= 100;

$_green *= 100;

$_blue *= 100;

Could you explain to me?

## kpodenphant

This is frickin’ awesome.I ported it to Actionscript.

I tried the RGB distance method which worked ok, but had some errors. Then i tried converting to HSB which worked well for the RGB errors but has some other error.

This algorithm is sweet!

## anonyMouse

Eduardo it means that the variable is set to its current value times 100;

i.e. red=2;

red*=100; (red is now 200, all further code that uses the variable “red” will now use 200 rather than 2);

## Radek

Thanks for great snippet Emanuele !

Just one point – shouldn’t be used abs(…) for all delta computations in de_1994() ?

Thanks anyway !

## Igor

Thanks for explaining this stuff, and for your snippets of code )

I’d like to use those snippets in our project, but in your post you don’t mention it anywhere, so can I ask you if it’s okay to reuse them? And if so, can you please put a license note on them, so they will be legally accessible?

## Emanuele Feronato

Hello Igor,

use it as you want, there’s no restriction, ok?

## Dylan

Thanks for this, it saved me A LOT of time.

I had to change Line 8 of de_1994 to $dh = sqrt(abs(($da*$da)+($db*$db)-($dc*$dc)));

## Dylan

Change line 8 of de_1994 to:

$dh = sqrt(($da*$da)+($db*$db)+($dc*$dc));

## Dylan

You are going to kill me!!! Ignore the nonsense I posted earlier…

Change line 8 of de_1994 to:

$dh = ($da * $da) + ($db * $db) – ($dc * $dc);

if ($dh < 0) { $dh = 0; } else { $dh = sqrt($dh); }

I guess the problem is an excessively large delta C resulting in a sqrt of a negative number. This was causing NaN on many comparisons.

## Jimmy James

Where’s the next part? I want to see how these functions are used!