Skip to content

Instantly share code, notes, and snippets.

@mathebox
Created April 12, 2015 16:47
Show Gist options
  • Save mathebox/e0805f72e7db3269ec22 to your computer and use it in GitHub Desktop.
Save mathebox/e0805f72e7db3269ec22 to your computer and use it in GitHub Desktop.
Python methods to convert colors between RGB, HSV and HSL
import math
def rgb_to_hsv(r, g, b):
r = float(r)
g = float(g)
b = float(b)
high = max(r, g, b)
low = min(r, g, b)
h, s, v = high, high, high
d = high - low
s = 0 if high == 0 else d/high
if high == low:
h = 0.0
else:
h = {
r: (g - b) / d + (6 if g < b else 0),
g: (b - r) / d + 2,
b: (r - g) / d + 4,
}[high]
h /= 6
return h, s, v
def hsv_to_rgb(h, s, v):
i = math.floor(h*6)
f = h*6 - i
p = v * (1-s)
q = v * (1-f*s)
t = v * (1-(1-f)*s)
r, g, b = [
(v, t, p),
(q, v, p),
(p, v, t),
(p, q, v),
(t, p, v),
(v, p, q),
][int(i%6)]
return r, g, b
def rgb_to_hsl(r, g, b):
r = float(r)
g = float(g)
b = float(b)
high = max(r, g, b)
low = min(r, g, b)
h, s, v = ((high + low) / 2,)*3
if high == low:
h = 0.0
s = 0.0
else:
d = high - low
s = d / (2 - high - low) if l > 0.5 else d / (high + low)
h = {
r: (g - b) / d + (6 if g < b else 0),
g: (b - r) / d + 2,
b: (r - g) / d + 4,
}[high]
h /= 6
return h, s, v
def hsl_to_rgb(h, s, l):
def hue_to_rgb(p, q, t):
t += 1 if t < 0 else 0
t -= 1 if t > 1 else 0
if t < 1/6: return p + (q - p) * 6 * t
if t < 1/2: return q
if t < 2/3: p + (q - p) * (2/3 - t) * 6
return p
if s == 0:
r, g, b = l, l, l
else:
q = l * (1 + s) if l < 0.5 else l + s - l * s
p = 2 * l - q
r = hue_to_rgb(p, q, h + 1/3)
g = hue_to_rgb(p, q, h)
b = hue_to_rgb(p, q, h - 1/3)
return r, g, b
def hsv_to_hsl(h, s, v):
l = 0.5 * v * (2 - s)
s = v * s / (1 - math.fabs(2*l-1))
return h, s, l
def hsl_to_hsv(h, s, l):
v = (2*l + s*(1-math.fabs(2*l-1)))/2
s = 2*(v-l)/v
return h, s, v
@Lywx
Copy link

Lywx commented May 12, 2020

hsl_to_rgb routine is problematic! Please use this!

def clamp(value, min_value, max_value):
	return max(min_value, min(max_value, value))

def saturate(value):
	return clamp(value, 0.0, 1.0)

def hue_to_rgb(h):
	r = abs(h * 6.0 - 3.0) - 1.0
	g = 2.0 - abs(h * 6.0 - 2.0)
	b = 2.0 - abs(h * 6.0 - 4.0)
	return saturate(r), saturate(g), saturate(b)

def hsl_to_rgb(h, s, l):
	r, g, b = hue_to_rgb(h)
	c = (1.0 - abs(2.0 * l - 1.0)) * s
	r = (r - 0.5) * c + l
	g = (g - 0.5) * c + l
	b = (b - 0.5) * c + l
	return r, g, b

@nprghu
Copy link

nprghu commented Dec 15, 2020

Hi! I have a question, for me rgb_to_hsv() is not working. For example, if I put print(rgb_to_hsv(100,0,0)), which should print 0, 100, 100, I got 0, 1, 255. Something is definitely wrong here.

@hugoaboud
Copy link

hugoaboud commented Mar 1, 2021

Hi! I have a question, for me rgb_to_hsv() is not working. For example, if I put print(rgb_to_hsv(100,0,0)), which should print 0, 100, 100, I got 0, 1, 255. Something is definitely wrong here.

The functions takes RGB values in the [0,1] range.

@hugoaboud
Copy link

plz correct l to low at https://gist.github.com/mathebox/e0805f72e7db3269ec22#file-color_conversion-py-L57

Actually, the fix should be on lines 50 and 65, where the variable names 'h, s, v' are used instead of 'h, s, l'. This complies with @Zangwill's answer.

@alexTitakoff
Copy link

File "/Users/alexMac/Projects/Freelance/schemochka-local/app/image2schema_lib/stages/schema_builder/cross.py", line 131, in rgb_to_hsl s = d / (2 - high - low) if l > 0.5 else d / (high + low) NameError: name 'l' is not defined

@alexTitakoff
Copy link

plz correct l to low at https://gist.github.com/mathebox/e0805f72e7db3269ec22#file-color_conversion-py-L57

Actually, the fix should be on lines 50 and 65, where the variable names 'h, s, v' are used instead of 'h, s, l'. This complies with @Zangwill's answer.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment