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

Introduce color interpolation based on the LAB color-space #6782

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

Conversation

d4vidi
Copy link

@d4vidi d4vidi commented Dec 2, 2024

Summary

In this PR, I've introduced color interpolation based on the OKLAB color space.

(image credit: ColorAide)

Details

OKLAB is derived from CIELAB - both considered improvements compared to RGB and HSV/L in terms of color gradient computation, as the linear interpolations over their channels results in a smoother experience. That's for 2 reasons:

  1. The color space tends to better preserve light intensity across the transition (largely thanks to the L channel)
  2. They minimize the inter-color transitivity

L*a*b* does often yield results very similar to RGB w/ gamma correction, as in the case of the default colors on the web-site:
image

Nevertheless, there are some cases where the result can be considered better. Going from red to blue, for example, LAB shows a smoother transition with less intermediate coloring (purple in this case):
image
Also, in yellow-to-blue, LAB better preserves lightness:
image

Things to notice

  • In my implementation, I've completely relied on culori, but had to rip their code off from it (all-the-while keeping the credit). I couldn't use it as-is, because I had no way to specify it's meant for off-loaded execution (i.e. using the worklet notation). I could definitely use some advice with that by the maintainers ❗
  • In terms of user-facing API's, I've decided to name the color-space selection LAB (alongisde RGB and HSV), hiding the implementation details (i.e. the underlying selection of oklab, in particular). I believe that any future offering of other LAB spaces (e.g. CIELAB) could be introduced by allowing for LAB-specific options.
  • OKLAB is the default implementation in native Android development, offered by Jetpack Compose.

Motivation

There are potential screens in the apps we're working on where a smooth color transition could improve the user experience. We're avid users of reanimated and would love to be able to incorporate the best experience though it.

Test plan

TBD

@d4vidi d4vidi marked this pull request as ready for review December 5, 2024 10:26
@d4vidi
Copy link
Author

d4vidi commented Dec 9, 2024

@tjzel @piaskowyk would appreciate a go/no-go on this

@tjzel
Copy link
Collaborator

tjzel commented Dec 9, 2024

Hey @d4vidi, thanks for your contribution!

This looks interesting and I see no reason not to add this to Reanimated. We'll circle back to it once we start preparing 3.17.0 release.

@d4vidi
Copy link
Author

d4vidi commented Dec 9, 2024

Hey @devjs1000, thanks for your contribution!

This looks interesting and I see no reason not to add this to Reanimated. We'll circle back to it once we start preparing 3.17.0 release.

Super, thanks. I'm @d4vidi, BTW 😅
Would also highly appreciate your advice regarding how to perhaps include the culori library as-is while having it run in a worker thread 🙏🏻

@tjzel
Copy link
Collaborator

tjzel commented Dec 10, 2024

Haha, sorry, I'm used to doing @ and the first letter to get the OPs name, no idea where devjs1000 came from 🤭

@tjzel
Copy link
Collaborator

tjzel commented Dec 10, 2024

What do you mean by include the culori library? We don't want to add any external dependencies to Reanimated if that's what you meant.

@d4vidi
Copy link
Author

d4vidi commented Dec 10, 2024

Haha, sorry, I'm used to doing @ and the first letter to get the OPs name, no idea where devjs1000 came from 🤭

It's cool, I often make the same mistake

What do you mean by include the culori library? We don't want add any external dependencies to Reanimated if that's what you meant.

I technically ripped code off the culori library in order to convert between the LAB <--> sRGB color spaces. Ideally, I'd like to be able to use the actual library itself, as a node module.

@tjzel
Copy link
Collaborator

tjzel commented Dec 11, 2024

Unfortunately we don't have any production-ready methods to workletize full libraries. culori library would have to mark necessary functions as worklets and respect the other rules the worklets follow - which I guess is a no-go too.

Copy link
Contributor

@patrycjakalinska patrycjakalinska left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi! Firstly, thanks for your contribution, it's really nice and a pretty interesting feature c:

Moving on to the review, I'd be grateful if you'd comment code in the documentation related to this feature. Please mark it with a - preferably TODO - comment explaining that it would be uncommented when Reanimated including this feature comes out. I'll take care of upgrading Reanimated version in the docs and uncommenting this portion when it'll be available.

