1use core::convert::TryFrom;
2
3use crate::error::{Error, Result};
4use crate::utils::unlikely;
5
6/// Image color space.
7///
8/// Note: the color space is purely informative. Although it is saved to the
9/// file header, it does not affect encoding/decoding in any way.
10#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
11#[repr(u8)]
12pub enum ColorSpace {
13 /// sRGB with linear alpha
14 Srgb = 0,
15 /// All channels are linear
16 Linear = 1,
17}
18
19impl ColorSpace {
20 /// Returns true if the color space is sRGB with linear alpha.
21 pub const fn is_srgb(self) -> bool {
22 matches!(self, Self::Srgb)
23 }
24
25 /// Returns true is all channels are linear.
26 pub const fn is_linear(self) -> bool {
27 matches!(self, Self::Linear)
28 }
29
30 /// Converts to an integer (0 if sRGB, 1 if all linear).
31 pub const fn as_u8(self) -> u8 {
32 self as u8
33 }
34}
35
36impl Default for ColorSpace {
37 fn default() -> Self {
38 Self::Srgb
39 }
40}
41
42impl From<ColorSpace> for u8 {
43 #[inline]
44 fn from(colorspace: ColorSpace) -> Self {
45 colorspace as Self
46 }
47}
48
49impl TryFrom<u8> for ColorSpace {
50 type Error = Error;
51
52 #[inline]
53 fn try_from(colorspace: u8) -> Result<Self> {
54 if unlikely(colorspace | 1 != 1) {
55 Err(Error::InvalidColorSpace { colorspace })
56 } else {
57 Ok(if colorspace == 0 { Self::Srgb } else { Self::Linear })
58 }
59 }
60}
61
62/// Number of 8-bit channels in a pixel.
63#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
64#[repr(u8)]
65pub enum Channels {
66 /// Three 8-bit channels (RGB)
67 Rgb = 3,
68 /// Four 8-bit channels (RGBA)
69 Rgba = 4,
70}
71
72impl Channels {
73 /// Returns true if there are 3 channels (RGB).
74 pub const fn is_rgb(self) -> bool {
75 matches!(self, Self::Rgb)
76 }
77
78 /// Returns true if there are 4 channels (RGBA).
79 pub const fn is_rgba(self) -> bool {
80 matches!(self, Self::Rgba)
81 }
82
83 /// Converts to an integer (3 if RGB, 4 if RGBA).
84 pub const fn as_u8(self) -> u8 {
85 self as u8
86 }
87}
88
89impl Default for Channels {
90 fn default() -> Self {
91 Self::Rgb
92 }
93}
94
95impl From<Channels> for u8 {
96 #[inline]
97 fn from(channels: Channels) -> Self {
98 channels as Self
99 }
100}
101
102impl TryFrom<u8> for Channels {
103 type Error = Error;
104
105 #[inline]
106 fn try_from(channels: u8) -> Result<Self> {
107 if unlikely(channels != 3 && channels != 4) {
108 Err(Error::InvalidChannels { channels })
109 } else {
110 Ok(if channels == 3 { Self::Rgb } else { Self::Rgba })
111 }
112 }
113}
114