fix: hsl from rgb fixed

This commit is contained in:
2025-08-14 13:54:07 +02:00
parent 2fddf33fde
commit 932bcf09e2
3 changed files with 50 additions and 18 deletions

View File

@@ -10,6 +10,16 @@ impl HSL {
} }
} }
impl PartialEq for HSL {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0 && self.1 == other.1 && self.2 == other.2
}
fn ne(&self, other: &Self) -> bool {
self.0 != other.0 || self.1 != other.1 || self.2 != other.2
}
}
fn min_of_float_vec(vector: Vec<f32>) -> Option<f32> { fn min_of_float_vec(vector: Vec<f32>) -> Option<f32> {
let mut min: Option<f32> = None; let mut min: Option<f32> = None;
@@ -48,36 +58,39 @@ impl From<RGB> for HSL {
let g = value.1.to_f32() / 255.0; let g = value.1.to_f32() / 255.0;
let b = value.2.to_f32() / 255.0; let b = value.2.to_f32() / 255.0;
let min: f32 = min_of_float_vec(vec![r, g, b]).unwrap(); let min: f32 = r.min(g.min(b));
let max: f32 = max_of_float_vec(vec![r, g, b]).unwrap(); let max: f32 = r.max(g.max(b));
// Luminance let h;
let l = ((min + max) / 2.0).round(); let s;
// Luminance set
let l = (min + max) / 2.0;
// Saturation if max == min {
let s: f32;
if r == g && g == b {
s = 0.0; s = 0.0;
h = 0.0;
} else { } else {
// Saturation set
if l <= 0.5 { if l <= 0.5 {
s = (max - min) / (max + min); s = (max - min) / (max + min);
} else { } else {
s = (max - min) / (2.0 - max - min); s = (max - min) / (2.0 - max - min);
} }
}
// Hue // Hue set
let h: f32; // TODO FIX
if max == r { if max == r {
h = (g - b) / (max - min); let temp = if g < b { 6.0 } else { 0.0 };
} else if max == g { h = (g - b) / (max - min) + temp;
h = 2.0 + (b - r) / (max - min); } else if max == g {
} else { h = (b - r) / (max - min) + 2.0;
h = 4.0 + (r - g) / (max - min); } else {
h = (r - g) / (max - min) + 4.0;
}
} }
HSL::new( HSL::new(
(h * 60.0).round() as u16, (h / 6.0 * 360.0).round() as u16,
(s * 100.0).round() as u8, (s * 100.0).round() as u8,
(l * 100.0).round() as u8, (l * 100.0).round() as u8,
) )

View File

@@ -12,6 +12,7 @@ pub type ColorHue = RangedInt<0, 360>;
pub type Percentage = RangedInt<0, 100>; pub type Percentage = RangedInt<0, 100>;
#[derive(Debug)] #[derive(Debug)]
pub struct RGB(ColorIntensity, ColorIntensity, ColorIntensity); pub struct RGB(ColorIntensity, ColorIntensity, ColorIntensity);
#[derive(Debug)]
pub struct HSL(ColorHue, Percentage, Percentage); pub struct HSL(ColorHue, Percentage, Percentage);
// pub struct HSV(ColorHue, Percentage, Percentage); // pub struct HSV(ColorHue, Percentage, Percentage);
#[derive(Debug)] #[derive(Debug)]

View File

@@ -10,7 +10,25 @@ pub mod tests {
} }
#[test] #[test]
fn test_hsl_variants() { fn test_rgb_to_hsl() {
let red_rgb = RGB::new(255, 0, 0);
let red_hsl = HSL::new(0, 100, 50);
assert_eq!(HSL::from(red_rgb), red_hsl);
let green_rgb = RGB::new(0, 255, 0);
let green_hsl = HSL::new(120, 100, 50);
assert_eq!(HSL::from(green_rgb), green_hsl);
let blue_rgb = RGB::new(0, 0, 255);
let blue_hsl = HSL::new(240, 100, 50);
assert_eq!(HSL::from(blue_rgb), blue_hsl);
}
#[test]
fn test_hsl_to_rgb() {
let red_hsl = Color::from(HSL::new(0, 100, 50)); let red_hsl = Color::from(HSL::new(0, 100, 50));
let red_rgb = Color::from(RGB::new(255, 0, 0)); let red_rgb = Color::from(RGB::new(255, 0, 0));
assert_eq!(red_hsl, red_rgb); assert_eq!(red_hsl, red_rgb);