Expanded color datatype
This commit is contained in:
parent
668e8e78b1
commit
5e8ad4f400
1 changed files with 85 additions and 3 deletions
|
@ -1,5 +1,87 @@
|
||||||
class Color:
|
class Color:
|
||||||
def __init__(self, *, hue: float, saturation: float, brightness: float):
|
def __init__(self, *, hue: float, saturation: float, brightness: float):
|
||||||
self.hue: float = hue
|
self.hue = hue
|
||||||
self.saturation: float = saturation
|
self.saturation = saturation
|
||||||
self.brightness: float = brightness
|
self.brightness = brightness
|
||||||
|
|
||||||
|
@property
|
||||||
|
def hue(self) -> float:
|
||||||
|
return self._hue
|
||||||
|
|
||||||
|
@hue.setter
|
||||||
|
def hue(self, value: float):
|
||||||
|
if 0 <= value <= 1:
|
||||||
|
self._hue = value
|
||||||
|
else:
|
||||||
|
raise ValueError("Hue must be between 0 and 1")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def saturation(self) -> float:
|
||||||
|
return self._saturation
|
||||||
|
|
||||||
|
@saturation.setter
|
||||||
|
def saturation(self, value: float):
|
||||||
|
if 0 <= value <= 1:
|
||||||
|
self._saturation = value
|
||||||
|
else:
|
||||||
|
raise ValueError("Saturation must be between 0 and 1")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def brightness(self) -> float:
|
||||||
|
return self._brightness
|
||||||
|
|
||||||
|
@brightness.setter
|
||||||
|
def brightness(self, value: float):
|
||||||
|
if 0 <= value <= 1:
|
||||||
|
self._brightness = value
|
||||||
|
else:
|
||||||
|
raise ValueError("Brightness must be between 0 and 1")
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
if isinstance(other, Color):
|
||||||
|
return (
|
||||||
|
self.hue == other.hue
|
||||||
|
and self.saturation == other.saturation
|
||||||
|
and self.brightness == other.brightness
|
||||||
|
)
|
||||||
|
raise ValueError(
|
||||||
|
"Can only compare Color instance to other Color instance. Instead, instance of another class was provided."
|
||||||
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.__repr__()
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
# Convert HSB to RGB
|
||||||
|
rgb = self.to_rgb()
|
||||||
|
# Convert RGB to HEX
|
||||||
|
return f"#{int(rgb[0] * 255):02X}{int(rgb[1] * 255):02X}{int(rgb[2] * 255):02X}"
|
||||||
|
|
||||||
|
def to_rgb(self) -> tuple:
|
||||||
|
"""Converts HSB to RGB as a tuple of floats in range [0, 1]."""
|
||||||
|
h, s, b = self.hue, self.saturation, self.brightness
|
||||||
|
|
||||||
|
if s == 0:
|
||||||
|
# Grayscale color (no saturation)
|
||||||
|
return b, b, b
|
||||||
|
|
||||||
|
h = h * 6 # Scale hue to [0, 6]
|
||||||
|
i = int(h) # Which color sector
|
||||||
|
f = h - i # Fractional part of hue
|
||||||
|
p = b * (1 - s)
|
||||||
|
q = b * (1 - s * f)
|
||||||
|
t = b * (1 - s * (1 - f))
|
||||||
|
|
||||||
|
i %= 6
|
||||||
|
if i == 0:
|
||||||
|
return b, t, p
|
||||||
|
elif i == 1:
|
||||||
|
return q, b, p
|
||||||
|
elif i == 2:
|
||||||
|
return p, b, t
|
||||||
|
elif i == 3:
|
||||||
|
return p, q, b
|
||||||
|
elif i == 4:
|
||||||
|
return t, p, b
|
||||||
|
elif i == 5:
|
||||||
|
return b, p, q
|
||||||
|
|
Loading…
Reference in a new issue