open-cogsci / OpenSesame

Graphical experiment builder for the social sciences
http://osdoc.cogsci.nl/
GNU General Public License v3.0
237 stars 112 forks source link

Wrong colors when using new CIELAB feature (OS 3.3) #682

Closed Martin2Constant closed 4 years ago

Martin2Constant commented 4 years ago

Hello,

In the upcoming OpenSesame version (3.3), there is the option to specify colors in the CIE L a b* color space. However, this feature produces severely different colors from other CIELAB conversions.

One limitation is that it only accepts integers as an input (e.g. 'lab(63, 2, 4)' ) but CIE L a b* colorspace can be navigated with floats (e.g. 'lab(72.2, 34.3, -28)' ), thus this feature loses accuracy when compared to other implementations.

The first screenshot is a colorwheel using colors produced by the new feature. implemented The second screenshot is a colorwheel using colors produced by other implementation (here, using the colormath library. I get the same when creating my own conversions or using the d3.js JavaScript library). custom

Here is the code I'm using for generating the colors for the colorwheels (requires the colormath library; new OS feature is commented): image

smathot commented 4 years ago

Thanks for testing this. The int issue is easily resolved. The apparent wrongness less so, but I'm also not very familiar with this colorspace. OpenSesame directly uses this function from PsychoPy:

Would it be possible to confirm that the problem comes from there? Once that's established, we can see if it's indeed really a problem, or whether it's a case of different people using different constants for this color space; and, if so, what OpenSesame should do.

For reference, this is where the magic happens:

Martin2Constant commented 4 years ago

The problem for the "wrong" colors lies in the fact that there is no transfer function, thus the output is linear RGB. When using the "transferFunc=cst.srgbTF" argument, the colors become "correct". Outputting linearRGB (gamma curve of 1) might be useful in some cases but I think the default should be to use the transfer function and to output sRGB (gamma curve of 2.2) as it is the most convenient and I guess most frequent use of LAB conversions.

Here's the code I used. image

smathot commented 4 years ago

Thanks for this. Good to have someone look at this who knows more about it than I do. Could you give some CIELab coordinates and the expected RGB values? Then I can a) fix this, and b) update the unit tests.

Martin2Constant commented 4 years ago

Sure, here's two csv converting from CIELAB to sRGB using the D65 whitepoint with the 2° standard observer (same as Psychopy's default). The difference with Psychopy default is the use of the transfer function of sRGB which applies a 2.2 gamma curve to the linearRGB values (it's the standard gamma curve for CRT , and that which most LCD screens are aiming for). One is the colors used to create the colorwheel of my "correct" screenshot (colorwheel.csv), the other is from random CIELAB values (random.csv). Since the LAB color space conversion doesn't care about bits, some RGB values are well above 255 in random.csv. This means the colors can't be rendered accurately using 8-bit RGB. CIELAB_to_sRGB.zip