From 4f59e600ff9e6497915d3cd558384769078acc59 Mon Sep 17 00:00:00 2001 From: okaneco <47607823+okaneco@users.noreply.github.com> Date: Thu, 19 Mar 2020 01:10:38 -0400 Subject: [PATCH] Implement functions to return component min/max for each color type Add functions for Alpha, Hsl, Hsv, Hwb, Lab, Lch, Luma, Rgb, Yxy, Xyz Add max_extended_chroma for Lch in addition to max_chroma --- palette/src/alpha.rs | 18 ++++++++++++++++ palette/src/hsl.rs | 28 ++++++++++++++++++++++++ palette/src/hsv.rs | 28 ++++++++++++++++++++++++ palette/src/hwb.rs | 28 ++++++++++++++++++++++++ palette/src/lab.rs | 40 ++++++++++++++++++++++++++++++++++ palette/src/lch.rs | 38 +++++++++++++++++++++++++++++++++ palette/src/luma/luma.rs | 16 ++++++++++++++ palette/src/rgb/rgb.rs | 40 ++++++++++++++++++++++++++++++++++ palette/src/xyz.rs | 46 ++++++++++++++++++++++++++++++++++++++-- palette/src/yxy.rs | 43 +++++++++++++++++++++++++++++++++++-- 10 files changed, 321 insertions(+), 4 deletions(-) diff --git a/palette/src/alpha.rs b/palette/src/alpha.rs index 26c9dd69a..de3c1e054 100644 --- a/palette/src/alpha.rs +++ b/palette/src/alpha.rs @@ -24,6 +24,18 @@ pub struct Alpha { pub alpha: T, } +impl Alpha { + /// Return the `alpha` value minimum. + pub fn min_alpha() -> T { + T::zero() + } + + /// Return the `alpha` value maximum. + pub fn max_alpha() -> T { + T::max_intensity() + } +} + impl Deref for Alpha { type Target = C; @@ -524,6 +536,12 @@ mod test { ); } + #[test] + fn check_min_max_components() { + assert_relative_eq!(Rgba::::min_alpha(), 0.0); + assert_relative_eq!(Rgba::::max_alpha(), 1.0); + } + #[cfg(feature = "serializing")] #[test] fn serialize() { diff --git a/palette/src/hsl.rs b/palette/src/hsl.rs index 8484ddcdf..230beabf7 100644 --- a/palette/src/hsl.rs +++ b/palette/src/hsl.rs @@ -177,6 +177,26 @@ where space: PhantomData, } } + + /// Return the `saturation` value minimum. + pub fn min_saturation() -> T { + T::zero() + } + + /// Return the `saturation` value maximum. + pub fn max_saturation() -> T { + T::max_intensity() + } + + /// Return the `lightness` value minimum. + pub fn min_lightness() -> T { + T::zero() + } + + /// Return the `lightness` value maximum. + pub fn max_lightness() -> T { + T::max_intensity() + } } ///[`Hsla`](type.Hsla.html) implementations. @@ -711,6 +731,14 @@ mod test { raw_pixel_conversion_tests!(Hsl: hue, saturation, lightness); raw_pixel_conversion_fail_tests!(Hsl: hue, saturation, lightness); + #[test] + fn check_min_max_components() { + assert_relative_eq!(Hsl::::min_saturation(), 0.0); + assert_relative_eq!(Hsl::::min_lightness(), 0.0); + assert_relative_eq!(Hsl::::max_saturation(), 1.0); + assert_relative_eq!(Hsl::::max_lightness(), 1.0); + } + #[cfg(feature = "serializing")] #[test] fn serialize() { diff --git a/palette/src/hsv.rs b/palette/src/hsv.rs index 84309afa0..1e1df9275 100644 --- a/palette/src/hsv.rs +++ b/palette/src/hsv.rs @@ -172,6 +172,26 @@ where space: PhantomData, } } + + /// Return the `saturation` value minimum. + pub fn min_saturation() -> T { + T::zero() + } + + /// Return the `saturation` value maximum. + pub fn max_saturation() -> T { + T::max_intensity() + } + + /// Return the `value` value minimum. + pub fn min_value() -> T { + T::zero() + } + + /// Return the `value` value maximum. + pub fn max_value() -> T { + T::max_intensity() + } } ///[`Hsva`](type.Hsva.html) implementations. @@ -726,6 +746,14 @@ mod test { raw_pixel_conversion_tests!(Hsv: hue, saturation, value); raw_pixel_conversion_fail_tests!(Hsv: hue, saturation, value); + #[test] + fn check_min_max_components() { + assert_relative_eq!(Hsv::::min_saturation(), 0.0,); + assert_relative_eq!(Hsv::::min_value(), 0.0,); + assert_relative_eq!(Hsv::::max_saturation(), 1.0,); + assert_relative_eq!(Hsv::::max_value(), 1.0,); + } + #[cfg(feature = "serializing")] #[test] fn serialize() { diff --git a/palette/src/hwb.rs b/palette/src/hwb.rs index c6aed845b..4610a8e98 100644 --- a/palette/src/hwb.rs +++ b/palette/src/hwb.rs @@ -138,6 +138,26 @@ where space: PhantomData, } } + + /// Return the `whiteness` value minimum. + pub fn min_whiteness() -> T { + T::zero() + } + + /// Return the `whiteness` value maximum. + pub fn max_whiteness() -> T { + T::max_intensity() + } + + /// Return the `blackness` value minimum. + pub fn min_blackness() -> T { + T::zero() + } + + /// Return the `blackness` value maximum. + pub fn max_blackness() -> T { + T::max_intensity() + } } ///[`Hwba`](type.Hwba.html) implementations. @@ -676,6 +696,14 @@ mod test { raw_pixel_conversion_tests!(Hwb: hue, whiteness, blackness); raw_pixel_conversion_fail_tests!(Hwb: hue, whiteness, blackness); + #[test] + fn check_min_max_components() { + assert_relative_eq!(Hwb::::min_whiteness(), 0.0,); + assert_relative_eq!(Hwb::::min_blackness(), 0.0,); + assert_relative_eq!(Hwb::::max_whiteness(), 1.0,); + assert_relative_eq!(Hwb::::max_blackness(), 1.0,); + } + #[cfg(feature = "serializing")] #[test] fn serialize() { diff --git a/palette/src/lab.rs b/palette/src/lab.rs index 234eda053..4e69f9675 100644 --- a/palette/src/lab.rs +++ b/palette/src/lab.rs @@ -112,6 +112,36 @@ where pub fn from_components((l, a, b): (T, T, T)) -> Self { Self::with_wp(l, a, b) } + + /// Return the `l` value minimum. + pub fn min_l() -> T { + T::zero() + } + + /// Return the `l` value maximum. + pub fn max_l() -> T { + from_f64(100.0) + } + + /// Return the `a` value minimum. + pub fn min_a() -> T { + from_f64(-128.0) + } + + /// Return the `a` value maximum. + pub fn max_a() -> T { + from_f64(127.0) + } + + /// Return the `b` value minimum. + pub fn min_b() -> T { + from_f64(-128.0) + } + + /// Return the `b` value maximum. + pub fn max_b() -> T { + from_f64(127.0) + } } ///[`Laba`](type.Laba.html) implementations. @@ -685,6 +715,16 @@ mod test { raw_pixel_conversion_tests!(Lab: l, a, b); raw_pixel_conversion_fail_tests!(Lab: l, a, b); + #[test] + fn check_min_max_components() { + assert_relative_eq!(Lab::::min_l(), 0.0); + assert_relative_eq!(Lab::::min_a(), -128.0); + assert_relative_eq!(Lab::::min_b(), -128.0); + assert_relative_eq!(Lab::::max_l(), 100.0); + assert_relative_eq!(Lab::::max_a(), 127.0); + assert_relative_eq!(Lab::::max_b(), 127.0); + } + #[cfg(feature = "serializing")] #[test] fn serialize() { diff --git a/palette/src/lch.rs b/palette/src/lch.rs index 9b35ec1d1..afbf4726c 100644 --- a/palette/src/lch.rs +++ b/palette/src/lch.rs @@ -112,6 +112,35 @@ where pub fn from_components>>((l, chroma, hue): (T, T, H)) -> Self { Self::with_wp(l, chroma, hue) } + + /// Return the `l` value minimum. + pub fn min_l() -> T { + T::zero() + } + + /// Return the `l` value maximum. + pub fn max_l() -> T { + from_f64(100.0) + } + + /// Return the `chroma` value minimum. + pub fn min_chroma() -> T { + T::zero() + } + + /// Return the `chroma` value maximum. This value does not cover the entire + /// color space, but covers enough to be practical for downsampling to + /// smaller color spaces like sRGB. + pub fn max_chroma() -> T { + from_f64(128.0) + } + + /// Return the `chroma` extended maximum value. This value covers the entire + /// color space and is included for completeness, but the additional range + /// should be unnecessary for most use cases. + pub fn max_extended_chroma() -> T { + from_f64(crate::float::Float::sqrt(128.0f64 * 128.0 + 128.0 * 128.0)) + } } ///[`Lcha`](type.Lcha.html) implementations. @@ -557,6 +586,15 @@ mod test { raw_pixel_conversion_tests!(Lch: l, chroma, hue); raw_pixel_conversion_fail_tests!(Lch: l, chroma, hue); + #[test] + fn check_min_max_components() { + assert_relative_eq!(Lch::::min_l(), 0.0); + assert_relative_eq!(Lch::::max_l(), 100.0); + assert_relative_eq!(Lch::::min_chroma(), 0.0); + assert_relative_eq!(Lch::::max_chroma(), 128.0); + assert_relative_eq!(Lch::::max_extended_chroma(), 181.01933598375618); + } + #[cfg(feature = "serializing")] #[test] fn serialize() { diff --git a/palette/src/luma/luma.rs b/palette/src/luma/luma.rs index e432c45d3..378326bc1 100644 --- a/palette/src/luma/luma.rs +++ b/palette/src/luma/luma.rs @@ -108,6 +108,16 @@ where pub fn from_components((luma,): (T,)) -> Self { Self::new(luma) } + + /// Return the `luma` value minimum. + pub fn min_luma() -> T { + T::zero() + } + + /// Return the `luma` value maximum. + pub fn max_luma() -> T { + T::max_intensity() + } } impl Luma @@ -807,6 +817,12 @@ mod test { assert_eq!(format!("{:03X}", Luma::::new(1)), "001"); } + #[test] + fn check_min_max_components() { + assert_relative_eq!(Luma::::min_luma(), 0.0); + assert_relative_eq!(Luma::::max_luma(), 1.0); + } + #[cfg(feature = "serializing")] #[test] fn serialize() { diff --git a/palette/src/rgb/rgb.rs b/palette/src/rgb/rgb.rs index e59b2add3..0b845f78f 100644 --- a/palette/src/rgb/rgb.rs +++ b/palette/src/rgb/rgb.rs @@ -116,6 +116,36 @@ impl Rgb { pub fn from_components((red, green, blue): (T, T, T)) -> Self { Self::new(red, green, blue) } + + /// Return the `red` value minimum. + pub fn min_red() -> T { + T::zero() + } + + /// Return the `red` value maximum. + pub fn max_red() -> T { + T::max_intensity() + } + + /// Return the `green` value minimum. + pub fn min_green() -> T { + T::zero() + } + + /// Return the `green` value maximum. + pub fn max_green() -> T { + T::max_intensity() + } + + /// Return the `blue` value minimum. + pub fn min_blue() -> T { + T::zero() + } + + /// Return the `blue` value maximum. + pub fn max_blue() -> T { + T::max_intensity() + } } /// Convenience functions to convert between a packed `u32` and `Rgb`. @@ -1315,4 +1345,14 @@ mod test { let c = Rgb::::from_str("abc"); assert_eq!(c.unwrap(), Rgb::::new(170, 187, 204)); } + + #[test] + fn check_min_max_components() { + assert_relative_eq!(Rgb::::min_red(), 0.0); + assert_relative_eq!(Rgb::::min_green(), 0.0); + assert_relative_eq!(Rgb::::min_blue(), 0.0); + assert_relative_eq!(Rgb::::max_red(), 1.0); + assert_relative_eq!(Rgb::::max_green(), 1.0); + assert_relative_eq!(Rgb::::max_blue(), 1.0); + } } diff --git a/palette/src/xyz.rs b/palette/src/xyz.rs index ac10a5160..1db89dd5b 100644 --- a/palette/src/xyz.rs +++ b/palette/src/xyz.rs @@ -113,6 +113,39 @@ where pub fn from_components((x, y, z): (T, T, T)) -> Self { Self::with_wp(x, y, z) } + + /// Return the `x` value minimum. + pub fn min_x() -> T { + T::zero() + } + + /// Return the `x` value maximum. + pub fn max_x() -> T { + let xyz_ref: Xyz = Wp::get_xyz(); + xyz_ref.x + } + + /// Return the `y` value minimum. + pub fn min_y() -> T { + T::zero() + } + + /// Return the `y` value maximum. + pub fn max_y() -> T { + let xyz_ref: Xyz = Wp::get_xyz(); + xyz_ref.y + } + + /// Return the `z` value minimum. + pub fn min_z() -> T { + T::zero() + } + + /// Return the `z` value maximum. + pub fn max_z() -> T { + let xyz_ref: Xyz = Wp::get_xyz(); + xyz_ref.z + } } ///[`Xyza`](type.Xyza.html) implementations. @@ -618,8 +651,7 @@ where mod test { use super::Xyz; use crate::white_point::D65; - use crate::LinLuma; - use crate::LinSrgb; + use crate::{LinLuma, LinSrgb}; const X_N: f64 = 0.95047; const Y_N: f64 = 1.0; const Z_N: f64 = 1.08883; @@ -669,6 +701,16 @@ mod test { raw_pixel_conversion_tests!(Xyz: x, y, z); raw_pixel_conversion_fail_tests!(Xyz: x, y, z); + #[test] + fn check_min_max_components() { + assert_relative_eq!(Xyz::::min_x(), 0.0); + assert_relative_eq!(Xyz::::min_y(), 0.0); + assert_relative_eq!(Xyz::::min_z(), 0.0); + assert_relative_eq!(Xyz::::max_x(), X_N); + assert_relative_eq!(Xyz::::max_y(), Y_N); + assert_relative_eq!(Xyz::::max_z(), Z_N); + } + #[cfg(feature = "serializing")] #[test] fn serialize() { diff --git a/palette/src/yxy.rs b/palette/src/yxy.rs index 5c1a0280c..bebf5f776 100644 --- a/palette/src/yxy.rs +++ b/palette/src/yxy.rs @@ -110,6 +110,36 @@ where pub fn from_components((x, y, luma): (T, T, T)) -> Self { Self::with_wp(x, y, luma) } + + /// Return the `x` value minimum. + pub fn min_x() -> T { + T::zero() + } + + /// Return the `x` value maximum. + pub fn max_x() -> T { + T::max_intensity() + } + + /// Return the `y` value minimum. + pub fn min_y() -> T { + T::zero() + } + + /// Return the `y` value maximum. + pub fn max_y() -> T { + T::max_intensity() + } + + /// Return the `luma` value minimum. + pub fn min_luma() -> T { + T::zero() + } + + /// Return the `luma` value maximum. + pub fn max_luma() -> T { + T::max_intensity() + } } ///[`Yxya`](type.Yxya.html) implementations. @@ -585,8 +615,7 @@ where mod test { use super::Yxy; use crate::white_point::D65; - use crate::LinLuma; - use crate::LinSrgb; + use crate::{LinLuma, LinSrgb}; #[test] fn luma() { @@ -633,6 +662,16 @@ mod test { raw_pixel_conversion_tests!(Yxy: x, y, luma); raw_pixel_conversion_fail_tests!(Yxy: x, y, luma); + #[test] + fn check_min_max_components() { + assert_relative_eq!(Yxy::::min_x(), 0.0); + assert_relative_eq!(Yxy::::min_y(), 0.0); + assert_relative_eq!(Yxy::::min_luma(), 0.0); + assert_relative_eq!(Yxy::::max_x(), 1.0); + assert_relative_eq!(Yxy::::max_y(), 1.0); + assert_relative_eq!(Yxy::::max_luma(), 1.0); + } + #[cfg(feature = "serializing")] #[test] fn serialize() {