HSV/HSL Color Spaces

Intuitive color representations based on Hue, Saturation, and Value/Lightness.

Overview

HSV (Hue, Saturation, Value) and HSL (Hue, Saturation, Lightness) are cylindrical color models designed to be more intuitive than RGB for human color selection. They're commonly used in color pickers and image editing software.

Key Difference:

  • HSV: Value represents brightness (pure colors at V=1)
  • HSL: Lightness represents perceptual brightness (pure colors at L=0.5)

RGB to HSV Conversion

Algorithm

$$ V = \max(R, G, B) $$

$$ C = V - \min(R, G, B) $$

$$ S = \begin{cases} 0 & \text{if } V = 0 \ \frac{C}{V} & \text{otherwise} \end{cases} $$

$$ H' = \begin{cases} \text{undefined} & \text{if } C = 0 \ \frac{G - B}{C} \mod 6 & \text{if } V = R \ \frac{B - R}{C} + 2 & \text{if } V = G \ \frac{R - G}{C} + 4 & \text{if } V = B \end{cases} $$

$$ H = 60° \times H' $$


HSV to RGB Conversion

Algorithm

$$ C = V \times S $$

$$ H' = \frac{H}{60°} $$

$$ X = C \times (1 - |H' \mod 2 - 1|) $$

$$ (R_1, G_1, B_1) = \begin{cases} (C, X, 0) & \text{if } 0 \leq H' < 1 \ (X, C, 0) & \text{if } 1 \leq H' < 2 \ (0, C, X) & \text{if } 2 \leq H' < 3 \ (0, X, C) & \text{if } 3 \leq H' < 4 \ (X, 0, C) & \text{if } 4 \leq H' < 5 \ (C, 0, X) & \text{if } 5 \leq H' < 6 \end{cases} $$

$$ m = V - C $$

$$ (R, G, B) = (R_1 + m, G_1 + m, B_1 + m) $$


Practical Implementation

Python

 1import numpy as np
 2
 3def rgb_to_hsv(r, g, b):
 4    """
 5    Convert RGB to HSV
 6    Input: r, g, b in [0, 1]
 7    Output: h in [0, 360), s, v in [0, 1]
 8    """
 9    v = max(r, g, b)
10    c = v - min(r, g, b)
11    
12    if c == 0:
13        h = 0
14    elif v == r:
15        h = 60 * (((g - b) / c) % 6)
16    elif v == g:
17        h = 60 * ((b - r) / c + 2)
18    else:  # v == b
19        h = 60 * ((r - g) / c + 4)
20    
21    s = 0 if v == 0 else c / v
22    
23    return h, s, v
24
25def hsv_to_rgb(h, s, v):
26    """
27    Convert HSV to RGB
28    Input: h in [0, 360), s, v in [0, 1]
29    Output: r, g, b in [0, 1]
30    """
31    c = v * s
32    h_prime = h / 60.0
33    x = c * (1 - abs(h_prime % 2 - 1))
34    
35    if h_prime < 1:
36        r1, g1, b1 = c, x, 0
37    elif h_prime < 2:
38        r1, g1, b1 = x, c, 0
39    elif h_prime < 3:
40        r1, g1, b1 = 0, c, x
41    elif h_prime < 4:
42        r1, g1, b1 = 0, x, c
43    elif h_prime < 5:
44        r1, g1, b1 = x, 0, c
45    else:
46        r1, g1, b1 = c, 0, x
47    
48    m = v - c
49    return r1 + m, g1 + m, b1 + m

Go

 1package color
 2
 3import "math"
 4
 5type HSV struct {
 6    H, S, V float64 // H in [0, 360), S, V in [0, 1]
 7}
 8
 9func RGBToHSV(rgb RGB) HSV {
10    max := math.Max(math.Max(rgb.R, rgb.G), rgb.B)
11    min := math.Min(math.Min(rgb.R, rgb.G), rgb.B)
12    c := max - min
13    
14    var h float64
15    if c == 0 {
16        h = 0
17    } else if max == rgb.R {
18        h = 60 * math.Mod((rgb.G-rgb.B)/c, 6)
19    } else if max == rgb.G {
20        h = 60 * ((rgb.B-rgb.R)/c + 2)
21    } else {
22        h = 60 * ((rgb.R-rgb.G)/c + 4)
23    }
24    
25    if h < 0 {
26        h += 360
27    }
28    
29    var s float64
30    if max == 0 {
31        s = 0
32    } else {
33        s = c / max
34    }
35    
36    return HSV{H: h, S: s, V: max}
37}
38
39func HSVToRGB(hsv HSV) RGB {
40    c := hsv.V * hsv.S
41    hPrime := hsv.H / 60.0
42    x := c * (1 - math.Abs(math.Mod(hPrime, 2)-1))
43    
44    var r1, g1, b1 float64
45    switch {
46    case hPrime < 1:
47        r1, g1, b1 = c, x, 0
48    case hPrime < 2:
49        r1, g1, b1 = x, c, 0
50    case hPrime < 3:
51        r1, g1, b1 = 0, c, x
52    case hPrime < 4:
53        r1, g1, b1 = 0, x, c
54    case hPrime < 5:
55        r1, g1, b1 = x, 0, c
56    default:
57        r1, g1, b1 = c, 0, x
58    }
59    
60    m := hsv.V - c
61    return RGB{R: r1 + m, G: g1 + m, B: b1 + m}
62}

RGB to HSL Conversion

Algorithm

$$ L = \frac{\max(R, G, B) + \min(R, G, B)}{2} $$

$$ C = \max(R, G, B) - \min(R, G, B) $$

$$ S = \begin{cases} 0 & \text{if } C = 0 \ \frac{C}{1 - |2L - 1|} & \text{otherwise} \end{cases} $$

Hue $H$ is calculated the same way as in HSV.


HSL to RGB Conversion

$$ C = (1 - |2L - 1|) \times S $$

$$ X = C \times (1 - |H' \mod 2 - 1|) $$

$$ m = L - \frac{C}{2} $$

Then use the same $(R_1, G_1, B_1)$ table as HSV, and:

$$ (R, G, B) = (R_1 + m, G_1 + m, B_1 + m) $$


Common Use Cases

HSV

  • Color pickers: Natural for users to select colors
  • Image adjustments: Brightness and saturation controls
  • Computer vision: Color-based segmentation

HSL

  • Web design: CSS hsl() function
  • Lightness adjustments: More perceptually uniform than HSV
  • Color schemes: Easier to create harmonious palettes

Key Differences

AspectHSVHSL
Pure colorsV = 1, S = 1L = 0.5, S = 1
WhiteV = 1, S = 0L = 1, any S
BlackV = 0, any SL = 0, any S
Perceptual uniformityPoorSlightly better
Common useColor pickers, graphicsWeb, design

Important Notes

  1. Not perceptually uniform: Equal changes in HSV/HSL don't correspond to equal perceived changes
  2. Hue is circular: 0° and 360° are the same (red)
  3. Undefined hue: When S = 0 (grayscale), hue is undefined
  4. Use LAB for color math: HSV/HSL are for UI, not color science

Hue Values Reference

  • 0° / 360°: Red
  • 60°: Yellow
  • 120°: Green
  • 180°: Cyan
  • 240°: Blue
  • 300°: Magenta

Further Reading

Related Snippets