mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-30 13:08:07 -06:00
Keep rgb_to_hsl saturation finite for over-range colours
Found while testing crates/color/src/lib.rs:100 (rgb_to_hsl) Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com> Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Haiku 5.5
parent
2961258879
commit
5d2d28a953
+14
-1
@@ -97,7 +97,9 @@ pub fn rgb_to_hsl(r: f32, g: f32, b: f32) -> (f32, f32, f32) {
|
||||
return (0.0, 0.0, l);
|
||||
}
|
||||
let d = max - min;
|
||||
let s = if l > 0.5 { d / (2.0 - max - min) } else { d / (max + min) };
|
||||
let denom = if l > 0.5 { 2.0 - max - min } else { max + min };
|
||||
// Over-range (HDR) or negative inputs can make the denominator zero or negative.
|
||||
let s = if denom > 0.0 { (d / denom).min(1.0) } else { 1.0 };
|
||||
let h = if max == r {
|
||||
(((g - b) / d + if g < b { 6.0 } else { 0.0 }) / 6.0).rem_euclid(1.0)
|
||||
} else if max == g {
|
||||
@@ -262,6 +264,17 @@ impl Label {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn hsl_round_trip_is_finite_for_out_of_range_colours() {
|
||||
for (r, g, b) in [(1.5, 0.5, 0.5), (2.0, 0.1, 0.3), (-0.5, 0.2, 0.9)] {
|
||||
let (h, s, l) = rgb_to_hsl(r, g, b);
|
||||
assert!(h.is_finite() && s.is_finite() && l.is_finite(), "{h} {s} {l}");
|
||||
assert!((0.0..=1.0).contains(&s), "saturation {s} for {r} {g} {b}");
|
||||
let (r2, g2, b2) = hsl_to_rgb(h, s, l);
|
||||
assert!(r2.is_finite() && g2.is_finite() && b2.is_finite(), "{r2} {g2} {b2}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hsv_to_rgb_tiny_negative_hue_is_red() {
|
||||
let (r, g, b) = hsv_to_rgb(-1e-9, 1.0, 1.0);
|
||||
|
||||
Reference in New Issue
Block a user