Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Darken or lighten a color in matplotlib

Say I have a color in Matplotlib. Maybe it's a string ('k') or an rgb tuple ((0.5, 0.1, 0.8)) or even some hex (#05FA2B). Is there a command / convenience function in Matplotlib that would allow me to darken (or lighten) that color.

I.e. is there matplotlib.pyplot.darken(c, 0.1) or something like that? I guess what I'm hoping for is something that, behind the scenes, would take a color, convert it to HSL, then either multiply the L value by some given factor (flooring at 0 and capping at 1) or explicitly set the L value to a given value and return the modified color.

like image 634
8one6 Avatar asked Jun 11 '16 15:06

8one6


People also ask

How do you darken a hex color in python?

set_hls_values() takes a color as RGB-Tuple, HEX or HTML-name and lets you manipulate the hue, lightness and saturation. The scaled lightness should be between 0 and 1 , where 1 < scale increases the lightness and 0 ≤ scale < 1 darkens the color.

How do you darken RGB colors?

For shades, multiply each component by 1/4, 1/2, 3/4, etc., of its previous value. The smaller the factor, the darker the shade. For tints, calculate (255 - previous value), multiply that by 1/4, 1/2, 3/4, etc.

How do I shade an area in Matplotlib?

You can use ax. axvspan , which apparently does exactely what you want. For better results, usa an alpha value below 0.5, and optionally set color and edge-color/width. If you want the shading to be in a different orientation (horizontal instead of vertical), there is also the ax.


2 Answers

Here is a function from my gist to lighten any color that I think will work with any color format known to matplotlib. I think setting an amount > 1 might darken too.

def lighten_color(color, amount=0.5):     """     Lightens the given color by multiplying (1-luminosity) by the given amount.     Input can be matplotlib color string, hex string, or RGB tuple.      Examples:     >> lighten_color('g', 0.3)     >> lighten_color('#F034A3', 0.6)     >> lighten_color((.3,.55,.1), 0.5)     """     import matplotlib.colors as mc     import colorsys     try:         c = mc.cnames[color]     except:         c = color     c = colorsys.rgb_to_hls(*mc.to_rgb(c))     return colorsys.hls_to_rgb(c[0], 1 - amount * (1 - c[1]), c[2]) 

EDIT: Indeed, it does darken as well as lighten:

import matplotlib.pyplot as plt import numpy as np  xs = np.linspace(-1, 1, 100) plt.plot(xs, 0 * xs, color='b', lw=3) plt.plot(xs, xs**2, color=lighten_color('b', 0.4), lw=3) plt.plot(xs, -xs**2, color=lighten_color('b', 1.6), lw=3) 

image with example of darken and lighten

Edit 2: Removed un-needed numpy dependency in the function.

Edit 3: Function modified with improvements from @FLekschas

def adjust_lightness(color, amount=0.5):     import matplotlib.colors as mc     import colorsys     try:         c = mc.cnames[color]     except:         c = color     c = colorsys.rgb_to_hls(*mc.to_rgb(c))     return colorsys.hls_to_rgb(c[0], max(0, min(1, amount * c[1])), c[2]) 
like image 140
Ian Hincks Avatar answered Sep 22 '22 03:09

Ian Hincks


Using only colorsys which is part of the python standard library it is possible to scale the lighntess with just two lines of code

If you still want the option to pass non rgb values like colornames or HEX you can simply use matplotlib.colors.ColorConverter.to_rgb("#ff0000").

This method scales the lightness of an rgb color

import colorsys  def scale_lightness(rgb, scale_l):     # convert rgb to hls     h, l, s = colorsys.rgb_to_hls(*rgb)     # manipulate h, l, s values and return as rgb     return colorsys.hls_to_rgb(h, min(1, l * scale_l), s = s) 

A simple demonstration. For more details have a look at the old example.

import matplotlib import seaborn as sns  color = matplotlib.colors.ColorConverter.to_rgb("navy") rgbs = [scale_lightness(color, scale) for scale in [0, .5, 1, 1.5, 2]] sns.palplot(rgbs) 

enter image description here


Old Answer

There is a Seaborn method, that easily lets you manipulate the lightness. seaborn.set_hls_values() takes a color as RGB-Tuple, HEX or HTML-name and lets you manipulate the hue, lightness and saturation.

The scaled lightness should be between 0 and 1, where 1 < scale increases the lightness and 0 ≤ scale < 1 darkens the color.

from colorsys import rgb_to_hls import seaborn as sns  color = (1.0, 0.0, 0.0)     # RGB  print(f"Input color:    \t Lightness:  {rgb_to_hls(*color)[1]: .2g}\t RGB:  {color}")  rgbs = [] for scale in [0, .5, 1, 1.5, 2]:      # scale the lightness (The values should be between 0 and 1)     lightness = min(1, rgb_to_hls(*color)[1] * scale)      # manipulate h, l, s channel of a rgb color     rgb = sns.set_hls_values(color = color, h = None, l = lightness, s = None)      print(f"Scale factor: {scale: .2g}\t Lightness:  {lightness: .2g}  \t RGB:  {rgb}")     rgbs.append(rgb)  sns.palplot(rgbs) 

In case you want to use other than RGB codes you need to convert your color to RGB. You could use the following command.

color = "red"               # HTML name color = "#ff0000"           # HEX color = matplotlib.colors.ColorConverter.to_rgb(color) 

The returned values are RGB-Tuples:

Input color:        Lightness:   0.5    RGB:  (1.0, 0.0, 0.0)  Scale factor:  0    Lightness:   0      RGB:  (0.0, 0.0, 0.0)  # Black Scale factor:  0.5  Lightness:   0.25   RGB:  (0.5, 0.0, 0.0) Scale factor:  1    Lightness:   0.5    RGB:  (1.0, 0.0, 0.0)  # Unchanged Scale factor:  1.5  Lightness:   0.75   RGB:  (1.0, 0.5, 0.5) Scale factor:  2    Lightness:   1      RGB:  (1.0, 1.0, 1.0)  # White 

enter image description here enter image description here enter image description here enter image description here enter image description here

EDIT:

Thanks @fhgd! I changed the code to actually scale the lightness and not just set it.

like image 30
Night Train Avatar answered Sep 23 '22 03:09

Night Train