hsluv / hsluv Goto Github PK
View Code? Open in Web Editor NEWHuman-friendly HSL, website and math
Home Page: https://www.hsluv.org/
License: MIT License
Human-friendly HSL, website and math
Home Page: https://www.hsluv.org/
License: MIT License
For saturation 100 quite often I get RGB results with one of the components slightly below zero:
hsluv.hsluvToRgb([171, 100, 55])
//[-3.261485526095953e-13, 0.5825533896631454, 0.5048262083306216]
I've noticed that while working on my HSLuv color picker. As i convert hsluv to float RGB and then back to hex using pex-color/index.js#L305. If I use your hsluv.hsluvToHex
it works correctly.
Test case on runkit https://runkit.com/embed/5s9atejnf98j
I think that is not a very good move as it poses problems for downstream projects. I have added support for husl to downstream projects https://github.com/mapbox/carto and https://github.com/omniscale/magnacarto. There you can specify the colours with husl(...). Now I have to rename that, which requires a major version increase.
At least some communication up-front would have been good, also about the reasons for renaming. I'm now thinking of dropping support again altogether as I'm missing the necessary stability.
I really like the interface of HSL Color Picker.
I would like to have a similar three-slider view for HUSL’s color picker on http://www.boronine.com/husl/, as an alternative to the current slider-and-map view. (I don’t care about the fourth slider, for alpha/opacity, though if you think you would like one, you can include it.)
The slider-and-map view makes it easier to get a high-level overview of the color space. But a triple-slider view makes it easier to vary one dimension without affecting the others (you don’t have to carefully move your mouse only vertically or only horizontally), and easier to preview what colors changing that one dimension would result in (because the resulting color at each point is shown inside the slider).
The new slider controls could be always visible right under the slider-and-map, showing the same information in a different format, or they could be accessible under a separate tab, so that you only see one group of controls at a time.
I have asked the creator of HSL Color Picker about the possibility of using his code, at hsl-picker GitHub Issue #10. Though since you already have a custom color picker, it may well be easier to just extend the code of that.
Once again, I’m filing this issue in this repository because I don’t see any repository for the HUSL website itself. If you are open to other people contributing to the website, I suggest creating a separate repository for it, or including its code in this repository, so that people can submit pull requests for it.
In http://www.hsluv.org/comparison/, the HSL and CIELAB LCh representations seem to be plotted with a reversed Y axis compared to the HSLuv and HPLuv plots. Either the first two need to be flipped, or the latter two, or the difference needs to be acknowledged and explained in the text of that page.
Attempting to require husl.js as a dependency using Browserify results in the following error:
events.js:72
throw er; // Unhandled 'error' event
^
Error: module "stylus" not found from "/Users/rileyjshaw/code/sweep/lib/bower_components/husl/husl.js"
Something like "Contribute"?
Look at the below image:
This was generated by:
As we are adding the same amount to the lightness channel (8), the differences in lightness should appear to be the same. I know this is all subjective, but to me the jump from the second to third colour looks much larger from the first to second.
In darker colours, I don't observe this (jumps seem perceptually uniform to me).
As HSLuv is supposed to be perceptually uniform, I thought this wasn't supposed to happen, at least to this extreme extent.
So I'm wondering if there's anything that can be done about this? Or is this a limitation of the system? Or am I misinterpreting something?
On this line I find myself confused
for (c in 0...3) {
var m1:Float = m[c][0];
m
is an array with three rows. Why is that range four positions?
On porting to typescript I had to change this bound to 2. I can't tell if this is a bug that haxe
is being graceful about, or if I'm just missing something and about to look dumb
Hey @boronine and team,
what is your opinion on having a dedicated JS implementation instead of generating code from Haxe? At the top of my head, I can think of the following reasons:
func([a,b,c])
and func(a,b,c)
)
nix
and makeNodePackage
?
I'm not familiar with Haxe so please correct me if you disagree with any of these points. I would also volunteer to work on the JS implementation if there are enough votes for it.
In the color picker at http://www.boronine.com/husl/, it would be nice if we could directly edit the numbers next to the “H”, “S”, and “L” labels, in addition to editing them by dragging the circle on the hue-saturation map and by dragging the lightness slider.
The numbers should also be styled like a text box, similar to the current hex code text box
, so that the user knows that they are editable.
Changing the numbers in the HSL text boxes would also change the position of the controls, just like HSL Color Picker does it.
Ideally, you would be able to edit any text box representing the color, including the hex code and the RGB values. For example, if the output hex code is edited to another valid hex code, the color should be updated, and its HUSL HSL values should be displayed in their text boxes, and the controls updated. HSL Color Picker supports this too.
The advantage of allowing direct editing is that it’s easier to type a number that you know you want than to carefully drag the mouse to the correct horizontal or vertical position. I once used the website color picker to generate some colors for a game. I was trying to generate different-hued families of colors with different saturations. When I had written the hex codes for all the light colors, it was a little difficult to move the map circle to the exact same horizontal position to get darker versions of the same hues. If I could have typed “225” into the hue text box, that would have been easier.
At the moment the sliders seem to lose a lot of precision needlessly, which results in an accuracy loss. If I set the saturation to 100, the lightness to 50, and move the hue slider to 73.4 (#887700) and I hold the left mouse button and move my mouse ONE PIXEL to the right, the next value becomes 75.7 (#867800).
A VERY brief glance over the code didn't make me sure where this comes about, so I'll just speculate and assume that this comes about due to either:
Either of these seems problematic.
Also, if you want to go really crazy, redo the picker so it does what Adobe does here:
https://color.adobe.com/create/color-wheel/
but in HSLuv.
(Sorry about my poor English)
Line 13 in 4b68049
Here, it says 17 digits, but the numbers below is obviously less than 17 digits. Why?
Oddly, in the C version, all the numbers are precise enough:
https://github.com/hsluv/hsluv-c/blob/498de4d9ce7a33933e9252fd3c87b75244215005/src/hsluv.c#L44
I guess the Haxe version got the precision wrong, and caused all generated code (Python, etc.) not precise enough? Does the numbers in the C version right?
I noticed the website has a hue picker, and it looks like it's displaying HSL values along with a hex. Is this slider input being used to produce HUSL at all? It wasn't clear to me beyond the visual colour space (chroma?) changing and the dot for colour moving through it. I wanted to use this library but it didn't seem like it was friendly for stepping through the hues, there doesn't seem to be documentation on it's value range? When trying the Lua version out I was getting hue values all over the place as I moved through the hues incrementally:
Progressively moving along the hue range from 0 to 359.5
6.7535548210144
636.54663085938
1390.5018310547
3776.076171875
6971.8715820313
5463.1713867188
1969.6057128906
336.37377929688
husl/huslp to rgb function seems to convert the colour fine. But I guess there isn't a programmatic way to cycle through the hue like with HSL? Perhaps a function could be used for this?
Does it need to be another file in the package? Does it need to have .mjs
extension?
The husl pastrel variant outputs a out of bounds saturation value.
> husl.p.fromRGB(0, 0, 0.5)
[ 265.87432021817733, 513.4126968442829, 8.646890129976928 ]
Thank you
Is it even possible?
Sometimes you need to do color manipulation on the gpu for performance reasons.
This sort of export is bad practice for browser-based consumers:
var root = {
"hsluvToRgb": hsluv.Hsluv.hsluvToRgb,
"rgbToHsluv": hsluv.Hsluv.rgbToHsluv,
"hpluvToRgb": hsluv.Hsluv.hpluvToRgb,
"rgbToHpluv": hsluv.Hsluv.rgbToHpluv,
"hsluvToHex": hsluv.Hsluv.hsluvToHex,
"hexToHsluv": hsluv.Hsluv.hexToHsluv,
"hpluvToHex": hsluv.Hsluv.hpluvToHex,
"hexToHpluv": hsluv.Hsluv.hexToHpluv
};
Would help browser-based solutions by allowing us to only import the functions we require, ala require('hsluv/rgbToHsluv')
.
Great work!
I saw in RunTests
and Snapshot
that they use Sys
which isn't on javascript, thus Sys.exit
and Sys.stdout
doesn't work at all.
Maybe adding a compile-time define to use alternatives or JS could make work, like using js.Browser.console.log
on browsers and its equivalent on Node.JS.
E.g.:
→ husl.fromHex('#ffffaa')
[ 85.87320306736065,
100.1472012813039,
98.30585954113286 ]
On the http://www.hsluv.org/ homepage, there's an interactive color "wheel".
The outer circle presumably represents maximum saturation in the HSL colour space, but I have no idea what the smaller circle could mean.
Any hints? Sorry for the n00bness.
This is important in order to use it with bower.
Thanks.
For Mac users unfamiliar with Nix, our build system is unapproachable due to #61. We must make it possible for such a user to configure an HSLuv build quickly.
Ideas:
Whatever the solution, it needs to be clearly explained in the README.
The interactive gamut widget is upside down. (The yellow primary is close to 90°.)
Pretty sure you've got a division by zero error in conv.xyz.luv
.
conv.xyz.luv = function(tuple) {
var L, U, V, X, Y, Z, varU, varV;
X = tuple[0], Y = tuple[1], Z = tuple[2];
varU = (4 * X) / (X + (15 * Y) + (3 * Z));
varV = (9 * Y) / (X + (15 * Y) + (3 * Z));
L = Y_to_L(Y);
if (L === 0) {
return [0, 0, 0];
}
U = 13 * L * (varU - refU);
V = 13 * L * (varV - refV);
return [L, U, V];
};
If X
, Y
, and Z
are 0, or that equation sums to 0, the denom will be 0. I think moving the L === 0
check above the varU
/varV
computation will fix that.
It doesn't error out since JS just returns NaN
but it's a fatal error in PHP which I'm trying to port.
In the color picker at http://www.boronine.com/husl/, the “Chroma” label is confusingly placed.
It is right next to, and horizontally aligned with, the sun icon that is part of the brightness slider. That visual placement made me think, for the first 10 minutes of using the color picker, that “chroma” meant the brightness of the color – that chroma was controlled by the slider. This was reinforced by the fact that the chroma usually changed when I dragged the slider. Only later did I realize that the slider controlled Lightness, and the chroma meant the absolute saturation, which the color picker does not provide a direct way to manipulate.
Some rearrangement of the picker controls and labels should be possible to prevent this confusion, and possibly better visually link each of the controls to the H, S, and L values. The Chroma label should be laid out so that it is clear that it is additional information about the current color, but unrelated to either the slider or the 2D color map control.
I’m filing this issue in this repository because I don’t see any repository for the HUSL website itself.
...
complete with tests.
lahwran/pin@9f18fad (impl), and lahwran/pin@db89dfa (which has a bunch of other stuff too, but also tests.)
I did this because it said the java port was unfinished. Also because it was fun.
I'm trying to get the C version running on an Arduino. I've made a couple of small tweaks to get code to compile: removing the C++ includes in the header file, and changing the name of the "round" function to "roundHsluv" to avoid name conflict. The following test program:
#include "husl.h"
void setup() {
float r, g, b;
Serial.begin(9600);
HUSLtoRGB(&r, &g, &b, 0.0, 100.0, 50.0);
int red = 255*r;
int green = 255*g;
int blue = 255*b;
Serial.print(F(" red: "));
Serial.print(red);
Serial.print(F(" green: "));
Serial.print(green);
Serial.print(F(" blue: "));
Serial.println(blue);
}
Produces the output: red: 233 green: 0 blue: 100, however, I expect the output to be red: 255 green: 0 blue: 0
I'm wondering if the problem is 16-bit integers on the Arduino? Can someone help me get this up-and-running? Thanks.
The text next to the plot on husl-colors.org states "To the left you can see CIELUV", however this is not entirely accurate. It shows a normalized version of CIELUV, which is not immediately apparent.
It might be useful to (have an option to) normalize the view to max overall chroma.
Looking at this example from the site:
If I were going to name these colors, I'd probably go: red, orange, yellow, green/chartreuse, green/cyan, cyan, cyan, blue, violet/lavender, magenta.
In other words, the 5th, 6th, and 7th all look very similar to me. Staring at them, I almost have trouble distinguishing their bars. This isn't the case for the other colors in the spectrum. Especially for the last three, I can see sharp, clearly distinguished colors.
This isn't just on the example page either; I've used HSLuv in projects, and noticed that it's harder to distinguish values in that range before.
Is this something subjective and I'm just observing it differently? Is this an artifact of CIELUV? An artifact of monitor color limitations? Or a problem with HSLuv?
Sorry if this is naive; I know very little about color theory besides what I've read about online over the years. But it's always bothered me.
Thanks!
I'm attempting to port to typescript.
In running your tests, I am seeing extremely small numeric drift (usually on the order of 10-15 or smaller.)
I haven't really dug around, but I suspect that Typescript is juggling the math in a way that screws with IEEE numeric precision's edges.
Are deviations that small considered acceptable?
Hello.
I tried to use the lib in a simple Lua project but I quickly went against a design issue with the current API : Lua's table indexes start at 1, whereas almost the rest of the world, including Haxe, starts at 0. So a classic Haxe array will be a bit weird to access from Lua as it might induce code such as manually setting the 0th element instead of directly using an array.
This is almost an edge case, so I was wondering if wrapping or conditionnal compilation would allow us to offer to lua users a module easily useable without a weird interface.
Honestly, I'm more suggesting this because I want to play around with it than because I actually want to use it for a real project. It might be handy in cases where you want to experiment with different hues of not-very-saturated colors.
It'd be neat to have a version of HSL with no chroma distortion at all. I.e., one that only includes a much smaller range of chroma, such that you can't actually access a color with a chroma unattainable with another hue for the same lightness value. It would require limiting the output to a very desaturated range of the visible color spectrum, but it'd be kind of neat to play with, I think.
Actually, now that I think of it, I guess you can attain pretty much the same effect by hovering around CIELCHuv(x,25~60,z).
I wanted to update an older library of mine, husl-harmony, to the newer math, and newer tooling.
I went to look at your implementations list because the Haxe approach isn't convenient under Typescript, to see if there was a native typescript one.
There wasn't, so I wrote one, under the community standard -ts
name.
In trying to publish the completed product, I learned that @gfmio already did, and already published under the standard name, but did not get it added to your site.
His and my implementation aren't actually the same, and both have advantages and disadvantages.
As a result I published mine as @stonecypher/hsluv.ts
instead of hsluv-ts
.
Please consider adding both the hsluv-ts
and @stonecypher/hsluv.ts
implementations to your list. Thank you.
What kind of approach is necessary to convert between HSLuv and HSV? is it a linear conversion?
I'd like to build a color wheel where the user can change hue, and always get the most saturated and vibrate version of that hue.
This is different than lightness, since the "most vibrant" color have different lightnesses depending on which hue we're talking about.
There are lots of attempts to convert between the two, but I'm not sure what the correct approach would be, and I was wondering if some people in this community could share some thoughts on the subject :)
Husl started outputting uppercase letters in the hex output instead of lowercase ones as of 6.0.3. Something like that is strange to happen for a patch release. It breaks some tests downstream at https://github.com/mapbox/carto.
I suggest to either restore the old behaviour or change 6.0.3 to 6.1.0.
HSLuv uses Nix extensively to build the website as well as various packages. There exist some workarounds to get it to work on Catalina. We will wait for an official solution from the Nix project. If no solution is made we can consider using Docker or some other build system with better cross-platform support.
Discussion: NixOS/nix#2925
Also noted by @roryokane here: #60
When I view http://www.hsluv.org/ in Firefox, the text in each color picker text field is unreadable because its edges are cut off:
The browser inspector tells me that this is caused by this CSS rule from min.min.css
, which applies to those <input>
s:
textarea, input, select {
padding: 8px;
border: 1px solid #ccc;
}
When I disable the padding
rule using the inspector, the text fields are fixed:
It’s not obvious to me how to fix the problem, because website/static/css/main.css
contains no such padding
rule.
At the moment, the hsluv
javascript package publishes with many functions that aren't exposed publicly (they are already present in the compiled file, but left out of the export file).
I would like to expose these so that I can update the color-space
npm library from husl
to hsluv
.
Functions:
hsluvToLch, lchToHsluv
hpluvToLch, lchToHpluv
rgbToXyz, xyzToRgb
rgbToLch, lchToRgb
luvToXyz, xyzToLuv
lchToLuv, luvToLch
Hello, i really love this concept but i fail to find any sass implementation or working alternative. Have you any clue for how to make this work in plain css via sass? Thanx.
I'm trying to convert an RGB color to HSLuv and then turn it back into RGB.
the color in question is rgb(0,167,135)
When converting back from Hsluv to RGB, the value for "RED" is not consistent, in fact is kind of weird because it contains letters.... I'm getting -9.431233571888242e-14
This is the code Being executed
<script src="/public/js/hsluv.min.js"></script>
<script type="text/javascript">
var percentageFrom255 = p255 = function(num){
return num/255
}
var green = [0,p255(167),p255(135)];
// this is equivalent to [0, 0.6549019607843137, 0.5294117647058824]
var greenHsluv = hsluv.rgbToHsluv(green);
console.log('green is: ', green, ' & in HSLUV: ', greenHsluv, ' & back in RGB: ', hsluv.hsluvToRgb(greenHsluv) );
/* this outputs:
green is: (3) [0, 0.6549019607843137, 0.5294117647058824]
& in HSLUV: (3) [162.74543122553402, 99.99999999999123, 61.1201850735859]
& back in RGB: (3) [-9.431233571888242e-14, 0.6549019607843142, 0.5294117647058815]
*/
</script>
All the other values (for Green and Blue) match almost exactly, and I've tried with a different color and everything works as expected. It's just for this color I'm not getting right the Red hue (witch should return 0
)
Hi!
The current HSLuv logo seems a bit too simple to me. I have played with some ideas on a candidate for a follow-up logo that I would like to share now. If none of these appeal to you, I won't be offended — it's just an idea.
The font is Helvetica Neue.
Hi,
I recently completed the Haskell port.
The candidate (not official/finalized yet) release is on Hackage at https://hackage.haskell.org/package/hsluv-haskell-0.1.0.0/candidate.
Source is at https://git.modalduality.org/hsluv-haskell/tree/.
What else needs to be done (other than finalizing the Hackage release)?
Hi,
I'm working on a Haskell port, didn't see any others. This is a great project, thanks for the work!
I'm wondering about this code:
// var min:Float = Float.MAX_VALUE;
var min:Float = 1.7976931348623157e+308;
for (i in 0...2) {
var length:Float = Geometry.distanceLineFromOrigin(bounds[i]);
min = Math.min(min, length);
}
found at https://github.com/hsluv/hsluv/blob/master/haxe/src/hsluv/Hsluv.hx#L92.
Is the first assignment to min
meant to be an upper bound on a double-precision floating point value?
Since the number of iterations is at least 1, why not just Math.min(Geometry.distanceLineFromOrigin[0], Geometry.distanceLineFromOrigin[1])
? Or with keeping the same code structure, min:Float = POSITIVE_INFINITY;
?
This is especially useful for users of IDEs like Intellij.
Hi! First I'd like to say I really like HSLuv! it's way better than HSL and more practical than CIELUV.
There is only one nearly-unfixable problem: CIELUV does not guarantee constant hue when changing saturation.
This has two effects:
Problem number 2 is most noticable with blues.
If you look at #0000FF blue and slide it to about 40% saturation you get #454587, which appears too purple (subjectively, I think it should be more like #34477f)
Unfortunately, when sliding with the lightness-slider, HSLuv does a lot of sliding towards or away from the center in order to keep the color in gammut. This means that for HSLuv chages in lightness can ALSO change the hue, so problem number 2 is an even bigger problem for HSLuv than for CIELUV.
For example if you take #0000FF and change its lightness value to 60, you get #8383ff, which again looks too purple.
I still think HSLuv is the most practical system as of yet, but it has this almost-unsolvable problem.
I hope I wasn't too much of a downer,
Snipstruis
(ps this probbably also explains issue #41)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.