Skip to content
This repository has been archived by the owner on Jan 12, 2024. It is now read-only.

Implement color luma change function #492

Closed
yvecai opened this issue May 6, 2018 · 6 comments
Closed

Implement color luma change function #492

yvecai opened this issue May 6, 2018 · 6 comments
Labels

Comments

@yvecai
Copy link

yvecai commented May 6, 2018

When dealing with data-driven colors, one often faces plain colors like yellow (255,255,0), red (255,0,0) etc. Cartographically speaking, these color are too saturated and far less than ideal.
My use case is the coloring of crosscountry skiing route relations for OSM, but I guess it’s the same for any route with a color tag.

One could desaturate() and lighten() or darken() the color, however, for some color it’s not satisfactory. For instance, the yellow visibility over a light background is not sufficient. At Opensnowmap, I implemented a while ago a pre-processing that alter the colors luma (see https://en.wikipedia.org/wiki/HSL_and_HSV).

Luma is the Y’ in Y’UV color space, and is defined by Y′601 ≈ 0.30R + 0.59G + 0.11B.
See an example below of the color change made in the Opensowmap pre-processing generating the ski routes style :
deluma
My question is, is this worth it to try to submit a PR implementing a deluma() function in function.js to decrease the luma of a color, or this is out of scope here? What would be a good name for the inverse function to increase luma ?

Below is my actual implementation in python :

def deluma(color,factor):
    # reduce color luma by a given factor. 
    r,g,b,a=(color.r, color.g, color.b, color.a)
    r=int(r*(1-0.3*factor))
    g=int(g*(1-0.59*factor))
    b=int(b*(1-0.11*factor))
    return mapnik.Color(r,g,b,a)
@nebulon42
Copy link
Collaborator

Before talking about the actual function I'm trying to understand why you need it in the first place. You are unsatisfied with the non-uniformity of the lightness of HSL, is that correct? Do you know that carto supports HSLuv (http://www.hsluv.org/) which tries to modify CIELUV to allow the same colour definitions as in HSL. Internally carto uses either HSL or HSLuv, see https://cartocss.readthedocs.io/en/latest/language_elements.html#color. Cf also #354, #453. Some argue that HSLuv is not really a perceptual colour space, but it solves the problem of HSL without the possibility of yielding non-representable colours like in CIELUV.

Would using HSLuv solve your problem without needing this function?

This would avoid the problem of conversions as internally colours are represented as HSL/HSLuv, so you would have to convert to RGB first, then change the luma value, convert back to HSL. Needless to say that there would be a lot of rounding errors.

@yvecai
Copy link
Author

yvecai commented May 6, 2018 via email

@yvecai
Copy link
Author

yvecai commented May 8, 2018

I played a little bit with HSLuv: HSLuv solves the issue of the lightness uniformity when you choose your colors.
However here, I don't choose them, the color are from the OSM contributors, but I'd like to change them to give them a more uniform lightness. The deluma function kind of reduce the lightness range: white become (pinkish) grey, black stays black.

I also figured out that my lightening function is more a whitening function:

 def lighten(color,factor):
     r,g,b,a=(color.r, color.g, color.b, color.a)
     r = int((1-factor)*r + factor*255)
     g = int((1-factor)*g + factor*255)
     b = int((1-factor)*b + factor*255)
     return mapnik.Color(r,g,b,a)

Given a non-chosen set of colors, these two color functions allows to:

  • Solve an issue with the visibility over a white background (white, yellow) (deluma)
  • Reduce saturation (whitening)

I just fiddled with these color change and in the end they give a valid result to my eye, so I would certainly have a hard time to defend the theory behind them :-)
So if if somebody else is seduced, I can add them to cartocss. Otherwise I keep them to me. Another option maybe an example using HSLuv conversion to give as similar result ?

Here is another example on colors sorted by r+g+b :
capture du 2018-05-08 21-40-23

@pnorman
Copy link
Contributor

pnorman commented May 9, 2018

I think data driven colours would be a Mapnik issue, not a Carto one, and suggest closing this issue as out of scope.

I would also not recommend Luma. Convert to a standard perceptual colour space, set the colour properties you want, project to the gamut, and use that colour.

@yvecai
Copy link
Author

yvecai commented May 14, 2018

Hmm, in any case, this works as expected for data driven colors:
[color!='']{line-color:[color];}

But this doesn't:
[color!='']{line-color:lighten([color],50%);}
Error: ../pistes-carto/routes_dyn.mss:23:51 incorrect arguments given to lighten()

And this neither:
[lightness(color) > 100]{line-color: #3B3B3B;}
Error: ../pistes-carto/routes_dyn.mss:27:7 Missing closing ] of filter.

So it seems there is something else to improve before discussing this anyway.

@pnorman
Copy link
Contributor

pnorman commented May 15, 2018

Hmm, in any case, this works as expected for data driven colors:
[color!='']{line-color:[color];}

This translates to Mapnik XML that roughly

<LineSymbolizer stroke="[color]" />

The other things you want are Mapnik issues.

@yvecai yvecai closed this as completed May 15, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants