image/
color.rs

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