image/
color.rs

1use std::ops::{Index, IndexMut};
2
3use num_traits::{NumCast, ToPrimitive, Zero};
4
5use crate::traits::{Enlargeable, Pixel, Primitive};
6
7/// An enumeration over supported color types and bit depths
8#[derive(Copy, PartialEq, Eq, Debug, Clone, Hash)]
9#[non_exhaustive]
10pub enum ColorType {
11    /// Pixel is 8-bit luminance
12    L8,
13    /// Pixel is 8-bit luminance with an alpha channel
14    La8,
15    /// Pixel contains 8-bit R, G and B channels
16    Rgb8,
17    /// Pixel is 8-bit RGB with an alpha channel
18    Rgba8,
19
20    /// Pixel is 16-bit luminance
21    L16,
22    /// Pixel is 16-bit luminance with an alpha channel
23    La16,
24    /// Pixel is 16-bit RGB
25    Rgb16,
26    /// Pixel is 16-bit RGBA
27    Rgba16,
28
29    /// Pixel is 32-bit float RGB
30    Rgb32F,
31    /// Pixel is 32-bit float RGBA
32    Rgba32F,
33}
34
35impl ColorType {
36    /// Returns the number of bytes contained in a pixel of `ColorType` ```c```
37    pub fn bytes_per_pixel(self) -> u8 {
38        match self {
39            ColorType::L8 => 1,
40            ColorType::L16 | ColorType::La8 => 2,
41            ColorType::Rgb8 => 3,
42            ColorType::Rgba8 | ColorType::La16 => 4,
43            ColorType::Rgb16 => 6,
44            ColorType::Rgba16 => 8,
45            ColorType::Rgb32F => 3 * 4,
46            ColorType::Rgba32F => 4 * 4,
47        }
48    }
49
50    /// Returns if there is an alpha channel.
51    pub fn has_alpha(self) -> bool {
52        use ColorType::*;
53        match self {
54            L8 | L16 | Rgb8 | Rgb16 | Rgb32F => false,
55            La8 | Rgba8 | La16 | Rgba16 | Rgba32F => true,
56        }
57    }
58
59    /// Returns false if the color scheme is grayscale, true otherwise.
60    pub fn has_color(self) -> bool {
61        use ColorType::*;
62        match self {
63            L8 | L16 | La8 | La16 => false,
64            Rgb8 | Rgb16 | Rgba8 | Rgba16 | Rgb32F | Rgba32F => true,
65        }
66    }
67
68    /// Returns the number of bits contained in a pixel of `ColorType` ```c``` (which will always be
69    /// a multiple of 8).
70    pub fn bits_per_pixel(self) -> u16 {
71        <u16 as From<u8>>::from(self.bytes_per_pixel()) * 8
72    }
73
74    /// Returns the number of color channels that make up this pixel
75    pub fn channel_count(self) -> u8 {
76        let e: ExtendedColorType = self.into();
77        e.channel_count()
78    }
79}
80
81/// An enumeration of color types encountered in image formats.
82///
83/// This is not exhaustive over all existing image formats but should be granular enough to allow
84/// round tripping of decoding and encoding as much as possible. The variants will be extended as
85/// necessary to enable this.
86///
87/// Another purpose is to advise users of a rough estimate of the accuracy and effort of the
88/// decoding from and encoding to such an image format.
89#[derive(Copy, PartialEq, Eq, Debug, Clone, Hash)]
90#[non_exhaustive]
91pub enum ExtendedColorType {
92    /// Pixel is 8-bit alpha
93    A8,
94    /// Pixel is 1-bit luminance
95    L1,
96    /// Pixel is 1-bit luminance with an alpha channel
97    La1,
98    /// Pixel contains 1-bit R, G and B channels
99    Rgb1,
100    /// Pixel is 1-bit RGB with an alpha channel
101    Rgba1,
102    /// Pixel is 2-bit luminance
103    L2,
104    /// Pixel is 2-bit luminance with an alpha channel
105    La2,
106    /// Pixel contains 2-bit R, G and B channels
107    Rgb2,
108    /// Pixel is 2-bit RGB with an alpha channel
109    Rgba2,
110    /// Pixel is 4-bit luminance
111    L4,
112    /// Pixel is 4-bit luminance with an alpha channel
113    La4,
114    /// Pixel contains 4-bit R, G and B channels
115    Rgb4,
116    /// Pixel is 4-bit RGB with an alpha channel
117    Rgba4,
118    /// Pixel is 8-bit luminance
119    L8,
120    /// Pixel is 8-bit luminance with an alpha channel
121    La8,
122    /// Pixel contains 8-bit R, G and B channels
123    Rgb8,
124    /// Pixel is 8-bit RGB with an alpha channel
125    Rgba8,
126    /// Pixel is 16-bit luminance
127    L16,
128    /// Pixel is 16-bit luminance with an alpha channel
129    La16,
130    /// Pixel contains 16-bit R, G and B channels
131    Rgb16,
132    /// Pixel is 16-bit RGB with an alpha channel
133    Rgba16,
134    /// Pixel contains 8-bit B, G and R channels
135    Bgr8,
136    /// Pixel is 8-bit BGR with an alpha channel
137    Bgra8,
138
139    // TODO f16 types?
140    /// Pixel is 32-bit float RGB
141    Rgb32F,
142    /// Pixel is 32-bit float RGBA
143    Rgba32F,
144
145    /// Pixel is 8-bit CMYK
146    Cmyk8,
147
148    /// Pixel is of unknown color type with the specified bits per pixel. This can apply to pixels
149    /// which are associated with an external palette. In that case, the pixel value is an index
150    /// into the palette.
151    Unknown(u8),
152}
153
154impl ExtendedColorType {
155    /// Get the number of channels for colors of this type.
156    ///
157    /// Note that the `Unknown` variant returns a value of `1` since pixels can only be treated as
158    /// an opaque datum by the library.
159    pub fn channel_count(self) -> u8 {
160        match self {
161            ExtendedColorType::A8
162            | ExtendedColorType::L1
163            | ExtendedColorType::L2
164            | ExtendedColorType::L4
165            | ExtendedColorType::L8
166            | ExtendedColorType::L16
167            | ExtendedColorType::Unknown(_) => 1,
168            ExtendedColorType::La1
169            | ExtendedColorType::La2
170            | ExtendedColorType::La4
171            | ExtendedColorType::La8
172            | ExtendedColorType::La16 => 2,
173            ExtendedColorType::Rgb1
174            | ExtendedColorType::Rgb2
175            | ExtendedColorType::Rgb4
176            | ExtendedColorType::Rgb8
177            | ExtendedColorType::Rgb16
178            | ExtendedColorType::Rgb32F
179            | ExtendedColorType::Bgr8 => 3,
180            ExtendedColorType::Rgba1
181            | ExtendedColorType::Rgba2
182            | ExtendedColorType::Rgba4
183            | ExtendedColorType::Rgba8
184            | ExtendedColorType::Rgba16
185            | ExtendedColorType::Rgba32F
186            | ExtendedColorType::Bgra8
187            | ExtendedColorType::Cmyk8 => 4,
188        }
189    }
190}
191impl From<ColorType> for ExtendedColorType {
192    fn from(c: ColorType) -> Self {
193        match c {
194            ColorType::L8 => ExtendedColorType::L8,
195            ColorType::La8 => ExtendedColorType::La8,
196            ColorType::Rgb8 => ExtendedColorType::Rgb8,
197            ColorType::Rgba8 => ExtendedColorType::Rgba8,
198            ColorType::L16 => ExtendedColorType::L16,
199            ColorType::La16 => ExtendedColorType::La16,
200            ColorType::Rgb16 => ExtendedColorType::Rgb16,
201            ColorType::Rgba16 => ExtendedColorType::Rgba16,
202            ColorType::Rgb32F => ExtendedColorType::Rgb32F,
203            ColorType::Rgba32F => ExtendedColorType::Rgba32F,
204        }
205    }
206}
207
208macro_rules! define_colors {
209    {$(
210        $(#[$doc:meta])*
211        pub struct $ident:ident<T: $($bound:ident)*>([T; $channels:expr, $alphas:expr])
212            = $interpretation:literal;
213    )*} => {
214
215$( // START Structure definitions
216
217$(#[$doc])*
218#[derive(PartialEq, Eq, Clone, Debug, Copy, Hash)]
219#[repr(C)]
220#[allow(missing_docs)]
221pub struct $ident<T> (pub [T; $channels]);
222
223impl<T: $($bound+)*> Pixel for $ident<T> {
224    type Subpixel = T;
225
226    const CHANNEL_COUNT: u8 = $channels;
227
228    #[inline(always)]
229    fn channels(&self) -> &[T] {
230        &self.0
231    }
232
233    #[inline(always)]
234    fn channels_mut(&mut self) -> &mut [T] {
235        &mut self.0
236    }
237
238    const COLOR_MODEL: &'static str = $interpretation;
239
240    fn channels4(&self) -> (T, T, T, T) {
241        const CHANNELS: usize = $channels;
242        let mut channels = [T::DEFAULT_MAX_VALUE; 4];
243        channels[0..CHANNELS].copy_from_slice(&self.0);
244        (channels[0], channels[1], channels[2], channels[3])
245    }
246
247    fn from_channels(a: T, b: T, c: T, d: T,) -> $ident<T> {
248        const CHANNELS: usize = $channels;
249        *<$ident<T> as Pixel>::from_slice(&[a, b, c, d][..CHANNELS])
250    }
251
252    fn from_slice(slice: &[T]) -> &$ident<T> {
253        assert_eq!(slice.len(), $channels);
254        unsafe { &*(slice.as_ptr() as *const $ident<T>) }
255    }
256    fn from_slice_mut(slice: &mut [T]) -> &mut $ident<T> {
257        assert_eq!(slice.len(), $channels);
258        unsafe { &mut *(slice.as_mut_ptr() as *mut $ident<T>) }
259    }
260
261    fn to_rgb(&self) -> Rgb<T> {
262        let mut pix = Rgb([Zero::zero(), Zero::zero(), Zero::zero()]);
263        pix.from_color(self);
264        pix
265    }
266
267    fn to_rgba(&self) -> Rgba<T> {
268        let mut pix = Rgba([Zero::zero(), Zero::zero(), Zero::zero(), Zero::zero()]);
269        pix.from_color(self);
270        pix
271    }
272
273    fn to_luma(&self) -> Luma<T> {
274        let mut pix = Luma([Zero::zero()]);
275        pix.from_color(self);
276        pix
277    }
278
279    fn to_luma_alpha(&self) -> LumaA<T> {
280        let mut pix = LumaA([Zero::zero(), Zero::zero()]);
281        pix.from_color(self);
282        pix
283    }
284
285    fn map<F>(& self, f: F) -> $ident<T> where F: FnMut(T) -> T {
286        let mut this = (*self).clone();
287        this.apply(f);
288        this
289    }
290
291    fn apply<F>(&mut self, mut f: F) where F: FnMut(T) -> T {
292        for v in &mut self.0 {
293            *v = f(*v)
294        }
295    }
296
297    fn map_with_alpha<F, G>(&self, f: F, g: G) -> $ident<T> where F: FnMut(T) -> T, G: FnMut(T) -> T {
298        let mut this = (*self).clone();
299        this.apply_with_alpha(f, g);
300        this
301    }
302
303    fn apply_with_alpha<F, G>(&mut self, mut f: F, mut g: G) where F: FnMut(T) -> T, G: FnMut(T) -> T {
304        const ALPHA: usize = $channels - $alphas;
305        for v in self.0[..ALPHA].iter_mut() {
306            *v = f(*v)
307        }
308        // The branch of this match is `const`. This way ensures that no subexpression fails the
309        // `const_err` lint (the expression `self.0[ALPHA]` would).
310        if let Some(v) = self.0.get_mut(ALPHA) {
311            *v = g(*v)
312        }
313    }
314
315    fn map2<F>(&self, other: &Self, f: F) -> $ident<T> where F: FnMut(T, T) -> T {
316        let mut this = (*self).clone();
317        this.apply2(other, f);
318        this
319    }
320
321    fn apply2<F>(&mut self, other: &$ident<T>, mut f: F) where F: FnMut(T, T) -> T {
322        for (a, &b) in self.0.iter_mut().zip(other.0.iter()) {
323            *a = f(*a, b)
324        }
325    }
326
327    fn invert(&mut self) {
328        Invert::invert(self)
329    }
330
331    fn blend(&mut self, other: &$ident<T>) {
332        Blend::blend(self, other)
333    }
334}
335
336impl<T> Index<usize> for $ident<T> {
337    type Output = T;
338    #[inline(always)]
339    fn index(&self, _index: usize) -> &T {
340        &self.0[_index]
341    }
342}
343
344impl<T> IndexMut<usize> for $ident<T> {
345    #[inline(always)]
346    fn index_mut(&mut self, _index: usize) -> &mut T {
347        &mut self.0[_index]
348    }
349}
350
351impl<T> From<[T; $channels]> for $ident<T> {
352    fn from(c: [T; $channels]) -> Self {
353        Self(c)
354    }
355}
356
357)* // END Structure definitions
358
359    }
360}
361
362define_colors! {
363    /// RGB colors.
364    ///
365    /// For the purpose of color conversion, as well as blending, the implementation of `Pixel`
366    /// assumes an `sRGB` color space of its data.
367    pub struct Rgb<T: Primitive Enlargeable>([T; 3, 0]) = "RGB";
368    /// Grayscale colors.
369    pub struct Luma<T: Primitive>([T; 1, 0]) = "Y";
370    /// RGB colors + alpha channel
371    pub struct Rgba<T: Primitive Enlargeable>([T; 4, 1]) = "RGBA";
372    /// Grayscale colors + alpha channel
373    pub struct LumaA<T: Primitive>([T; 2, 1]) = "YA";
374}
375
376/// Convert from one pixel component type to another. For example, convert from `u8` to `f32` pixel values.
377pub trait FromPrimitive<Component> {
378    /// Converts from any pixel component type to this type.
379    fn from_primitive(component: Component) -> Self;
380}
381
382impl<T: Primitive> FromPrimitive<T> for T {
383    fn from_primitive(sample: T) -> Self {
384        sample
385    }
386}
387
388// from f32:
389// Note that in to-integer-conversion we are performing rounding but NumCast::from is implemented
390// as truncate towards zero. We emulate rounding by adding a bias.
391
392impl FromPrimitive<f32> for u8 {
393    fn from_primitive(float: f32) -> Self {
394        let inner = (float.clamp(0.0, 1.0) * u8::MAX as f32).round();
395        NumCast::from(inner).unwrap()
396    }
397}
398
399impl FromPrimitive<f32> for u16 {
400    fn from_primitive(float: f32) -> Self {
401        let inner = (float.clamp(0.0, 1.0) * u16::MAX as f32).round();
402        NumCast::from(inner).unwrap()
403    }
404}
405
406// from u16:
407
408impl FromPrimitive<u16> for u8 {
409    fn from_primitive(c16: u16) -> Self {
410        fn from(c: impl Into<u32>) -> u32 {
411            c.into()
412        }
413        // The input c is the numerator of `c / u16::MAX`.
414        // Derive numerator of `num / u8::MAX`, with rounding.
415        //
416        // This method is based on the inverse (see FromPrimitive<u8> for u16) and was tested
417        // exhaustively in Python. It's the same as the reference function:
418        //  round(c * (2**8 - 1) / (2**16 - 1))
419        NumCast::from((from(c16) + 128) / 257).unwrap()
420    }
421}
422
423impl FromPrimitive<u16> for f32 {
424    fn from_primitive(int: u16) -> Self {
425        (int as f32 / u16::MAX as f32).clamp(0.0, 1.0)
426    }
427}
428
429// from u8:
430
431impl FromPrimitive<u8> for f32 {
432    fn from_primitive(int: u8) -> Self {
433        (int as f32 / u8::MAX as f32).clamp(0.0, 1.0)
434    }
435}
436
437impl FromPrimitive<u8> for u16 {
438    fn from_primitive(c8: u8) -> Self {
439        let x = c8.to_u64().unwrap();
440        NumCast::from((x << 8) | x).unwrap()
441    }
442}
443
444/// Provides color conversions for the different pixel types.
445pub trait FromColor<Other> {
446    /// Changes `self` to represent `Other` in the color space of `Self`
447    fn from_color(&mut self, _: &Other);
448}
449
450/// Copy-based conversions to target pixel types using `FromColor`.
451// FIXME: this trait should be removed and replaced with real color space models
452// rather than assuming sRGB.
453pub(crate) trait IntoColor<Other> {
454    /// Constructs a pixel of the target type and converts this pixel into it.
455    fn into_color(&self) -> Other;
456}
457
458impl<O, S> IntoColor<O> for S
459where
460    O: Pixel + FromColor<S>,
461{
462    fn into_color(&self) -> O {
463        // Note we cannot use Pixel::CHANNELS_COUNT here to directly construct
464        // the pixel due to a current bug/limitation of consts.
465        #[allow(deprecated)]
466        let mut pix = O::from_channels(Zero::zero(), Zero::zero(), Zero::zero(), Zero::zero());
467        pix.from_color(self);
468        pix
469    }
470}
471
472/// Coefficients to transform from sRGB to a CIE Y (luminance) value.
473const SRGB_LUMA: [u32; 3] = [2126, 7152, 722];
474const SRGB_LUMA_DIV: u32 = 10000;
475
476#[inline]
477fn rgb_to_luma<T: Primitive + Enlargeable>(rgb: &[T]) -> T {
478    let l = <T::Larger as NumCast>::from(SRGB_LUMA[0]).unwrap() * rgb[0].to_larger()
479        + <T::Larger as NumCast>::from(SRGB_LUMA[1]).unwrap() * rgb[1].to_larger()
480        + <T::Larger as NumCast>::from(SRGB_LUMA[2]).unwrap() * rgb[2].to_larger();
481    T::clamp_from(l / <T::Larger as NumCast>::from(SRGB_LUMA_DIV).unwrap())
482}
483
484// `FromColor` for Luma
485impl<S: Primitive, T: Primitive> FromColor<Luma<S>> for Luma<T>
486where
487    T: FromPrimitive<S>,
488{
489    fn from_color(&mut self, other: &Luma<S>) {
490        let own = self.channels_mut();
491        let other = other.channels();
492        own[0] = T::from_primitive(other[0]);
493    }
494}
495
496impl<S: Primitive, T: Primitive> FromColor<LumaA<S>> for Luma<T>
497where
498    T: FromPrimitive<S>,
499{
500    fn from_color(&mut self, other: &LumaA<S>) {
501        self.channels_mut()[0] = T::from_primitive(other.channels()[0])
502    }
503}
504
505impl<S: Primitive + Enlargeable, T: Primitive> FromColor<Rgb<S>> for Luma<T>
506where
507    T: FromPrimitive<S>,
508{
509    fn from_color(&mut self, other: &Rgb<S>) {
510        let gray = self.channels_mut();
511        let rgb = other.channels();
512        gray[0] = T::from_primitive(rgb_to_luma(rgb));
513    }
514}
515
516impl<S: Primitive + Enlargeable, T: Primitive> FromColor<Rgba<S>> for Luma<T>
517where
518    T: FromPrimitive<S>,
519{
520    fn from_color(&mut self, other: &Rgba<S>) {
521        let gray = self.channels_mut();
522        let rgb = other.channels();
523        let l = rgb_to_luma(rgb);
524        gray[0] = T::from_primitive(l);
525    }
526}
527
528// `FromColor` for LumaA
529
530impl<S: Primitive, T: Primitive> FromColor<LumaA<S>> for LumaA<T>
531where
532    T: FromPrimitive<S>,
533{
534    fn from_color(&mut self, other: &LumaA<S>) {
535        let own = self.channels_mut();
536        let other = other.channels();
537        own[0] = T::from_primitive(other[0]);
538        own[1] = T::from_primitive(other[1]);
539    }
540}
541
542impl<S: Primitive + Enlargeable, T: Primitive> FromColor<Rgb<S>> for LumaA<T>
543where
544    T: FromPrimitive<S>,
545{
546    fn from_color(&mut self, other: &Rgb<S>) {
547        let gray_a = self.channels_mut();
548        let rgb = other.channels();
549        gray_a[0] = T::from_primitive(rgb_to_luma(rgb));
550        gray_a[1] = T::DEFAULT_MAX_VALUE;
551    }
552}
553
554impl<S: Primitive + Enlargeable, T: Primitive> FromColor<Rgba<S>> for LumaA<T>
555where
556    T: FromPrimitive<S>,
557{
558    fn from_color(&mut self, other: &Rgba<S>) {
559        let gray_a = self.channels_mut();
560        let rgba = other.channels();
561        gray_a[0] = T::from_primitive(rgb_to_luma(rgba));
562        gray_a[1] = T::from_primitive(rgba[3]);
563    }
564}
565
566impl<S: Primitive, T: Primitive> FromColor<Luma<S>> for LumaA<T>
567where
568    T: FromPrimitive<S>,
569{
570    fn from_color(&mut self, other: &Luma<S>) {
571        let gray_a = self.channels_mut();
572        gray_a[0] = T::from_primitive(other.channels()[0]);
573        gray_a[1] = T::DEFAULT_MAX_VALUE;
574    }
575}
576
577// `FromColor` for RGBA
578
579impl<S: Primitive, T: Primitive> FromColor<Rgba<S>> for Rgba<T>
580where
581    T: FromPrimitive<S>,
582{
583    fn from_color(&mut self, other: &Rgba<S>) {
584        let own = &mut self.0;
585        let other = &other.0;
586        own[0] = T::from_primitive(other[0]);
587        own[1] = T::from_primitive(other[1]);
588        own[2] = T::from_primitive(other[2]);
589        own[3] = T::from_primitive(other[3]);
590    }
591}
592
593impl<S: Primitive, T: Primitive> FromColor<Rgb<S>> for Rgba<T>
594where
595    T: FromPrimitive<S>,
596{
597    fn from_color(&mut self, other: &Rgb<S>) {
598        let rgba = &mut self.0;
599        let rgb = &other.0;
600        rgba[0] = T::from_primitive(rgb[0]);
601        rgba[1] = T::from_primitive(rgb[1]);
602        rgba[2] = T::from_primitive(rgb[2]);
603        rgba[3] = T::DEFAULT_MAX_VALUE;
604    }
605}
606
607impl<S: Primitive, T: Primitive> FromColor<LumaA<S>> for Rgba<T>
608where
609    T: FromPrimitive<S>,
610{
611    fn from_color(&mut self, gray: &LumaA<S>) {
612        let rgba = &mut self.0;
613        let gray = &gray.0;
614        rgba[0] = T::from_primitive(gray[0]);
615        rgba[1] = T::from_primitive(gray[0]);
616        rgba[2] = T::from_primitive(gray[0]);
617        rgba[3] = T::from_primitive(gray[1]);
618    }
619}
620
621impl<S: Primitive, T: Primitive> FromColor<Luma<S>> for Rgba<T>
622where
623    T: FromPrimitive<S>,
624{
625    fn from_color(&mut self, gray: &Luma<S>) {
626        let rgba = &mut self.0;
627        let gray = gray.0[0];
628        rgba[0] = T::from_primitive(gray);
629        rgba[1] = T::from_primitive(gray);
630        rgba[2] = T::from_primitive(gray);
631        rgba[3] = T::DEFAULT_MAX_VALUE;
632    }
633}
634
635// `FromColor` for RGB
636
637impl<S: Primitive, T: Primitive> FromColor<Rgb<S>> for Rgb<T>
638where
639    T: FromPrimitive<S>,
640{
641    fn from_color(&mut self, other: &Rgb<S>) {
642        let own = &mut self.0;
643        let other = &other.0;
644        own[0] = T::from_primitive(other[0]);
645        own[1] = T::from_primitive(other[1]);
646        own[2] = T::from_primitive(other[2]);
647    }
648}
649
650impl<S: Primitive, T: Primitive> FromColor<Rgba<S>> for Rgb<T>
651where
652    T: FromPrimitive<S>,
653{
654    fn from_color(&mut self, other: &Rgba<S>) {
655        let rgb = &mut self.0;
656        let rgba = &other.0;
657        rgb[0] = T::from_primitive(rgba[0]);
658        rgb[1] = T::from_primitive(rgba[1]);
659        rgb[2] = T::from_primitive(rgba[2]);
660    }
661}
662
663impl<S: Primitive, T: Primitive> FromColor<LumaA<S>> for Rgb<T>
664where
665    T: FromPrimitive<S>,
666{
667    fn from_color(&mut self, other: &LumaA<S>) {
668        let rgb = &mut self.0;
669        let gray = other.0[0];
670        rgb[0] = T::from_primitive(gray);
671        rgb[1] = T::from_primitive(gray);
672        rgb[2] = T::from_primitive(gray);
673    }
674}
675
676impl<S: Primitive, T: Primitive> FromColor<Luma<S>> for Rgb<T>
677where
678    T: FromPrimitive<S>,
679{
680    fn from_color(&mut self, other: &Luma<S>) {
681        let rgb = &mut self.0;
682        let gray = other.0[0];
683        rgb[0] = T::from_primitive(gray);
684        rgb[1] = T::from_primitive(gray);
685        rgb[2] = T::from_primitive(gray);
686    }
687}
688
689/// Blends a color inter another one
690pub(crate) trait Blend {
691    /// Blends a color in-place.
692    fn blend(&mut self, other: &Self);
693}
694
695impl<T: Primitive> Blend for LumaA<T> {
696    fn blend(&mut self, other: &LumaA<T>) {
697        let max_t = T::DEFAULT_MAX_VALUE;
698        let max_t = max_t.to_f32().unwrap();
699        let (bg_luma, bg_a) = (self.0[0], self.0[1]);
700        let (fg_luma, fg_a) = (other.0[0], other.0[1]);
701
702        let (bg_luma, bg_a) = (
703            bg_luma.to_f32().unwrap() / max_t,
704            bg_a.to_f32().unwrap() / max_t,
705        );
706        let (fg_luma, fg_a) = (
707            fg_luma.to_f32().unwrap() / max_t,
708            fg_a.to_f32().unwrap() / max_t,
709        );
710
711        let alpha_final = bg_a + fg_a - bg_a * fg_a;
712        if alpha_final == 0.0 {
713            return;
714        };
715        let bg_luma_a = bg_luma * bg_a;
716        let fg_luma_a = fg_luma * fg_a;
717
718        let out_luma_a = fg_luma_a + bg_luma_a * (1.0 - fg_a);
719        let out_luma = out_luma_a / alpha_final;
720
721        *self = LumaA([
722            NumCast::from(max_t * out_luma).unwrap(),
723            NumCast::from(max_t * alpha_final).unwrap(),
724        ])
725    }
726}
727
728impl<T: Primitive> Blend for Luma<T> {
729    fn blend(&mut self, other: &Luma<T>) {
730        *self = *other
731    }
732}
733
734impl<T: Primitive> Blend for Rgba<T> {
735    fn blend(&mut self, other: &Rgba<T>) {
736        // http://stackoverflow.com/questions/7438263/alpha-compositing-algorithm-blend-modes#answer-11163848
737
738        if other.0[3].is_zero() {
739            return;
740        }
741        if other.0[3] == T::DEFAULT_MAX_VALUE {
742            *self = *other;
743            return;
744        }
745
746        // First, as we don't know what type our pixel is, we have to convert to floats between 0.0 and 1.0
747        let max_t = T::DEFAULT_MAX_VALUE;
748        let max_t = max_t.to_f32().unwrap();
749        let (bg_r, bg_g, bg_b, bg_a) = (self.0[0], self.0[1], self.0[2], self.0[3]);
750        let (fg_r, fg_g, fg_b, fg_a) = (other.0[0], other.0[1], other.0[2], other.0[3]);
751        let (bg_r, bg_g, bg_b, bg_a) = (
752            bg_r.to_f32().unwrap() / max_t,
753            bg_g.to_f32().unwrap() / max_t,
754            bg_b.to_f32().unwrap() / max_t,
755            bg_a.to_f32().unwrap() / max_t,
756        );
757        let (fg_r, fg_g, fg_b, fg_a) = (
758            fg_r.to_f32().unwrap() / max_t,
759            fg_g.to_f32().unwrap() / max_t,
760            fg_b.to_f32().unwrap() / max_t,
761            fg_a.to_f32().unwrap() / max_t,
762        );
763
764        // Work out what the final alpha level will be
765        let alpha_final = bg_a + fg_a - bg_a * fg_a;
766        if alpha_final == 0.0 {
767            return;
768        };
769
770        // We premultiply our channels by their alpha, as this makes it easier to calculate
771        let (bg_r_a, bg_g_a, bg_b_a) = (bg_r * bg_a, bg_g * bg_a, bg_b * bg_a);
772        let (fg_r_a, fg_g_a, fg_b_a) = (fg_r * fg_a, fg_g * fg_a, fg_b * fg_a);
773
774        // Standard formula for src-over alpha compositing
775        let (out_r_a, out_g_a, out_b_a) = (
776            fg_r_a + bg_r_a * (1.0 - fg_a),
777            fg_g_a + bg_g_a * (1.0 - fg_a),
778            fg_b_a + bg_b_a * (1.0 - fg_a),
779        );
780
781        // Unmultiply the channels by our resultant alpha channel
782        let (out_r, out_g, out_b) = (
783            out_r_a / alpha_final,
784            out_g_a / alpha_final,
785            out_b_a / alpha_final,
786        );
787
788        // Cast back to our initial type on return
789        *self = Rgba([
790            NumCast::from(max_t * out_r).unwrap(),
791            NumCast::from(max_t * out_g).unwrap(),
792            NumCast::from(max_t * out_b).unwrap(),
793            NumCast::from(max_t * alpha_final).unwrap(),
794        ])
795    }
796}
797
798impl<T: Primitive> Blend for Rgb<T> {
799    fn blend(&mut self, other: &Rgb<T>) {
800        *self = *other
801    }
802}
803
804/// Invert a color
805pub(crate) trait Invert {
806    /// Inverts a color in-place.
807    fn invert(&mut self);
808}
809
810impl<T: Primitive> Invert for LumaA<T> {
811    fn invert(&mut self) {
812        let l = self.0;
813        let max = T::DEFAULT_MAX_VALUE;
814
815        *self = LumaA([max - l[0], l[1]])
816    }
817}
818
819impl<T: Primitive> Invert for Luma<T> {
820    fn invert(&mut self) {
821        let l = self.0;
822
823        let max = T::DEFAULT_MAX_VALUE;
824        let l1 = max - l[0];
825
826        *self = Luma([l1])
827    }
828}
829
830impl<T: Primitive> Invert for Rgba<T> {
831    fn invert(&mut self) {
832        let rgba = self.0;
833
834        let max = T::DEFAULT_MAX_VALUE;
835
836        *self = Rgba([max - rgba[0], max - rgba[1], max - rgba[2], rgba[3]])
837    }
838}
839
840impl<T: Primitive> Invert for Rgb<T> {
841    fn invert(&mut self) {
842        let rgb = self.0;
843
844        let max = T::DEFAULT_MAX_VALUE;
845
846        let r1 = max - rgb[0];
847        let g1 = max - rgb[1];
848        let b1 = max - rgb[2];
849
850        *self = Rgb([r1, g1, b1])
851    }
852}
853
854#[cfg(test)]
855mod tests {
856    use super::{Luma, LumaA, Pixel, Rgb, Rgba};
857
858    #[test]
859    fn test_apply_with_alpha_rgba() {
860        let mut rgba = Rgba([0, 0, 0, 0]);
861        rgba.apply_with_alpha(|s| s, |_| 0xFF);
862        assert_eq!(rgba, Rgba([0, 0, 0, 0xFF]));
863    }
864
865    #[test]
866    fn test_apply_with_alpha_rgb() {
867        let mut rgb = Rgb([0, 0, 0]);
868        rgb.apply_with_alpha(|s| s, |_| panic!("bug"));
869        assert_eq!(rgb, Rgb([0, 0, 0]));
870    }
871
872    #[test]
873    fn test_map_with_alpha_rgba() {
874        let rgba = Rgba([0, 0, 0, 0]).map_with_alpha(|s| s, |_| 0xFF);
875        assert_eq!(rgba, Rgba([0, 0, 0, 0xFF]));
876    }
877
878    #[test]
879    fn test_map_with_alpha_rgb() {
880        let rgb = Rgb([0, 0, 0]).map_with_alpha(|s| s, |_| panic!("bug"));
881        assert_eq!(rgb, Rgb([0, 0, 0]));
882    }
883
884    #[test]
885    fn test_blend_luma_alpha() {
886        let a = &mut LumaA([255_u8, 255]);
887        let b = LumaA([255_u8, 255]);
888        a.blend(&b);
889        assert_eq!(a.0[0], 255);
890        assert_eq!(a.0[1], 255);
891
892        let a = &mut LumaA([255_u8, 0]);
893        let b = LumaA([255_u8, 255]);
894        a.blend(&b);
895        assert_eq!(a.0[0], 255);
896        assert_eq!(a.0[1], 255);
897
898        let a = &mut LumaA([255_u8, 255]);
899        let b = LumaA([255_u8, 0]);
900        a.blend(&b);
901        assert_eq!(a.0[0], 255);
902        assert_eq!(a.0[1], 255);
903
904        let a = &mut LumaA([255_u8, 0]);
905        let b = LumaA([255_u8, 0]);
906        a.blend(&b);
907        assert_eq!(a.0[0], 255);
908        assert_eq!(a.0[1], 0);
909    }
910
911    #[test]
912    fn test_blend_rgba() {
913        let a = &mut Rgba([255_u8, 255, 255, 255]);
914        let b = Rgba([255_u8, 255, 255, 255]);
915        a.blend(&b);
916        assert_eq!(a.0, [255, 255, 255, 255]);
917
918        let a = &mut Rgba([255_u8, 255, 255, 0]);
919        let b = Rgba([255_u8, 255, 255, 255]);
920        a.blend(&b);
921        assert_eq!(a.0, [255, 255, 255, 255]);
922
923        let a = &mut Rgba([255_u8, 255, 255, 255]);
924        let b = Rgba([255_u8, 255, 255, 0]);
925        a.blend(&b);
926        assert_eq!(a.0, [255, 255, 255, 255]);
927
928        let a = &mut Rgba([255_u8, 255, 255, 0]);
929        let b = Rgba([255_u8, 255, 255, 0]);
930        a.blend(&b);
931        assert_eq!(a.0, [255, 255, 255, 0]);
932    }
933
934    #[test]
935    fn test_apply_without_alpha_rgba() {
936        let mut rgba = Rgba([0, 0, 0, 0]);
937        rgba.apply_without_alpha(|s| s + 1);
938        assert_eq!(rgba, Rgba([1, 1, 1, 0]));
939    }
940
941    #[test]
942    fn test_apply_without_alpha_rgb() {
943        let mut rgb = Rgb([0, 0, 0]);
944        rgb.apply_without_alpha(|s| s + 1);
945        assert_eq!(rgb, Rgb([1, 1, 1]));
946    }
947
948    #[test]
949    fn test_map_without_alpha_rgba() {
950        let rgba = Rgba([0, 0, 0, 0]).map_without_alpha(|s| s + 1);
951        assert_eq!(rgba, Rgba([1, 1, 1, 0]));
952    }
953
954    #[test]
955    fn test_map_without_alpha_rgb() {
956        let rgb = Rgb([0, 0, 0]).map_without_alpha(|s| s + 1);
957        assert_eq!(rgb, Rgb([1, 1, 1]));
958    }
959
960    macro_rules! test_lossless_conversion {
961        ($a:ty, $b:ty, $c:ty) => {
962            let a: $a = [<$a as Pixel>::Subpixel::DEFAULT_MAX_VALUE >> 2;
963                <$a as Pixel>::CHANNEL_COUNT as usize]
964                .into();
965            let b: $b = a.into_color();
966            let c: $c = b.into_color();
967            assert_eq!(a.channels(), c.channels());
968        };
969    }
970
971    #[test]
972    fn test_lossless_conversions() {
973        use super::IntoColor;
974        use crate::traits::Primitive;
975
976        test_lossless_conversion!(Luma<u8>, Luma<u16>, Luma<u8>);
977        test_lossless_conversion!(LumaA<u8>, LumaA<u16>, LumaA<u8>);
978        test_lossless_conversion!(Rgb<u8>, Rgb<u16>, Rgb<u8>);
979        test_lossless_conversion!(Rgba<u8>, Rgba<u16>, Rgba<u8>);
980    }
981
982    #[test]
983    fn accuracy_conversion() {
984        use super::{Luma, Pixel, Rgb};
985        let pixel = Rgb::from([13, 13, 13]);
986        let Luma([luma]) = pixel.to_luma();
987        assert_eq!(luma, 13);
988    }
989}