pub fn cmyk_to_rgb_naive(c: f64, m: f64, y: f64, k: f64) -> (f64, f64, f64) {
let c = c.clamp(0.0, 1.0);
let m = m.clamp(0.0, 1.0);
let y = y.clamp(0.0, 1.0);
let k = k.clamp(0.0, 1.0);
(
(1.0 - c) * (1.0 - k),
(1.0 - m) * (1.0 - k),
(1.0 - y) * (1.0 - k),
)
}
pub fn rgb_to_cmyk_naive(r: f64, g: f64, b: f64) -> (f64, f64, f64, f64) {
let r = r.clamp(0.0, 1.0);
let g = g.clamp(0.0, 1.0);
let b = b.clamp(0.0, 1.0);
let k = 1.0 - r.max(g).max(b);
if k >= 1.0 {
(0.0, 0.0, 0.0, 1.0)
} else {
let inv = 1.0 - k;
(
(1.0 - r - k) / inv,
(1.0 - g - k) / inv,
(1.0 - b - k) / inv,
k,
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn naive_cmyk_roundtrips_exactly() {
for &(r, g, b) in &[
(1.0, 1.0, 0.0),
(0.0, 1.0, 1.0),
(1.0, 0.0, 1.0),
(0.2, 0.6, 0.9),
(0.0, 0.0, 0.0),
(1.0, 1.0, 1.0),
(0.5, 0.5, 0.5),
] {
let (c, m, y, k) = rgb_to_cmyk_naive(r, g, b);
let (r2, g2, b2) = cmyk_to_rgb_naive(c, m, y, k);
assert!(
(r - r2).abs() < 1e-9 && (g - g2).abs() < 1e-9 && (b - b2).abs() < 1e-9,
"roundtrip ({r},{g},{b}) -> ({r2},{g2},{b2})"
);
}
}
#[test]
fn naive_cmyk_reference_points() {
assert_eq!(rgb_to_cmyk_naive(1.0, 1.0, 0.0), (0.0, 0.0, 1.0, 0.0)); assert_eq!(rgb_to_cmyk_naive(0.0, 0.0, 0.0), (0.0, 0.0, 0.0, 1.0)); assert_eq!(rgb_to_cmyk_naive(1.0, 1.0, 1.0), (0.0, 0.0, 0.0, 0.0)); assert_eq!(cmyk_to_rgb_naive(0.0, 0.0, 0.0, 1.0), (0.0, 0.0, 0.0)); assert_eq!(cmyk_to_rgb_naive(1.0, 0.0, 1.0, 0.0), (0.0, 1.0, 0.0));
}
}