Skip to content

Commit cf7e691

Browse files
committed
new: implement hsv
1 parent 724f022 commit cf7e691

File tree

1 file changed

+101
-5
lines changed

1 file changed

+101
-5
lines changed

colour.py

Lines changed: 101 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
Formats
1010
-------
1111
12+
HSV:
13+
3-uple of Hue, Saturation, Value all between 0.0 and 1.0
14+
1215
HSL:
1316
3-uple of Hue, Saturation, Lightness all between 0.0 and 1.0
1417
@@ -465,6 +468,90 @@ def rgb2hsl(rgb):
465468
return (h, s, l)
466469

467470

471+
def hsv2rgb(hsv):
472+
"""Convert HSV representation towards RGB
473+
474+
:param h: Hue, position around the chromatic circle (h=1 equiv h=0)
475+
:param s: Saturation, color saturation (0=full gray, 1=full color)
476+
:param v: Value, brightness value(0=full black, 1=full brightness)
477+
:rtype: 3-uple for RGB values in float between 0 and 1
478+
479+
Hue, Saturation, and Value are floats between 0 and 1
480+
481+
Note that Hue can be set to any value but as it is a rotation
482+
around the chromatic circle, any value above 1 or below 0 can
483+
be expressed by a value between 0 and 1 (Note that h=0 is equiv
484+
to h=1).
485+
486+
This algorithm came from:
487+
http://www.easyrgb.com/index.php?X=MATH&H=21#text21
488+
489+
Here are some examples of HSV to RGB convertion:
490+
491+
>>> from colour import hsv2rgb
492+
493+
TODO: finish examples
494+
495+
>>> hsv2rgb((1.0, 1.0, 1.0)) # doctest: +ELLIPSIS
496+
(..., 0.0, 1.0)
497+
>>> hsv2rgb((0.5, 0.5, 0.5)) # doctest: +ELLIPSIS
498+
(..., 0.0, 0.5)
499+
>>> hsv2rgb((0.0, 0.0, 0.0)) # doctest: +ELLIPSIS
500+
(..., 0.0, 0.0)
501+
502+
If only one color is different from the others, it defines the
503+
direct Hue:
504+
505+
>>> hsv2rgb((0.5, 0.5, 1.0)) # doctest: +ELLIPSIS
506+
(0.66..., 1.0, 0.75)
507+
>>> hsv2rgb((0.2, 0.1, 0.1)) # doctest: +ELLIPSIS
508+
(0.0, 0.33..., 0.15...)
509+
510+
Having only one value set, you can check that:
511+
512+
>>> hsv2rgb((1.0, 0.0, 0.0))
513+
(0.0, 1.0, 0.5)
514+
>>> hsv2rgb((0.0, 1.0, 0.0)) # doctest: +ELLIPSIS
515+
(0.33..., 1.0, 0.5)
516+
>>> hsv2rgb((0.0, 0.0, 1.0)) # doctest: +ELLIPSIS
517+
(0.66..., 1.0, 0.5)
518+
519+
Of course:
520+
>>> hsv2rgb((0.0, 2.0, 0.5)) # doctest: +ELLIPSIS
521+
Traceback (most recent call last):
522+
...
523+
ValueError: Green must be between 0 and 1. You provided 2.0.
524+
525+
And:
526+
>>> hsv2rgb((0.0, 0.0, 1.5)) # doctest: +ELLIPSIS
527+
Traceback (most recent call last):
528+
...
529+
ValueError: Blue must be between 0 and 1. You provided 1.5.
530+
531+
"""
532+
h, s, v = [float(v) for v in hsl]
533+
534+
#TODO: implement this
535+
if not (0.0 - FLOAT_ERROR <= s <= 1.0 + FLOAT_ERROR):
536+
raise ValueError("Saturation must be between 0 and 1.")
537+
if not (0.0 - FLOAT_ERROR <= l <= 1.0 + FLOAT_ERROR):
538+
raise ValueError("Lightness must be between 0 and 1.")
539+
540+
if s == 0:
541+
return l, l, l
542+
543+
if l < 0.5:
544+
v2 = l * (1.0 + s)
545+
else:
546+
v2 = (l + s) - (s * l)
547+
548+
v1 = 2.0 * l - v2
549+
550+
r = _hue2rgb(v1, v2, h + (1.0 / 3))
551+
g = _hue2rgb(v1, v2, h)
552+
b = _hue2rgb(v1, v2, h - (1.0 / 3))
553+
554+
468555
def _hue2rgb(v1, v2, vH):
469556
"""Private helper function (Do not call directly)
470557
@@ -788,7 +875,7 @@ class Color(object):
788875
"""Abstraction of a color object
789876
790877
Color object keeps information of a color. It can input/output to different
791-
format (HSL, RGB, HEX, WEB) and their partial representation.
878+
format (HSV, HSL, RGB, HEX, WEB) and their partial representation.
792879
793880
>>> from colour import Color, HSL
794881
@@ -814,6 +901,8 @@ class Color(object):
814901
815902
>>> b.rgb
816903
(0.0, 0.0, 1.0)
904+
>>> b.hsv # doctest: +ELLIPSIS
905+
(0.66..., 1.0, 1.0)
817906
>>> b.hsl # doctest: +ELLIPSIS
818907
(0.66..., 1.0, 0.5)
819908
>>> b.hex
@@ -863,15 +952,21 @@ class Color(object):
863952
<Color red>
864953
865954
>>> c.saturation = 0.0
866-
>>> c.hsl # doctest: +ELLIPSIS
955+
>>> c.hsv # doctest: +ELLIPSIS
867956
(..., 0.0, 0.5)
957+
>>> c.hsl # doctest: +ELLIPSIS
958+
(..., 0.5, 0.0)
868959
>>> c.rgb
869960
(0.5, 0.5, 0.5)
870961
>>> c.hex
871962
'#7f7f7f'
872963
>>> c
873964
<Color #7f7f7f>
874965
966+
>>> c.value = 0.5
967+
>>> c
968+
<TODO: herp>
969+
875970
>>> c.luminance = 0.0
876971
>>> c
877972
<Color black>
@@ -904,10 +999,8 @@ class Color(object):
904999
...
9051000
AttributeError: 'lightness' not found
9061001
907-
TODO: could add HSV, CMYK, YUV conversion.
1002+
TODO: could add CMYK, YUV conversion.
9081003
909-
# >>> b.hsv
910-
# >>> b.value
9111004
# >>> b.cyan
9121005
# >>> b.magenta
9131006
# >>> b.yellow
@@ -1032,6 +1125,9 @@ def get_web(self):
10321125
## Set
10331126
##
10341127

1128+
def set_hsv(self, value):
1129+
self._hsl = hsv2hsl(value)
1130+
10351131
def set_hsl(self, value):
10361132
self._hsl = list(value)
10371133

0 commit comments

Comments
 (0)