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
additional colour space for d3 #579
Conversation
Ah I just saw that there is a pull request for HSV too... will add interpolators as per the comment there. |
Nice work, and thank for you the contribution! Related #183 - d3.lab Do you have any recommendation as to how to choose between XYZ, CIE Lab or CIE LCh? Is there a pressing need for all three, or did you include them for completeness' sake? My main reservation here is feature creep. Still, given the interest I could be convinced of the usefulness of including at least one perceptually-based colorspace in core. (Probably CIE Lab?) The other colorspaces are useful, but I wonder if it might be better to have a d3-chromatist plugin that adds additional colorspaces on demand? Implementation comment: if we have more than two color spaces, then having methods on every color space to convert to every other color space probably won't scale. Fortunately, it's also unnecessary because all of them must support a toString() method that returns the "#rrggbb" format (for browser compatibility); as long as all the constructors support parsing the same format and converting to the respective colorspace, then we only have to deal with conversion to and from RGB. So, we shouldn't remove the existing methods for backwards-compatibility, but you should only have to implement an rgb() and a toString() method on the new colorspaces, and leave the conversion to the constructors. For example, to go from xyz to lab, you might say |
XYZ was only really there as CIELab is defined as a transform from it. I don't think there is much of a use case for it directly, so will remove it. The other two are just the linear and cylindrical versions of the same space. Some operations only really make sense in the linear CIELab, like interpolation, but other things like changing hue make more sense in cylindrical coordinates. One option would be to have one type but expose the cylindrical operations on it too. I think this is probably the nicest to work with, so will give it a try. |
Ok so now XYZ is gone. CIELab now has hue() and chroma() methods that can return or set the hue and chroma, which is the only reason I had CIELch, so that is gone too. Added Lab interpolator. It is pretty small, so doesn't look too much like bloat in the core. |
Some thoughts at this point:
|
It’s quite helpful to be able to interpolate in terms of both LCh and Lab*. The former is useful when it’s a desirable feature to keep chroma high (for instance, when interpolating from red to blue, it might be nice to go through a colorful purple instead of a dull purplish-gray). As a precedent, ArcGIS allows the use of either in its “color ramp” pickers. Regardless of which are supported, CIELAB → RGB transformations have to have some knowledge of gamut and some gamut mapping algorithm for out-of-gamut colors. The most obvious choices are (a) the nearest in-gamut point between a color and the grey of the same lightness, and (b) the nearest in-gamut point between a color and middle gray (L* = 50). HSL/HSV/RGB are quite perniciously bad tools for visualizations (and anything with human input involved, really), and the documentation should clearly recommend against them. Chroma (C) should scale the same as a/b*, or else it’s entirely confusing what it means. CIELAB has no “maximum” chroma, and 100 is not in any way special. It should not accept percentages. You might be right that CIECAM02 is more complex than necessary for many D3 applications. |
One more thing that should really be clarified: I assume the CIELAB here is relative to a reference D65 white point? This is fine, but it should be pointed out in the docs that this makes for different output than Photoshop, which uses a chromatic adaptation transform (the Bradford CAT) to adapt XYZ colors from a source color space’s white point (e.g. sRGB’s D65) to D50, and then computes CIELAB coordinates based on that D50-adapted XYZ. |
Thanks for those comments they are very helpful. Will work on the issues raised, should be able to add both interpolators for example. |
Having used this as is for a bit, it is annoying not to have a way to do LCh initialization. Not sure whether to do an "lch(...)" style one like rgb has or go back to having an LCh colourspace. Doing interpolation across LCh will be a little slower without a colourspace for it too. |
Would you be interested in exposing this as a D3 plugin? I've created a repository at d3/d3-plugins, and I could give you push access to submit your code there. To help you get started, I made some scaffolding of a d3.cie plugin to show you what I was imagining; you're of course welcome to propose an alternative structure, but I think it could fit in nicely. |
Yeah sure that looks good, will see how it works out but certainly makes sense. |
Great! I just gave you push privileges. Let me know if you want a hand. |
I combined your code with @jheer's earlier implementation of Lab color and it is now available as the d3.cie plugin. Here's an example demonstrating Lab and LCH interpolation. If you want to make any edits, go ahead, you have the powah! |
Will find some time to look at this soon! Been tied up in other projects but its not forgotten! |
Main thing that would be very helpful if people plan to start using this is some kind of gamut mapping algorithm. Otherwise, they’re going to do LCh interpolation from one bright color to another, and end up with all kinds of weird artifacts along the way. Otherwise, it’s nice that D3 is trying to put some better color spaces in. :-) |
Here is a patch for adding CIE Lab colourspace to d3.
There is a gist up http://bl.ocks.org/1958838 showing the improved perceptual colours for brighter and darker, will add some more for the hues.