Algorithm RGB -> HSL
0 <= R, G, B <= 1
0 <= H <= 360
0 <= S, L <= 1
max = MAX( R, G, B )
min = MIN( R, G, B )
1) max = min
h = 0
2) max = R
h = (60 * (G - B) / (max - min) + 360 ) mod 360
3) max = G
h = 60 * (B - R) / (max - min) + 120
4) max = B
h = 60 * (R - G) / (max - min) + 240
L = (max + min) / 2
1) max = min
s = 0;
2) L <= 0.5
s = (max - min) / (max + min) = (max - min) / (2 * L)
3) L > 0.5
s = (max - min) / (2 - (max + min)) = (max - min) / (2 - 2 * L)
Algorithm HSL -> RGB
0 <= R, G, B <= 1
0 <= H < 360
0 <= S, L <= 1
1) L < 0.5
Q = L * (L + S)
2) L >= 0.5
Q = L + S - (L * S)
P = 2 * L - Q
Hk = H / 360
Tr = Hk + 1.0 / 3.0
Tg = Hk
Tb = Hk - 1.0 / 3.0
1) Tr < 0
Tr = Tr + 1.0
2) Tr > 1.0
Tr = Tr - 1.0
3) Tg < 0
Tg = Tg + 1.0
4) Tg > 1.0
Tg = Tg - 1.0
5) Tb < 0
Tb = Tb + 1.0
6) Tb > 1.0
Tb = Tb - 1.0
1) Tr < 1.0 / 6.0
Tr = P + ((Q - P) * 6 * Tr)
2) 1.0 / 6.0 <= Tr < 0.5
Tr = Q
3) 0.5 <= Tr < 2.0 / 3.0
Tr = P + ((Q- P) * 6 * (2.0 / 3.0 - Tr))
4) otherwise
Tr = P
5) Tg < 1.0 / 6.0
Tg = P + ((Q - P) * 6 * Tg)
6) 1.0 / 6.0 <= Tg < 0.5
Tg = Q
7) 0.5 <= Tg < 2.0 / 3.0
Tg = P + ((Q- P) * 6 * (2.0 / 3.0 - Tg))
8) otherwise
Tg = P
9) Tb < 1.0 / 6.0
Tb = P + ((Q - P) * 6 * Tb)
10) 1.0 / 6.0 <= Tb < 0.5
Tb = Q
11) 0.5 <= Tb < 2.0 / 3.0
Tb = P + ((Q- P) * 6 * (2.0 / 3.0 - Tb))
12) otherwise
Tb = P
// r, g, b are [0, 1]
// h is [0, 360)
// s is [0, 1]
// l is [0, 1]
#define RGB2HSL( r, g, b, h, s, l ) /
I_MACRO_BEGIN /
if ( (r) == (g) && (g) == (b) ) /
{ /
(h) = 0; /
(s) = 0; /
(l) = (g); /
} /
else /
{ /
float _max; /
float _min; /
if ( (r) > (g) ) /
{ /
_min = (g) > (b) ? (b) : (g); /
if ( (r) > (b) ) /* r is max */ /
{ /
_max = (r); /
(h) = ((int) (60.0 * ((g) - (b)) / ((r) - _min) + 0.5) + 360) % 360; /
} /
else /* b is max */ /
{ /
_max = (b); /
(h) = (int) (60.0 * ((r) - (g)) / ((b) - _min) + 0.5) + 240; /
} /
} /
else /* (r) <= (g) */ /
{ /
_min = (r) > (b) ? (b) : (r); /
if ( (g) > (b) ) /* g is max */ /
{ /
_max = (g); /
(h) = (int) (60.0 * ((b) - (r)) / ((g) - _min) + 0.5) + 120; /
} /
else /* b is max */ /
{ /
_max = (b); /
(h) = (int) (60.0 * ((r) - (g)) / ((b) - _min) + 0.5) + 240; /
} /
} /
(l) = 0.5 * (_max + _min); /
if ( (l) > 0.5 ) /
{ /
(s) = (float) (_max - _min) / (2.0 - (_max + _min)); /
} /
else /
{ /
(s) = (float) (_max - _min) / (float) (_max + _min); /
} /
} /
I_MACRO_END
#define II_HSL2RGB( p, q, tc ) /
I_MACRO_BEGIN /
if ( (tc) < 1.0 / 6.0 ) /
{ /
(tc) = (p) + ((q) - (p)) * 6.0 * (tc); /
} /
else if ( (tc) < 1.0 / 2.0 ) /
{ /
(tc) = (q); /
} /
else if ( (tc) < 2.0 / 3.0 ) /
{ /
(tc) = (p) + ((q) - (p)) * 6.0 * (2.0 / 3.0 - (tc)); /
} /
else /
{ /
(tc) = (p); /
} /
I_MACRO_END
// h is [0, 360)
// s is [0, 1]
// l is [0, 1]
// r, g, b are [0, 1]
#define HSL2RGB( h, s, l, r, g, b ) /
I_MACRO_BEGIN /
float _p; /
float _q; /
float _hk; /
float _tr; /
float _tg; /
float _tb; /
assert( (h) < 360 ); /
if ( (l) < 0.5 ) /
{ /
_q = (l) * (1 + (s)); /
} /
else /
{ /
_q = (l) + (s) - (l) * (s); /
} /
_p = 2.0 * (l) - _q; /
_hk = (float) (h) / 360.0; /
_tr = _hk + 1.0 / 3.0; /
if ( _tr < 0 ) /
_tr += 1.0; /
else if ( _tr > 1.0 ) /
_tr -= 1.0; /
_tg = _hk; /
if ( _tg < 0 ) /
_tg += 1.0; /
else if ( _tg > 1.0 ) /
_tg -= 1.0; /
_tb = _hk - 1.0 / 3.0; /
if ( _tb < 0 ) /
_tb += 1.0; /
else if ( _tb > 1.0 ) /
_tb -= 1.0; /
II_HSL2RGB( _p, _q, _tr ); /
II_HSL2RGB( _p, _q, _tg ); /
II_HSL2RGB( _p, _q, _tb ); /
(r) = _tr; /
(g) = _tg; /
(b) = _tb; /
I_MACRO_END