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

lab() and lch() color previews added #306

Open
wants to merge 15 commits into
base: main
Choose a base branch
from

Conversation

GauravB159
Copy link
Contributor

@GauravB159 GauravB159 commented Nov 6, 2022

Issue #305
Main Repo Issue microsoft/vscode#165207

  • Added lab() preview
  • Added lch() preview
  • Added basic unit tests for lab()
  • Added basic unit tests for lch()
  • Fixed logic where negative values inside a color function were not parsed
  • Added oklab() preview
  • Added oklch() preview

@GauravB159 GauravB159 marked this pull request as draft November 8, 2022 13:17
@aeschli
Copy link
Contributor

aeschli commented Nov 9, 2022

Thanks for the PR, it looks promising. I added comments.

  • please format the changes with the TypeScript formatter built-in in VS Code
  • use const when possible

@GauravB159
Copy link
Contributor Author

Done! Didn't know about the formatter, I'll keep that in mind going forward. And I've replaced const when possible. Is the functionality required all covered by this? I'll add more test cases and the other two functions if so. Thank you.

@romainmenke
Copy link
Contributor

romainmenke commented Nov 9, 2022

Thank you for this @GauravB159!

I've gone over these changes and the conversions don't seem to be accurate.
Can you share the source of the transforms?

Good reference code can be found here : https://github.com/w3c/csswg-drafts/tree/main/css-color-4
WPT has a bunch of tests : https://wpt.fyi/results/css/css-color?label=master&label=experimental&aligned&view=subtest

We also have a bunch of tests : https://github.com/csstools/postcss-plugins/blob/main/plugins/postcss-lab-function/test/basic.display-p3-false.preserve-true.expect.css
And also code that you can take : https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-lab-function/src/css-color-4

But best of all would be to use https://github.com/LeaVerou/color.js, if @aeschli is open to adding this as a dependency?
The authors of this package are the specification editors for most of the things related to color in CSS.


One important aspect that doesn't seem to be covered here is out of gamut color handling. It is not possible to round trip lab -> rgb -> lab for all colors without changing the channel values. This might be confusing for users if they are not aware of this and just switch to a different color function out of habit.

@GauravB159
Copy link
Contributor Author

Hi @romainmenke

I used this webpage for a reference for the formulae. Is there somewhere I could see the correct values?

I was using this online converter to verify my values. It does give values in decimals, but rgb requires whole numbers I guess, so I have rounded the values at the end. Maybe that is causing an issue?

lab -> rgb -> lab is probably inaccurate because of the rounding up right? Is there a workaround to that that I could implement?

Thanks for your help! I'll check out the code you linked, maybe there's some issue with the formula implementation.

@aeschli
Copy link
Contributor

aeschli commented Nov 9, 2022

Thanks for the great info @romainmenke !
No added dependencies please. It would mean quite some administrative overhead as I have to get legal approvals. Also for maintenance it's easier if we own all the code.

@romainmenke
Copy link
Contributor

lab -> rgb -> lab is probably inaccurate because of the rounding up right? Is there a workaround to that that I could implement?

Rounding errors might also cause this, but those would be very small deviations.
lab, lch,... however can all express a lot more colors than srgb (even some colors that do not exist). So a valid value in lab might not have a corresponding value in srgb.

I think there are three options :

  1. allow channel values in srgb to go under 0 or above 255. (this options is lossless)
  2. clamp channel values in srgb to 0 - 255. (lossy and gives poor results)
  3. apply a gamut mapping so that colors from lab that are out of gamut for srgb are visually similar. (lossy and gives ok results)

The "right" option depends on the function of this feature in VSCode :

  • a way to change the format of a color function without changing the value
  • a way to change a color in one color space to a another
  • a way to change a modern format to a legacy format or back
  • ....

No added dependencies please. It would mean quite some administrative overhead as I have to get legal approvals. Also for maintenance it's easier if we own all the code.

Got it!
Yes avoiding all that is better.

The code linked from the CSSTools repo is a port to TypeScript from the reference implementation that exists in the csswg-drafts repo.

It has the same W3C license because the only thing I did was add typings.

@GauravB159
Copy link
Contributor Author

@romainmenke Yeah, I understand what you're saying. Now that you mention it, I remember there were negative and valuss greater than 255 after converting to sRGB. I clamped those values to 0-255 which might be causing the loss.

@aeschli Which option do you recommend we go with? We could store the negative values and clamp them just while displaying the color possibly.
Although this might still cause issues in a lab->rgb->lab conversion through the color picker since it will pick up the clamped string from the new rule and use that, and not the stored negative values.

@GauravB159 GauravB159 marked this pull request as ready for review January 23, 2024 19:32
@domnantas
Copy link

Conversion from a wide to a narrow gamut is naturally lossy, so that should not be avoided. In the case of the color picker, the users can be informed that conversion is lossy, like in Chrome's DevTools color picker: https://developer.chrome.com/docs/devtools/css/color#convert-colors This approach may require ditching the click-to-convert in favor of a dropdown.

@romainmenke
Copy link
Contributor

romainmenke commented Nov 10, 2024

Conversion from a wide to a narrow gamut is naturally lossy

When displaying a color on a screen or in print, yes.

But wide gamut colors can still be represented in narrow gamut notations by going beyond the value ranges that describe the boundaries of the narrower gamut.
These round-trip just fine if the implementations are correct.

rgb(300 -20, 0) -> beyond 0 - 255, so out of gamut but otherwise there is nothing weird about these values.

There is no mathematical reason to make these lossy when converting from one notation to another.

@domnantas
Copy link

Interesting, rgb(300, -20, 0) seems to be valid in CSS, and browsers take care of clamping it to sRGB. This leads me to believe the option 1 @romainmenke suggested

  1. allow channel values in srgb to go under 0 or above 255. (this options is lossless)

fits VSCode usecase the best, though I'm curious how would rgb(300, -20, 0) be converted to hex.

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

Successfully merging this pull request may close these issues.

4 participants