Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add HSLuv color space #284

Closed
yklcs opened this issue Feb 10, 2023 · 5 comments · Fixed by #404
Closed

Add HSLuv color space #284

yklcs opened this issue Feb 10, 2023 · 5 comments · Fixed by #404

Comments

@yklcs
Copy link

yklcs commented Feb 10, 2023

The HSLuv color space bounds LCh's chroma component into a "saturation component".
I'm not sure if this project is interested in adding every color space out there, but it does have some popularity, so it would be a welcome addition.

It is defined as a transformation on LCh, so implementation should be straightforward enough. I might look into creating a PR if I can.

@facelessuser
Copy link
Collaborator

Just for clarity, HSLuv is the transformation on CIELUV LCh, not LCh. The former is the cylindrical form of Luv while the latter is the cylindrical form of L*a*b*.

You'll have to at least implement Luv, CIELUV LCh, and HSLuv. The conversion path is XYZ D65 -> Luv -> CIELUV LCh -> HSLuv.

@Myndex
Copy link
Contributor

Myndex commented Sep 18, 2023

Hi @facelessuser

The conversion path is XYZ D65....

The conversions to LUV are built into HSLuv, last I checked it was a complete conversion straight from sRGB.

I happen to like HSLuv, it updates Luv with a novel built-in constraint to realizable colors in sRGB. I like Luv in general for its simplicity, lack of purple shift¹, and the fact it has a saturation correlate in addition to chroma*, while CIELAB only has chroma.

And yes, HSLuv is otherwise essentially polar Luv as Lshuv, using the saturation correlate, which has useful advantages over chroma, one being that the saturation control is closer to being an orthogonally independent control of colorfulness or color purity.

¹ Regarding the purple shift

Click to reveal the colorful gradient examples and discussion

Here are some Luv vs Lab examples from a couple years ago, before OKLab, for reference. Everything is D65, using standard CIE math. The top four are polar, and the bottom four are rectangular. For all, the gradients were created doing a simple average of each of the three correlates of which ever space, with the middle being an average of the first and last, and subdividing accordingly.

Pay attention to the top row, second from left, as that is Lshuv, it is IMO the most consistent of all.

TOP, Polar Coordinates:
$Std. HSL,\ \ Lsh_{uv},\ \ LCh_{ab},\ \ LCh_{ab}$

BOTTOM, Cartesian:
$sRGB,\ \ CIE\ xyY,\ \ L^* u^* v^* ,\ \ L^* a^* b^*$

Click to enlarge
Gradient explorer, showing blue gradients

Here we see the infamous purple shift in LAB, especially in the rectangular coordinates version. LUV does not have such a plainly obvious shift.

Next
Gradient explorer, showing blue to yellow gradients

The purple shift in LAB continues to be an issue. Also notice that sRGB is noticeably darker and that the HSL is being more colorful than the rest, but also uneven.

Next Slide — Colorful!
Gradient explorer, showing blue to yellow, reversed gradients

In this case, the polar "hue rotation" direction was reversed, so the color palette of the top row using polar coordinates is suddenly more colorful. Also, the HSL gradient isn't doing too well. The sRGB is still a bit dark, and LAB is still polluting other colors with purple. The LAB LCh is a bit out of whack — but the LUV plots, especially Lsh are still demonstrating consistency

Last slide
Gradient explorer, showing blue to white gradients

What's going on? A pure blue to achromatic gradient can demonstrate unexpected behaviors. Notice the LAB plots and their shifts, but the LUV plots are still doing well, with expected behavior.

So what's wrong with luv?

LUV is widely recognized as bad when used with diffuse, reflected surface colors. This is not in dispute. But as a color chooser for selecting colors for content on self-illuminated displays, it works well, and has advantages as mentioned.

I have reason to believe that part of why Luv does poorly in certain contexts is that the choice of Munsell value for L*, while good with Lab, is not a good fit for Luv, for reasons I am still investigating. Nevertheless Tektronix modified Luv, in particular scaling and axis substantially, for use in one of their professional broadcast color correction systems.... gosh if only I know of some perceptually uniform lightness thingy somewhere.....

Thank you for reading

.

P.S. I use details/summary to make my posts appear much shorter than they really are.

@facelessuser
Copy link
Collaborator

facelessuser commented Sep 18, 2023

@Myndex I'm not quite sure what you mean by "built into" HSLuv. You have to first get it into one of these spaces to then apply the transform to HSLuv: https://github.com/hsluv/hsluv/blob/master/math/cie.mac.

Is it self-contained in their repo (all of the conversions)? Sure, but the transformation to HSLuv requires you to first get it into LChuv, then transform it to HSLuv. These steps are separate even if they are all done within their repo. I've implemented it here: https://github.com/facelessuser/coloraide/blob/main/coloraide/spaces/luv.py and https://github.com/facelessuser/coloraide/blob/main/coloraide/spaces/hsluv.py.

If you are going to go ahead and add support for HSLuv, you might as well expose Luv and LCHuv as you have to apply the transform from XYZ anyway. If you want to hide it all in the HSLuv implementation, you can surely do that, but you deprive people of being able to use Luv/LCHuv directly.

Anyway, I think my statement holds true, but it can be implemented however it is desired here. Personally, I would expose all the color spaces as the full Luv color space can be useful if you are not confined to an sRGB-limited variant of it.

@Myndex
Copy link
Contributor

Myndex commented Sep 18, 2023

@facelessuser Ah I misunderstood your point, my bad.

The other color spaces are already here, largely.

CIE Lab, XYZ are already in color.js ... Luv isn't but uses the same L* as Lab, and the LCh for uv is identical to the LCh for ab. So literally all that's missing is the uv projection from XYZ... and the HSLuv package...

@facelessuser
Copy link
Collaborator

CIE Lab, XYZ are already in color.js ... Luv isn't but uses the same L* as Lab, and the LCh for uv is identical to the LCh for ab. So literally all that's missing is the uv projection from XYZ... and the HSLuv package...

Yes, all of this could be leveraged, and if that is how it is wanted here, that is fine. I think it would be a shame to limit support to HSLuv only, but 🤷🏻‍♂️. Either way, I don't think it is difficult to add support for any of these.

The implementation is pretty straight forward. I think to officially claim HSLuv support, you should implement HPLuv as well (per their documentation). They provide tests to confirm your implementation: https://github.com/facelessuser/coloraide/blob/main/tests/test_hsluv/snapshot-rev4.json.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants