# How to replicate v9's color conversion to LAB under v10

Mathematica 10(.0.0) appears to use a different flavor of the LAB color space, but I would like to emulate the same behavior observed in version 9(.0.0).

## v9

Brown
(*RGBColor[0.6, 0.4, 0.2]*)

ColorConvert[Brown, "RGB" -> "LAB"]
(*{0.714252,0.0598271,0.283735}*)


## v10

Brown // FullForm
(*RGBColor[0.6,0.4,0.2]*)

ColorConvert[Brown, "RGB" -> "LAB"] // FullForm
(*LABColor[0.4802420048160916, 0.17425620426156752, 0.3687165422680724]*)


v10 ColorConversion's documentation mentions a D50 white point and LABColor's even lists some formulas, but v9's docs avoid the subject completely.

Which conversion is correct? Are they equivalent, only with a different "black magic" color space parameter? And, if so, how could I replicate v9's results under v10?

• Related: 7483. One of the answers replicates the V9 conversion. – Michael E2 Nov 6 '14 at 1:45
• v9's lightness of 0.71 is far too light to be brown. Here's an independent implementation of RGB to Lab conversion, whose results are close to v10's (although slightly different because it uses a D65 white point). – Rahul Nov 6 '14 at 3:47

I had implemented my own color conversion functions previously so that I could convert to the Msh color space, a polar version of LAB, so I thought I'd give it a go.

To do the color conversion, you have to know what reference white value is being used. The numeric values can be found here where they are referred to as reference illuminant tristimulus values. Next you need a transformation matrix to go from sRGB to XYZ color spaces, and the exact matrix you use depends again on the reference white.

Version 10 uses a D50 reference for XYZ and LAB, while version 9 seems to have used a D65 (but this is a small difference and not enough to account for the dramatically different values you find).

Here is what happens in version 10:

rgb2labV10[r_, g_, b_] := Module[{
referenceWhite = {96.42, 100.0, 82.49},
transformation = {
{0.4360747, 0.3850649, 0.1430804},
{0.2225045, 0.7168786, 0.0606169},
{0.0139322, 0.0971045, 0.7141733}
},
rgblinear, x, y, z, f},
(*Transform RGB to linear RGB *)

rgblinear =
If[# > .04045, ((# + 0.055)/1.055)^2.4, #/12.92] & /@ {r, g, b};
(*Transform linear RGB to XYZ *)
{x, y, z} =
100 transformation.rgblinear;

(*Transform XYZ to LAB *)

f = If[((#) > 0.008856), (#^(1/3)), (7.787 # + 4/29.)] &;
{x, y, z} = f /@ ({x, y, z}/referenceWhite);
{116.0 (y - 4./29), 500.0 (x - y), 200 (y - z)}/100
]

rgb2labV10[.6, .4, .2]
(* {0.480242, 0.174275, 0.368625} *)


For some reason, in the previous version, Mathematica omits the step of first converting to linear RGB color - even though this seems to be the norm. See here, here, and here for example.

The conversion is therefore given by

rgb2labV9[r_, g_, b_] := Module[{
referenceWhite = {95.047, 100.0, 108.883},
transformation = {
{0.4124564, 0.3575761, 0.1804375},
{0.2126729, 0.7151522, 0.072175},
{0.0193339, 0.119192, 0.9503041}
},
x, y, z, f},
(*Transform linear RGB to XYZ *)
{x, y, z} =
100 transformation.{r, g, b};

(*Transform XYZ to LAB *)

f = If[((#) > 0.008856), (#^(1/3)), (7.787 # + 4/29.)] &;
{x, y, z} = f /@ ({x, y, z}/referenceWhite);
{116.0 (y - 4./29), 500.0 (x - y), 200 (y - z)}/100
]

rgb2labV9[.6, .4, .2]
(* {0.714258, 0.0598473, 0.283741} *)

• If waiting a year is what it takes to have a nice answer like this one, so be it! I have a few other unanswered questions wink wink – Aisamu Feb 12 '16 at 12:43
• You accounted for chromatic adaptation in this case, yes? – J. M. is away Feb 12 '16 at 13:07
• @J.M., ja - I followed the formulas from this site – Jason B. Feb 12 '16 at 13:09
• It bothers me slightly that I only have accuracy up to about 4 decimal places, but I suppose that Mathematica might truncate their conversion matrices a little bit more than Bruce Lindbloom does. – Jason B. Feb 12 '16 at 13:12