flood-rs/src/color.rs
2025-07-19 03:00:35 +02:00

69 lines
2 KiB
Rust

use std::fmt;
/// Represents a color in the RGB (Red, Green, Blue) model.
/// Values range from 0 to 255.
pub struct Rgb {
pub r: u8,
pub g: u8,
pub b: u8,
}
/// Represents a color in the HSV (Hue, Saturation, Value) model.
/// - `h` (hue): 0-359 degrees
/// - `s` (saturation): 0.0-1.0
/// - `v` (value/brightness): 0.0-1.0
pub struct Hsv {
pub h: u16,
pub s: f32,
pub v: f32,
}
// Implement the `Debug` trait for Rgb to allow pretty-printing.
impl fmt::Debug for Rgb {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Rgb({}, {}, {})", self.r, self.g, self.b)
}
}
/// Provides the conversion logic from HSV to RGB.
/// This uses the standard mathematical formula for the conversion.
impl From<Hsv> for Rgb {
fn from(hsv: Hsv) -> Self {
// Ensure saturation and value are within the valid range [0.0, 1.0]
let s = hsv.s.clamp(0.0, 1.0);
let v = hsv.v.clamp(0.0, 1.0);
// When saturation is 0, the color is a shade of gray.
if s == 0.0 {
let val = (v * 255.0) as u8;
return Rgb { r: val, g: val, b: val };
}
// The hue is treated as a sector on a color wheel.
let h = hsv.h as f32 / 60.0; // Sector 0-5
let i = h.floor() as i32;
let f = h - i as f32; // Fractional part of h
let p = v * (1.0 - s);
let q = v * (1.0 - f * s);
let t = v * (1.0 - (1.0 - f) * s);
// Determine the RGB values based on the hue sector.
let (r, g, b) = match i {
0 => (v, t, p),
1 => (q, v, p),
2 => (p, v, t),
3 => (p, q, v),
4 => (t, p, v),
_ => (v, p, q), // Default case for sector 5
};
// Convert the float RGB values (0.0-1.0) to u8 values (0-255).
Rgb {
r: (r * 255.0).round() as u8,
g: (g * 255.0).round() as u8,
b: (b * 255.0).round() as u8,
}
}
}