diff --git a/src/color.rs b/src/color.rs index 49af6255c1..310b7454c0 100644 --- a/src/color.rs +++ b/src/color.rs @@ -969,48 +969,28 @@ pub(crate) trait Invert { /// Inverts a color in-place. fn invert(&mut self); } - impl Invert for LumaA { fn invert(&mut self) { - let l = self.0; - let max = T::DEFAULT_MAX_VALUE; - - *self = LumaA([max - l[0], l[1]]); + let [l, a] = self.0; + *self = LumaA([l.invert_range(), a]); } } - impl Invert for Luma { fn invert(&mut self) { - let l = self.0; - - let max = T::DEFAULT_MAX_VALUE; - let l1 = max - l[0]; - - *self = Luma([l1]); + let [l] = self.0; + *self = Luma([l.invert_range()]); } } - impl Invert for Rgba { fn invert(&mut self) { - let rgba = self.0; - - let max = T::DEFAULT_MAX_VALUE; - - *self = Rgba([max - rgba[0], max - rgba[1], max - rgba[2], rgba[3]]); + let [r, g, b, a] = self.0; + *self = Rgba([r.invert_range(), g.invert_range(), b.invert_range(), a]); } } - impl Invert for Rgb { fn invert(&mut self) { - let rgb = self.0; - - let max = T::DEFAULT_MAX_VALUE; - - let r1 = max - rgb[0]; - let g1 = max - rgb[1]; - let b1 = max - rgb[2]; - - *self = Rgb([r1, g1, b1]); + let [r, g, b] = self.0; + *self = Rgb([r.invert_range(), g.invert_range(), b.invert_range()]); } } diff --git a/src/primitive_sealed.rs b/src/primitive_sealed.rs index 4d71e11e65..58a77e990b 100644 --- a/src/primitive_sealed.rs +++ b/src/primitive_sealed.rs @@ -8,7 +8,7 @@ use crate::imageops::fast_blur::BlurAccumulator; /// this crate. #[allow(private_bounds)] pub trait PrimitiveSealed: - Sized + NearestFrom + WithBlurAcc + BgraSwizzle + RgbToLuma + Sized + NearestFrom + WithBlurAcc + BgraSwizzle + RgbToLuma + InvertRange { } @@ -229,3 +229,35 @@ impl RgbToLuma for f32 { } } impl RgbToLuma for f64 {} + +pub(crate) trait InvertRange { + /// Inverts the default range of this value. + /// + /// This has the following properties: + /// - `self.invert_range().invert_range() == self` + /// - `T::DEFAULT_MIN_VALUE.invert_range() == T::DEFAULT_MAX_VALUE` and + /// `T::DEFAULT_MAX_VALUE.invert_range() == T::DEFAULT_MIN_VALUE` + /// + /// For floats, this is `1.0 - self`. For integers, this is `!self`. + fn invert_range(self) -> Self; +} +impl InvertRange for f32 { + fn invert_range(self) -> Self { + 1.0 - self + } +} +impl InvertRange for f64 { + fn invert_range(self) -> Self { + 1.0 - self + } +} +macro_rules! impl_invert_range_for_ints { + ($($t:ty),+) => { $( + impl InvertRange for $t { + fn invert_range(self) -> Self { + !self + } + } + )+ }; +} +impl_invert_range_for_ints!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize); diff --git a/src/traits.rs b/src/traits.rs index f395798391..3639e00637 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -560,7 +560,7 @@ pub trait Pixel: Copy + Clone { where F: FnMut(Self::Subpixel, Self::Subpixel) -> Self::Subpixel; - /// Invert this pixel + /// Invert the color channels of this pixel. Alpha channels are *not* inverted. fn invert(&mut self); /// Blend the color of a given pixel into ourself, taking into account alpha channels