As of culori being a dependency - I strongly support what @tjzel said, we are not able to workletize full libraries yet, and culori adding and maintaining workletization of their important functions is probably a no-go. As I checked, your approach to rewriting needed functions to worklets is fine - they seem easy to maintain and we focus only on portions of the library that we require. Please include culori MIT license requests in the code as I mentioned in a review comment.

Copy link
Contributor

@patrycjakalinska patrycjakalinska left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Few more adjustments ✨

@d4vidi
Copy link
Author

d4vidi commented Dec 24, 2024

@patrycjakalinska So you can say I've pretty much eradicated all mentioning of OKLAB on the docs side; Replaced everything with instructional comments that start with TODO (OKLAB) so it as to make them easy to find exclusively.

Thanks a lot for all your time and patience!

@d4vidi
Copy link
Author

d4vidi commented Dec 30, 2024

Hope to get more comments from you guys/gals 🙏🏻

@patrycjakalinska
Copy link
Contributor

Hi, thanks and sorry for the wait! One thing I noticed that's happening is that when I try to use docs with your react-native-reanimated package with culori, the Docusaurus throws an error. As far as I know and worked with Docusaurus, it could be bug on my side not related to your package as well as full blown bug. Does docs on your side work with reanimated extended with culori package installed?

@d4vidi
Copy link
Author

d4vidi commented Jan 7, 2025

Hi, thanks and sorry for the wait! One thing I noticed that's happening is that when I try to use docs with your react-native-reanimated package with culori, the Docusaurus throws an error. As far as I know and worked with Docusaurus, it could be bug on my side not related to your package as well as full blown bug. Does docs on your side work with reanimated extended with culori package installed?

All good, it's new years and therefore well understood!
Currently the culori package is not a part of the project; Is the error thrown when you try to add it yourself?

@patrycjakalinska
Copy link
Contributor

patrycjakalinska commented Jan 7, 2025

All good, it's new years and therefore well understood! Currently the culori package is not a part of the project; Is the error thrown when you try to add it yourself?

No, the error rises when you check if your Reanimated package is working with documentation. To check you need to yarn && yarn build && yarn pack and use it in the Reanimated Documentation package.json as react-native-reanimated. Without the culori changes the documentation works and I'm wondering from where the bug comes (and as I said, due to Docusaurus - handler for our documentation - and its nature it is possible the bug is "on my side").

Try to replace react-native-reanimated in docs-reanimated's package.json with your reanimated with culori expansion:

  1. in /packages/react-native-reanimated run yarn && yarn build && yarn pack
  2. move the .tgz file to `/packages/docs-reanimated'
  3. in package.json change version of reanimated to your packed file

@d4vidi
Copy link
Author

d4vidi commented Jan 8, 2025

@patrycjakalinska ok I think I got it, will test that out. I've previously checked (developed) by replacing the react-native-reanimated package.json path to the relative one (i.e. without the yarn pack part). Will post back.

@d4vidi
Copy link
Author

d4vidi commented Jan 8, 2025

So just to be sure I've completely erased docs-reanimated/node_modules before packing my work (based on culori) and patching the package.json. I've checked the docs (served from localhost) with and without support for the LAB option, gradient etc. - it works flawlessly on both cases:
image

Could you share what error you're seeing?

@patrycjakalinska
Copy link
Contributor

Hi @d4vidi, good to hear that, as I suspected Docusaurus is randomly not working on my side c':

Comment on lines +13 to +27
//
// import { converter } from 'culori';
//
// export default {
// convert: {
// fromRgb: (rgbColor: RgbColor) => converter('oklab')({
// mode: 'rgb',
// ...rgbColor,
// }),
// toRgb: (labColor: LabColor) => converter('rgb')({
// mode: 'oklab',
// ...labColor,
// }),
// },
// };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this portion of code?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, no - we don't. This was meant to explain how to integrate the same functionality assuming culori could one day be workletized. I can remove it if you consider it unnecessary noise.

Copy link
Contributor

@patrycjakalinska patrycjakalinska Jan 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can remove it for now c: You can also merge main into your branch and I think we are good to go!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good news! Should I remove these TODO's altogether or just the code snippet part?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this sound as a replacement of the TODO after the code snippet is removed? -

// TODO Once we have the option to workletize external dependencies, we can replace most of the code below with
//  a simple implementation based on their converter utils (see
//  https://github.com/software-mansion/react-native-reanimated/pull/6782#pullrequestreview-2488830278).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perfect!

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.

3 participants