Skip to content

Instantly share code, notes, and snippets.

@crowsonkb
Created May 11, 2018 20:29
Show Gist options
  • Save crowsonkb/a58d6a816ffd2c60995e5adf3e7aee6b to your computer and use it in GitHub Desktop.
Save crowsonkb/a58d6a816ffd2c60995e5adf3e7aee6b to your computer and use it in GitHub Desktop.
Converts colors from HSL to RGB and back.
"""Converts colors from HSL to RGB and back."""
import numpy as np
from scipy import optimize
def tstack(a):
"""Stacks arrays in sequence along the last axis (tail)."""
a = np.asarray(a)
return np.concatenate([x[..., np.newaxis] for x in a], axis=-1)
def tsplit(a):
"""Splits arrays in sequence along the last axis (tail)."""
a = np.asarray(a)
return np.array([a[..., x] for x in range(a.shape[-1])])
def hue_to_rgb_once(m1, m2, h):
h %= 1
if h * 6 < 1:
return m1 + (m2 - m1) * h * 6
if h * 2 < 1:
return m2
if h * 3 < 2:
return m1 + (m2 - m1) * (2/3 - h) * 6
return m1
def hue_to_rgb(m1, m2, h):
m1m2h = tstack([m1, m2, h])
return np.apply_along_axis(lambda a: hue_to_rgb_once(*a), -1, m1m2h)
def hsl_to_rgb(hsl):
"""Converts HSL colors to RGB. See
https://www.w3.org/TR/2018/PR-css-color-3-20180315/#hsl-color.
"""
h, s, l = tsplit(hsl)
m1, m2 = np.zeros_like(h), np.zeros_like(h)
m2 += (l <= 0.5) * l * (s + 1)
m2 += (l > 0.5) * (l + s - l * s)
m1 = l * 2 - m2
r = hue_to_rgb(m1, m2, h + 1/3)
g = hue_to_rgb(m1, m2, h)
b = hue_to_rgb(m1, m2, h - 1/3)
return tstack([r, g, b])
def rgb_to_hsl_once(rgb):
def loss(hsl):
rgb2 = hsl_to_rgb(hsl)
return sum((rgb - rgb2)**2)
x0 = np.array([0.5, 0.5, 0.5])
opt = optimize.fmin_bfgs(loss, x0, disp=False)
return opt
def rgb_to_hsl(rgb):
"""Converts RGB colors back to HSL."""
rgb = np.asarray(rgb)
hsl = np.apply_along_axis(rgb_to_hsl_once, -1, rgb)
hsl[..., 0] %= 1
return np.clip(hsl, 0, 1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment