[KColorUtils] Add hue(), chroma(), hcyColor() and update documentation
ClosedPublic

Authored by ndavis on Jan 30 2020, 5:21 AM.

Details

Summary

This patch provides ways to get just the hue or just the chroma in the HCY colorspace and a way to get a QColor based on given hue, chroma, luma and alpha values.

This patch also adds more details to the documentation, such as the ranges of chroma and hue and the fact that KHCY hue, chroma and luma are computed in linear colorspace rather than sRGB.

Diff Detail

Repository
R273 KGuiAddons
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.
ndavis created this revision.Jan 30 2020, 5:21 AM
Restricted Application added a project: Frameworks. · View Herald TranscriptJan 30 2020, 5:21 AM
Restricted Application added a subscriber: kde-frameworks-devel. · View Herald Transcript
ndavis requested review of this revision.Jan 30 2020, 5:21 AM
broulik added inline comments.
src/colors/kcolorutils.h
42

This doesn't mention hcy anywhere and there's QColor::hue.
But we already have luma in the same way, so I guess this is alright.

ndavis marked an inline comment as done.Jan 30 2020, 9:12 AM
ndavis added inline comments.
src/colors/kcolorutils.h
42

Hue in this implementation of HCY is similar, but not the same as hue in HSV or HSL. For instance, the hue of #232629 is 0.587279 in HCY and 0.583333 in HSV/HSL.

Luma and chroma are also different than value/lightness or HSV/HSL saturation.

ndavis marked an inline comment as done.EditedJan 30 2020, 9:13 AM

Just realized, I'm not actually certain that hue in HCY translates directly into degrees like in HSV/HSL and negative values are apparently valid. For #FF00FF, HCY hue is -0.166667 while HSV/HSL hue is 0.833333. I wish this library had more thorough documentation.

