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}