rgb to Lab as a list-- is there an easier way?

Floating Point's icon
Max Patch
Copy patch and select New From Clipboard in Max.

I made a little patch that seems rather complicated for such a simple objective:
I want to convert a list of rgb values (just a 3-element list) into the L*a*b* colour space equivalent. But it seems I have to fill a matrix first, then convert to the colour space, then convert back to a list again (see patch)-- is there a simpler way to do it?
Thanks,
T
edit-- just moved this to jitter forum

Floating Point's icon

just thought I'd bump this... any feedback appreciated-- got a number of instances of this and am thinking it may not be very efficient

metamax's icon

You can't convert a generic list of RGB values directly to L*ab because an RGB list has no defined color space. First you have to define a color space for the RGB values (ex. sRGB) and then convert that to XYZ space... Only then can you convert to L*ab.

However efficiency is the least of your concerns. The results generated by your patch are off.. like WAY off. I don't know what that colorspace object is calculating, but it ain't L*ab values...

Floating Point's icon

Do you mean the L should be 0-100, a and b range from -100 to +100? because I think the jit.colorspace object maps those to chars. If that's not what you mean, is there a resource I can compare converted values to?

metamax's icon

That object is suspect. Given the values it is outputting, I wouldn't use it.

Check out http://www.brucelindbloom.com and http://www.easyrgb.com/index.php?X=MATH for the math. They are both reliable.

For a quick accuracy check of your conversions... http://www.easyrgb.com/index.php?X=CALC is a good source.

I am going to try to make a patch to do this because it's relevant to my work too.. but I'm new to Max, so it's gonna take me a little while. If you can get a patch to match the tables generated by the calculator at easyrgb.. please post it.

metamax's icon

OK, this works.

It converts RGB (0-255) to XYZ to CIE L*ab.

Like I said, I'm new at this so I'm sure it can be simplified further.. but it's pretty compact. The ugliest parts of the patch are inefficient use of [if]. I couldn't get the expressions to work how I wanted so I was forced to break out some of the math operations. It's still very accurate though. Test it using the link in my last post.

Max Patch
Copy patch and select New From Clipboard in Max.

metamax's icon
Floating Point's icon
Max Patch
Copy patch and select New From Clipboard in Max.

here's a start-- I have to admit I have only a general understanding of what's going on here, but it appears there's something not quite right with jit.colorspace rgb to lab conversion.
I've made a patch which implements the conversion code in the second link you posted, but it's not consistent with testing using the bruce lindbloom site calculator. It works fine converting rgb to xyz values, but is not consistent in mapping xyz to lab, but still it seems better than the jit.colorspace object.

edit: just saw your prior two posts -- yours and my versions seem to differ in lightness values-- anyway certainly different from the jitter object

metamax's icon

Lindbloom doesn't have an RGB to L*ab calculator. His calculates the other direction.

If you enter the L*ab values generated by my patch into Lindbloom's calculator with reference white set to D65, no adaptation, RGB Model: sRGB, Gamma: sRGB and check "scale RGB", you will get the original RGB values used to generate those L*ab values.

Also, if you use the calculator at easyRGB, it outputs exactly the same L*ab values as my patch to several decimal places. I'm confident that my patch is outputting very accurate values.

Your patch is dead accurate for XYZ, but something isn't quite right with the XYZ to L*ab...

Floating Point's icon

OK, thanks for the clarification, much appreciated.

Roman Thilenius's icon

got my versions finished, patches are here https://cycling74.com/forums/rgb2xyz

Floating Point's icon

I've managed to implement the Lab RGB conversion in jit.pix; an example patch with comparison with the jit.colorspace object follows. They are _very_ different, but consistent within their own gamuts.

Max Patch
Copy patch and select New From Clipboard in Max.

The jit.pix patches aren't very efficient-- any comments on how to make them cleaner appreciated.
(my first attempt at using jit.pix)

metamax's icon

Interesting.. It appears that at least some of the discrepacy between the jitter color conversion and the data output from the calculated formulas is essentially a white point issue. i.e. using different color adaptation matrices going in and out of rgb/xyz.

While a D65 illuminant white point is the most common reference standard and used most often for monitor calibration - sRGB specification also involves the use of D50 as an "encoding ambient white point".

Note the comments in the above link regarding relative warmth/coolness as well as the difference between a standard viewing environment and "encoding viewing environment" - both of which may account for the differences revealed in your patch.

Play with the weighting in your rgb to lab conversion using the chromatic adaptation matrices found on Lindblooms' site. In fact, he already did the matrix calculations so you only need to plug in the weights.

I have family in town so I don't have time to tinker with this now , but I'm sure this will produce some interesting results. Given that HDTV uses the Rec 709 standard (D65) and that D65 is generally a more 'universal' reference white, I am going to modifying my existing color calc abstractions so I can easily change the reference white point when doing conversions.

Thanks for sharing. This has been illuminating. :)

Floating Point's icon

I am going to modifying my existing color calc abstractions so I can easily change the reference white point when doing conversions.

let me know when you do-- then I can use it to adapt my jit.pix patches

Floating Point's icon
Max Patch
Copy patch and select New From Clipboard in Max.

for the sake of completeness this is the non-jitter 'prototype' I made up based on contributions from Roman on this thread:
https://cycling74.com/forums/rgb2xyz/

metamax's icon

Here.. I tweaked your jit.pix abstractions with the D50 weights. The difference is noticeable, but minor, with a warmer output color (due to less blue and more red). But it's definitely closer to the jitter object output.

All I did was change the weighting from

D65: 0.95046997 100. 1.08883

to

D50: 0. 96421997 100. 0.82521004

Those numbers are the coordinates of the white point in the chromaticity space. Given that white = 255 255 255, those number change how the maximum value for each color channel is scaled.

Max Patch
Copy patch and select New From Clipboard in Max.

metamax's icon

You may also choose to update the expr values for the matrix conversion in your patches. The more accurate values are:

0.4124564 0.3575761 0.1804375
0.2126729 0.7151522 0.0721750
0.0193339 0.1191920 0.9503041

Floating Point's icon

OK that's great, so now we know how to roll our own colourspaces; I'll try making an optimised and adaptable jit.pix patch when I get the chance.

metamax's icon

Wait! I think I got it.. Changing the white point for maximum channel values is not enough. Both matrices have to be adjusted to reflect the D50 white point for all values. It's not difficult. It's just a matter of changing all of the matrix values in the abstractions. I will try and get to it tonight.

Roman Thilenius's icon

and when all these things are finished, we should take the next step and invent a 4-dimensional colorspace which gives us access to temperature, mood, weather forecast and shiva presence parameters for each of the 12 color channels.

Floating Point's icon

oh roman i didn't know you cared...;)

Roman Thilenius's icon

you can feel a certain kind of inner warmth when shiva is coming closer to you, did you know?

damn, jit.pix does not exist for mac classic.

metamax's icon

Hey.. haven't forgotten about this. It's just that the existing format for the calculations is inadequate. I'm redoing everything so that the input matrices can be changed easily (using coll to store them).