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

Clamp RGB to sRGB gamut #10

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Conversation

drwpow
Copy link
Contributor

@drwpow drwpow commented Sep 3, 2023

Changes

Fixes #9. Clamps colors to the RGB range.

CleanShot 2023-09-03 at 16 01 06

Worth noting that this is the “bad” way to clamp; Björn Ottosen outlines keeping hue consistent and clamping lightness and chroma, which culori has implemented in their clampChroma(… 'oklch') method. I instead took the lazier approach of just clamping to (0, 1) as a first pass.

Culori’s clampRGB() function also takes the same lazy approach, but loads a bunch of converter methods for a total of 3.6 kB for what ends up being the same end result.

Alternative method

The alternate way of doing it the “right” way has a couple caveats:

  • It adds ~ 3.8 kB of client weight. Which may not be much all things considered. Also worth noting that even though clampRGB() is a bit bloated, clampChroma() is not—it’s actually a complex calculation and does involve shifting a color through a couple color spaces to get the accuracy right.
  • This only happens when the value changes externally (e.g. the slider), so you could argue that true gamut adjustment is outside the scope of this library. When colors are adjusted on the picker this problem doesn’t exist

But if the alternate method is preferred, it’s an easy swap

Reviewing

  • See comments

// only clamp if necessary
if (okhsv.s > 1 || okhsv.v > 1) {
const { r, g, b } = oklab_to_rgb(okhsv_to_oklab(okhsv))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This seems a bit roundabout—converting to RGB just to clamp—but the problem isn’t really fixed otherwise. And I made it as performant as I could be by not clamping unless it’s actually needed (i.e. you can call clamp_color() for “free” on in-range colors)

Copy link
Contributor Author

@drwpow drwpow Sep 4, 2023

Choose a reason for hiding this comment

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

Alternate approach

Also, edited the PR notes, but if we wanted to do this the “correct” way, it’d just involve using Culori’s clampChroma(…, 'oklch') method here instead.

clampChroma() is the same method used on oklch.com for the “fallback” color which matches Björn’s implementation from my extensive testing.

So the tradeoff here is basically just is 3.8 kB of weight worth it to fix the problem? I could go either way, honestly

@@ -0,0 +1,90 @@
<script lang="ts">
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added a new /oklab page to test this out. Just a copy of the original RGB demo, just with the obvious colorspace change

@drwpow drwpow changed the title Clamp rgb Clamp RGB to sRGB gamut Sep 3, 2023
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.

Values need to be clamped to RGB / P3 gamut
1 participant