From 5e8ad4f40082fdb811e4d98707ed3855345313aa Mon Sep 17 00:00:00 2001 From: Maximilian Giller Date: Tue, 21 Jan 2025 05:03:47 +0100 Subject: [PATCH] Expanded color datatype --- src/core/color.py | 88 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 85 insertions(+), 3 deletions(-) diff --git a/src/core/color.py b/src/core/color.py index dc8c7e6..1957d25 100644 --- a/src/core/color.py +++ b/src/core/color.py @@ -1,5 +1,87 @@ class Color: def __init__(self, *, hue: float, saturation: float, brightness: float): - self.hue: float = hue - self.saturation: float = saturation - self.brightness: float = brightness + self.hue = hue + self.saturation = saturation + 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