zune_core/
colorspace.rs

1/*
2 * Copyright (c) 2023.
3 *
4 * This software is free software;
5 *
6 * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license
7 */
8
9//! Image Colorspace information and manipulation utilities.
10
11/// All possible image colorspaces
12/// Some of them aren't yet supported exist here.
13#[allow(clippy::upper_case_acronyms)]
14#[derive(Copy, Clone, Debug, Eq, PartialEq)]
15#[non_exhaustive]
16pub enum ColorSpace {
17    /// Red, Green , Blue
18    RGB,
19    /// Red, Green, Blue, Alpha
20    RGBA,
21    /// YUV colorspace
22    YCbCr,
23    /// Grayscale colorspace
24    Luma,
25    /// Grayscale with alpha colorspace
26    LumaA,
27    YCCK,
28    /// Cyan , Magenta, Yellow, Black
29    CMYK,
30    /// Blue, Green, Red
31    BGR,
32    /// Blue, Green, Red, Alpha
33    BGRA,
34    /// The colorspace is unknown
35    Unknown,
36    /// Alpha Red Green Blue
37    ARGB,
38    /// Hue,Saturation,Lightness
39    /// Conversion from RGB to HSL and back matches that of Python [colorsys](https://docs.python.org/3/library/colorsys.html) module
40    /// Color type is expected to be in floating point
41    HSL,
42    /// Hue, Saturation,Value
43    ///
44    /// Conversion from RGB to HSV and back matches that of Python [colorsys](https://docs.python.org/3/library/colorsys.html) module
45    /// Color type is expected to be in floating point
46    HSV,
47    /// Multiple arbitrary image channels.
48    ///
49    /// This introduces **limited** support for multi-band/multichannel images
50    /// that can have n channels.
51    ///
52    /// The library contains optimized and well-supported routines for up to 4 image channels as is
53    /// more common out there, but some pipelines may require multi-band image support.
54    ///
55    /// For operations, multi-band images are assumed to be n-channel images with no alpha
56    /// to allow for generic processing, without necessarily caring for the underlying interpretation
57    MultiBand(core::num::NonZeroU32)
58}
59
60impl ColorSpace {
61    /// Number of color channels present for a certain colorspace
62    ///
63    /// E.g. RGB returns 3 since it contains R,G and B colors to make up a pixel
64    pub const fn num_components(&self) -> usize {
65        match self {
66            Self::RGB | Self::YCbCr | Self::BGR | Self::HSV | Self::HSL => 3,
67            Self::RGBA | Self::YCCK | Self::CMYK | Self::BGRA | Self::ARGB => 4,
68            Self::Luma => 1,
69            Self::LumaA => 2,
70            Self::Unknown => 0,
71            Self::MultiBand(n) => n.get() as usize
72        }
73    }
74
75    pub const fn has_alpha(&self) -> bool {
76        matches!(self, Self::RGBA | Self::LumaA | Self::BGRA | Self::ARGB)
77    }
78
79    pub const fn is_grayscale(&self) -> bool {
80        matches!(self, Self::LumaA | Self::Luma)
81    }
82
83    /// Returns the position of the alpha pixel in a pixel
84    ///
85    ///
86    /// That is for an array of color components say `[0,1,2,3]` if the image has an alpha channel
87    /// and is in RGBA format, this will return `Some(3)`, indicating alpha is found in the third index
88    /// but if the image is in `ARGB` format, it will return `Some(0)` indicating alpha is found in  
89    /// index 0
90    ///
91    /// If an image doesn't have an alpha channel returns `None`
92    ///
93    pub const fn alpha_position(&self) -> Option<usize> {
94        match self {
95            ColorSpace::RGBA => Some(3),
96            ColorSpace::LumaA => Some(1),
97            ColorSpace::BGRA => Some(3),
98            ColorSpace::ARGB => Some(0),
99            _ => None
100        }
101    }
102}
103
104/// Encapsulates all colorspaces supported by
105/// the library
106///
107/// This explicitly leaves out multi-band images
108pub static ALL_COLORSPACES: [ColorSpace; 12] = [
109    ColorSpace::RGB,
110    ColorSpace::RGBA,
111    ColorSpace::LumaA,
112    ColorSpace::Luma,
113    ColorSpace::CMYK,
114    ColorSpace::BGRA,
115    ColorSpace::BGR,
116    ColorSpace::YCCK,
117    ColorSpace::YCbCr,
118    ColorSpace::ARGB,
119    ColorSpace::HSL,
120    ColorSpace::HSV
121];
122
123/// Color characteristics
124///
125/// Gives more information about values in a certain
126/// colorspace
127#[allow(non_camel_case_types)]
128#[derive(Copy, Clone, Debug, PartialEq)]
129pub enum ColorCharacteristics {
130    /// Normal default gamma setting
131    /// The float contains gamma present
132    ///
133    /// The default gamma value is 2.2 but for
134    /// decoders that allow specifying gamma values,e.g PNG,
135    /// the gamma value becomes the specified value by the decoder
136    sRGB,
137    /// Linear transfer characteristics
138    /// The image is in linear colorspace
139    Linear
140}
141/// Represents a single channel color primary.
142///
143/// This can be viewed as a 3D coordinate of the color primary
144/// for a given colorspace
145#[derive(Default, Debug, Copy, Clone)]
146pub struct SingleColorPrimary {
147    pub x: f64,
148    pub y: f64,
149    pub z: f64
150}
151/// A collection of red,green and blue color primaries placed
152/// in one struct for easy manipulation
153#[derive(Default, Debug, Copy, Clone)]
154pub struct ColorPrimaries {
155    /// Red color primaries
156    pub red:   SingleColorPrimary,
157    /// Green color primaries
158    pub green: SingleColorPrimary,
159    /// Blue color primaries
160    pub blue:  SingleColorPrimary
161}
162
163/// Rendering intents indicate what one may want to do with colors outside of it's gamut
164///
165///
166/// Further reading
167///  - [IBM Rendering Intent](https://www.ibm.com/docs/en/i/7.5?topic=management-rendering-intents)
168///  - [ColorGate Blog](https://blog.colorgate.com/en/rendering-intent-explained)   
169#[derive(Eq, PartialEq, Clone, Copy, Debug)]
170pub enum RenderingIntent {
171    AbsoluteColorimetric,
172    Saturation,
173    RelativeColorimetric,
174    Perceptual
175}