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