16 ms·
HSLuv, a developer friendly perceptual color space
- leeoniya 7y ago> HSLuv is already available for many languages btw, the JS port is not perf-optimized (it's a straight compilation from haxe to js). i hand-ported the C version [1] locally that avoids heap-allocating any objects or arrays, which makes it about 40% faster. i'm hoping it gets to replace the "official" js port at some point, but i still need to run it through all the tests [2]. if anyone is interested in helping out with this (i'm tight on time right now), i'll publish it. initial benchmark of 100k random RGB triplets completes in 100ms in Chrome 80 and 60ms in Firefox 73, on a pretty average Core i5-7500T @ 2.70GHz. 1M triplets is 680ms in chrome and 421ms in firefox. the official JS port gets 934ms in Chrome and 545ms in Firefox for 1M triplets. For reference, a typical jpeg image contains < 300k unique colors. [1] https://github.com/hsluv/hsluv-c https://github.com/hsluv/hsluv-c [2] https://github.com/hsluv/hsluv-c/blob/master/tests/scripts/snapshot-rev4.json https://github.com/hsluv/hsluv-c/blob/master/tests/scripts/s...
- kuon 7y agoThis is great. I have to admit I usually "bake" my colors when using JS so I have not been hit by the performances, but if it can be done in a performent way, it can open new applications in the browser.
- tobr 7y agoNot sure how much help I would be, but if it’s any encouragement I would very much appreciate a “real” JS version. I looked at the JS version of HSLUV just the other week and was bummed that it was compiled from Haxe.
- throwaway3157 7y ago> was bummed that it was compiled from Haxe Why do you need a "real" JS version? Is it that you want to be able to read/edit from a human-source, rather than a Haxe-compiled source (which I assume is less legible)?
- lioeters 7y agoThat new JS-port of HSLuv C sounds great. Would love to see it published!
- microcolonel 7y agoAs far as testing goes, can't you just test all the colours? the space is pretty small. It should take something like less than 16 seconds in total per implementation, in each direction.
- dllu 7y agoI am a big fan of HSLuv and I use it for generating colourschemes for lidar point clouds: https://daniel.lawrence.lu/public/colortransform/#0_2584_964_49_6_2624_722_363_10_3248_906_559_15_415_961_731 https://daniel.lawrence.lu/public/colortransform/#0_2584_964... which is used for videos such as this: https://www.youtube.com/watch?v=eNt8D1mfwwo https://www.youtube.com/watch?v=eNt8D1mfwwo
- somishere 7y agoYour link broke my back button :/
- dllu 7y agoSorry about that. Fixed the link now.
- nja 7y agoThe amount of detail in that video is amazing. I noticed it can partially see through chain link gates -- neat!
- wpietri 7y agoThat's very cool! Could you explain a bit about what the colors mean? I'm especially intrigued by the painted road markings, which are clearly visible.
- dllu 7y agoThe colours are based on lidar intensity, i.e. how much light is bounced back from a surface. This depends on the reflectivity. That's why it can see lane markings and even murals on the wall: https://www.youtube.com/watch?v=a0-JaMGivX4 https://www.youtube.com/watch?v=a0-JaMGivX4
- wpietri 7y agoAh, thanks. So the colors are an aesthetic choice? There's no more information than one might get from greyscale? (Which is a fine thing; I love the colors.)
- boulos 7y agoInteresting! I hadn't heard of HSLuv. The original writeup / blog post [1] seems more informative though on "why" (hsluv.org is not a very interesting landing page). I'm a little sad (disclosure: co-author) that we didn't make oRGB [2] more popular. Perhaps we should put some source code online? [1] https://www.boronine.com/2012/03/26/Color-Spaces-for-Human-Beings/ https://www.boronine.com/2012/03/26/Color-Spaces-for-Human-B... [2] https://www.cs.utah.edu/~bratkova/research/projects/orgb/orgb.pdf https://www.cs.utah.edu/~bratkova/research/projects/orgb/org...
- jake-low 7y agoThis is a great paper! Thank you for sharing it. I'm not an expert by any means in color theory, but I found the paper both accessible (great diagrams!) and compelling.
- tommysavaria 7y agoI was curious to see how oRGB worked in practice so I made some code to test this, and uploaded to a JS fiddle: https://jsfiddle.net/phv7x39q/1/ https://jsfiddle.net/phv7x39q/1/ It is a very naive implementation, more work could be put in optimizing it. Once I got around to fiddling with it I understood what the paper explained. I'm not new to colorspaces or matrix transformations but it is hard sometimes to grasp the concept from the paper.
- patrec 7y agoOut of curiosity: when you go full throttle on red yellow, dark <-> light goes from red to orange to yellow. Is that really as it is meant to be? I'd (intuitively) expect to be able to go from orange to brown by adjusting the dark/light dimension.
- jes5199 7y agoI think you have a bug - the rotation is supposed to be in the opposite direction if the red-green value is below zero. The paper doesn't make that very clear.
- qwerty456127 7y agoGreen certainly looks darker than pink and blue at some point.
- kuon 7y agoYeah, it's not perfect, and I suspect we don't see colors the same way (monitor not calibrated the same way, and even our vision might be different), but it is "good enough" to avoid common pitfalls like having white text on yellow.
- tobr 7y agoMaybe someone in this thread would have an answer to this question: how do you interpolate between two colors in HSLUV? Just interpolating each parameter doesn’t give the right result, since eg mixing two saturated complementary colors would create an equally saturated color, rather than some shade of gray. Converting to CIELUV and mixing there doesn’t seem safe since I don’t think it’s a “convex” color space; you run the risk of ending up with colors that can’t be reproduced properly on a screen.
- kuon 7y agoBy interpolating, you mean like given two colors, you want to generate the intermediate gradient colors, like on this article[1]? If that's the case, I don't see why interpolating two saturated colors would provide a shade of gray. Can you clarify? [1]: https://www.alanzucconi.com/2016/01/06/colour-interpolation/ https://www.alanzucconi.com/2016/01/06/colour-interpolation/
- tobr 7y agoYeah, basically build a linear (whatever that means in a polar color space) gradient between two colors. If you interpolate a bright red and bright cyan (complementary colors), the midpoint would be gray in most color spaces. You can try it in your link. But in polar color spaces (like HSLUV and most of the ones starting with H) if you just lerp each of the numbers you have to pick a direction for the hue, and your cyan—red has to pass through a saturated green, yellow or blue, magenta. That rainbow effect can be nice but doesn’t feel linear. It also creates discontinuities when you change a color stop enough.
- mark-r 7y agoHere's a comparison between different methods of creating a gradient. https://stackoverflow.com/a/49321304/5987 https://stackoverflow.com/a/49321304/5987
- kuon 7y agoYes, now I see what you mean. Yeah HSLuv is not good for that. The SO answer @mark-r pointed gives a good information. Gradients are complicated beasts, and are often rendered wrong, even by popular softwares like browsers.
- Tade0 7y agoSomewhat related: A friend of mine designed a color palette for terminals based on the Solarized set, but with some improvements: https://github.com/jan-warchol/selenized https://github.com/jan-warchol/selenized
- pansa2 7y agoIsn’t CIELUV more-or-less deprecated now, in favour of CIELAB? Is there a reason that HSLuv is based on the former (and isn’t “HSLab” instead)?
- mark-r 7y agoI've never figured out why LAB and LUV both exist, they were created around the same time to solve the same problem. LAB is definitely more popular though.
- hug 7y agoCIE recommend the use of LAB for paints/dyes/surfaces, and LUV for displays. I don't know why. I just know they do. If I had to guess, it would be that LUV is designed for additive mixing, and LAB is not, but that is a guess educated by some dimly remembered early highschool physics along with 4th grade art lessons.
- mpetroff 7y agoThis is a common misconception; both were recommended because they performed equally well on available data at the time [1]. While CIELUV does have the advantage that additive mixtures fall on straight lines in its chromaticity diagram, it does poorly at predicting color differences and has a flawed adaptation transform, so CIELAB is generally preferred. [1] https://doi.org/10.1002/col.5080150308 https://doi.org/10.1002/col.5080150308
- deltron3030 7y agoAB coordinates are a bit unintuitive, it's easier to visualize hues around a circle and have separate values for luminance and chroma, that's why people who work with color usually prefer LCH/HCL (Luminance, Chroma, Hue). Chroma values in LCH differ between Hues, because each Hue has a different potential and max value. That's where HSLuv comes in, where chroma is a percentage value and therefore relative to the Hue, instead of an absolute one. This gives HCL similar usage ergonmics like HSL, thus the name HSLuv.
- jordansmithnz 7y agoTangential - this reminds me of a tricky bug I once fixed. I had this code that lets you choose a brighter or darker variant of a color palette, and initially bright yellow looked awfully close to white, so I decided to do this conversion through CIELAB (similar to HSLuv). Some unrelated code was storing these colors in the cloud using hex format, and clients would sync these colors back and forth with the cloud. Usually, everything worked great. I had no problems, however a couple of users started emailing to complain that their colors had ‘disappeared’! As in - the stored colors had become transparent. I spent at least a few hours auditing syncing code, but found nothing. A few weeks later I stumbled on the issue by chance: if you select dark green (this specific color configuration only), the color would eventually become transparent. The thing is - some platforms (e.g. iOS) support wide color, which use RGB values outside the 0 to 1 range. Green would go through the CIELAB brightness conversion, and come out with a negative number for one of the RGB values. This is OK, until you convert it to hex and send it to the cloud for syncing... naive color -> hex conversion will freak out with negative numbers. This got sent to the cloud, and later on, the cloud would send this back to the client, which would use it as a source of truth (and so dark green colors would disappear). The fix was to write a less naive hex converter. This was a few years back, perhaps by now most color -> hex libraries consider this case.
- smohare 7y agoThis sounds more like a fundamental misunderstanding of color spaces (and gamuts) than anything.
- jordansmithnz 7y agoDo you mind explaining that? If you increase the brightness of a color space like RGB or HSL, the perceived brightness color increase is different depending on hue. This is why CIELAB was used, because like the linked HSLuv color space, you can increase brightness across hues with the same perceived brightness shift. The fact that CIELAB can covert to RGB values outside the usual range is fine, e.g. negative values are fine in wide RGB color space.
- 7y ago
- sberder 7y agoI'm really not a specialist in color theory but have been looking for a library that could consistently return colors for multi charts with no defined number of lines. Most color palettes are a set size (5, 6, 8 colors) but I currently need to chart things with an unknown number of lines. Any suggestion from the mind hive?
- kevin_thibedeau 7y agoRotate hues with an increment of phi (1.618...). It maximizes average distance between colors. It is discussed at the end of the sinebow article: https://basecase.org/env/on-rainbows https://basecase.org/env/on-rainbows
- infogulch 7y agoThat's a neat solution, the most irrational number strikes again!
- sberder 7y agoVery much appreciated, I knew I'd get a perfect answer!
- mark-r 7y agoI love the Sinebow! It's a natural solution to a problem nobody ever talks about - the colors made by combining two primaries are unnaturally bright compared to a single primary. The way our monitors work, those colors emit twice as many photons. That's OK for yellow because we expect it to be bright, but magenta and cyan just look too garish.
- azhenley 7y agoI really like this. I’ve been working on a retro game for my students that only allows for 256 colors. I was planning on using the 216 web safe colors, but I think using a perfectly spaced out set of 256 colors using HSLuv would be more logical. Any other ideas?
- jmiskovic 7y agoWeb safe colors are completely useless for graphics. Really poor choice of colors. 256 is far too many to pick from :) People do their best work when they are under severe constraints. I would recommend a palette that was put together manually without algorithms because someone made sure that colors actually fit well together. My go to source for such project is this site: https://lospec.com/palette-list/ https://lospec.com/palette-list/
- neetrain 7y agoIf you want a real retro NES feel, consider using NES' original 54-color palette. It lacks deep red and pale orange (suitable for human skins), so the developer of Shovel Knight added 4 colors to it. https://yachtclubgames.com/2014/07/breaking-the-nes/ https://yachtclubgames.com/2014/07/breaking-the-nes/ https://lospec.com/palette-list/shovel-knight-nes https://lospec.com/palette-list/shovel-knight-nes
- gravitystorm 7y agoI use HSLuv for designing our maps at Thunderforest. The map stylesheet language we use is CartoCSS, and it has built-in support for HSLuv since 2016. https://cartocss.readthedocs.io/en/latest/language_elements.html#color https://cartocss.readthedocs.io/en/latest/language_elements.... I can really recommend using HSLuv for this kind of thing. I used to use regular RGB values (like #f2cdaa), but it's hard to make features on the map "a bit less blue" without accidentally changing other properties. For example, changing #f2cdaa to #f2cd88 makes it less blue, but also darker. So a few years ago I switched to using HSL in our stylesheets (and using the HSL tab in the Inkscape colour picker) which makes it easier to reason about the colour changes. But there's still some problems with HSL, as the article describes. For example when choosing road colours, I often want to keep the saturation and lightness the same, but when I make minor roads yellow the change in hue really changes the perceived brightness in HSL. So HSLuv is great for what I do, since I know that if I get the brightness and saturation of the roads the way I want, I can mess around with the hue without any side effects. Or if I like the colour of the forests but want them slightly less saturated, again no side effects when I make changes. The big drawback is that there aren't many colour pickers available in HSLuv, mainly just the one on https://www.hsluv.org/ https://www.hsluv.org/ . I haven't found e.g. HSLuv colour picker plugins for Inkscape or the GIMP yet.
- jpxw 7y agoThe "outdoors" demo image on https://www.thunderforest.com/ https://www.thunderforest.com/ is literally 2 minutes away from where I grew up!
- enriquto 7y agoI dislike strongly the look and feel of most Thunderforest maps. It may look "modern" but when you want to actually read a map, having light green symbols on a slightly lighter green background is ridiculous.
- monokai_nl 7y agoColors are hard. Mixing colors is harder. Yesterday I launched a new tool [1] to automatically create pleasing gradients aimed at web devs. It uses ideas similar to the ones described in the article. But the hard part with dark-to-light color gradients is determining what's a pleasing darker or lighter variant of a color. There's a lot of subjectivity involved. You cannot objectively determine a certain color that lies "between" two other colors. Anyway, I hope my tool helps with quickly creating a nice CSS color gradient. [1] https://mybrandnewlogo.com/color-gradient-generator https://mybrandnewlogo.com/color-gradient-generator
- Grustaf 7y agoWell written and very interesting article, but I think it would benefit from being more visually pleasing, especially the palette examples! Seeing that it deals with aesthetics....
- 0xdeadb00f 7y agoMaybe tangential, but what a great looking website!