70 lines
2 KiB
Rust
70 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,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|