OK, it seems like hue goes from -0.166667 (#ff00ff) to almost 0.833333 (#ff00ff minus a tiny amount of red). I think it might be bugged.

ndavis updated this revision to Diff 74959.Feb 3 2020, 9:22 PM
  • Update hue() comment to reflect its true behavior
ndavis added a comment.EditedFeb 3 2020, 9:26 PM

I emailed Matthew Woehlke:

Me:

[snip]
I noticed that the minimum value for hue was -0.166667 (#ff00ff) and
the maximum was almost 0.833333 (slightly less red than #ff00ff). Is
this intentional or a bug? It's a bit hard to tell how the math is
meant to work.
[snip]

Matthew Woehlke:

[snip]
I assume you're talking about the hue that is calculated when converting
*from* RGB?

Yes, that looks intentional. There are three branches for computing the
hue, based on which component is "dominant" (i.e. has the largest
value), which produce values of 0/3, 1/3 and 2/3, ±1/6.

Keep in mind that "hue" is a cyclic value, i.e. h=1.5 is perfectly valid
and should produce the same result as h=0.5, h=-0.5, etc. (Note that
conversion *to* RGB starts by normalizing hue.)

Basically, since it is desirable to accept denormalized hue anyway, it
is slightly easier (read: less code, fewer machine instructions) to not
bother normalizing it in conversion from RGB. If you are extracting HCY
values for display purposes, you should apply the wrap helper function
to the value first.
[snip]

ndavis added a comment.EditedFeb 3 2020, 9:37 PM

luma() and getHcy() don't return normalized or wrapped values. Should they? If they should, then we should also normalize chroma() and wrap hue() as Matthew said.

ndavis added a subscriber: mwoehlke.Feb 3 2020, 9:48 PM
ndavis added a comment.Feb 3 2020, 9:52 PM

Just realized @mwoehlke is on Phabricator, so I added him to the subscribers in case he has anything he wants to say.

Indeed, we could have been having this conversation here instead of via e-mail 😉. But, six of one...

I believe luma and chroma are already guaranteed to return normalized values; it's just hue that you may want to normalize if you don't want to "surprise" users with its "natural" range of ¯¹⁄₆ - ⁵⁄₆.

src/colors/kcolorspaces.cpp
161

So... per discussions, wrapping this in, well, wrap 😉 might be reasonable.

mwoehlke added inline comments.Feb 3 2020, 10:07 PM
src/colors/kcolorutils.h
42

I expect it wouldn't hurt to mention that luma, chroma and hue all work in linear color space. (I expect this is the reason KHCY and QColor produce different answers.)

ndavis updated this revision to Diff 74962.Feb 3 2020, 10:08 PM
  • Wrap the hue
ndavis updated this revision to Diff 74963.Feb 3 2020, 10:16 PM
  • Update commments
ndavis retitled this revision from [KColorUtils] Add hue(), chroma() and getHcyColor() to [KColorUtils] Add hue(), chroma() and getHcyColor() and update documentation.Feb 3 2020, 10:26 PM
ndavis edited the summary of this revision. (Show Details)
ndavis updated this revision to Diff 74964.Feb 3 2020, 10:34 PM
  • Say that the hue, chroma and luma values are based on linear RGB.
ndavis retitled this revision from [KColorUtils] Add hue(), chroma() and getHcyColor() and update documentation to [KColorUtils] Add hue(), chroma(), getHcyColor() and update documentation.Feb 3 2020, 10:46 PM
ndavis marked 2 inline comments as done.Feb 4 2020, 12:47 AM
ndavis marked an inline comment as done.
ndavis added a comment.Feb 4 2020, 5:43 PM

Anyone want to accept this?

mwoehlke added inline comments.Feb 4 2020, 9:43 PM
src/colors/kcolorutils.cpp
60

I guess it will be less confusing if this is also normalized?

*h = khcy.h + (khcy.h < 0.0 ? 1.0 : 0.0);
src/colors/kcolorutils.h
36

"0.999..." is a little odd, and I wonder if it is accurate for e.g. QColor::fromRgba64(0xffff, 0, 1}? Maybe something like "just under 1.0 (also red)" would be more useful? (If you want to get technical, "to (asymptotically) 1.0" would also work. Maybe "0.0 approaching 1.0"?)

The range is of course [0, 1), but I don't know how to say that in straight-forward English 🙂.

OTOH, I wonder if it's worth bothering, vs. just saying "0.0 to 1.0" and ignoring that it will never be exactly 1.0.

37

Suggestion: "The result is computed in linear (not sRGB) color space and may differ slightly from QColor::hue()."

For the others, drop "and may differ...".

72

I guess here should use the same text as hue?

85

This reads a little odd. I think "For example, 0.0 and ..." would be better.

86

It might be useful to add (to luma also) "Out of range values will be clamped.".

93

This name feels a little odd, but I'd appreciate some broader input. Maybe hcyColor?

ndavis updated this revision to Diff 75021.Feb 4 2020, 10:16 PM
  • Address comments
ndavis marked 5 inline comments as done.Feb 4 2020, 10:23 PM
ndavis added inline comments.
src/colors/kcolorutils.h
36

from 0.0 (red) to almost 1.0 (slightly blue-ish red)

This sounds good to me. I think it's worth saying that it won't be 1.0 so that people don't assume the number is a rounding error or something.

ndavis updated this revision to Diff 75022.Feb 4 2020, 10:26 PM
ndavis marked an inline comment as done.
  • More edits based on comments
ndavis marked 3 inline comments as done.Feb 4 2020, 10:27 PM
ndavis added a comment.Feb 6 2020, 2:45 AM

Any more suggestions?

ndavis updated this revision to Diff 75094.Feb 6 2020, 11:01 AM
  • Update @since version and fix hcyColor comment edit I missed
ndavis updated this revision to Diff 75097.Feb 6 2020, 11:14 AM
  • Remove getHcy hue value change
ndavis added inline comments.Feb 6 2020, 11:14 AM
src/colors/kcolorutils.cpp
60

I should probably put this change in another commit so as not to do too much at once, so I'm removing it from this one.

ndavis marked an inline comment as done.Feb 6 2020, 12:10 PM
ndavis retitled this revision from [KColorUtils] Add hue(), chroma(), getHcyColor() and update documentation to [KColorUtils] Add hue(), chroma(), hcyColor() and update documentation.Feb 6 2020, 12:14 PM
ndavis edited the summary of this revision. (Show Details)
This revision was not accepted when it landed; it landed in state Needs Review.Feb 6 2020, 5:59 PM
This revision was automatically updated to reflect the committed changes.