2022-01-03 14:14:01 +00:00
|
|
|
use core::convert::TryFrom;
|
2021-12-31 10:34:27 +00:00
|
|
|
|
|
|
|
use crate::error::{Error, Result};
|
|
|
|
use crate::utils::unlikely;
|
|
|
|
|
|
|
|
/// Image color space.
|
|
|
|
///
|
|
|
|
/// Note: the color space is purely informative. Although it is saved to the
|
|
|
|
/// file header, it does not affect encoding/decoding in any way.
|
2022-01-03 10:41:54 +00:00
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
|
2021-12-31 10:34:27 +00:00
|
|
|
#[repr(u8)]
|
|
|
|
pub enum ColorSpace {
|
|
|
|
/// sRGB with linear alpha
|
|
|
|
Srgb = 0,
|
|
|
|
/// All channels are linear
|
|
|
|
Linear = 1,
|
2021-11-29 22:23:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl ColorSpace {
|
2022-01-03 17:43:55 +00:00
|
|
|
/// Returns true if the color space is sRGB with linear alpha.
|
2021-11-29 22:23:39 +00:00
|
|
|
pub const fn is_srgb(self) -> bool {
|
2021-12-31 10:34:27 +00:00
|
|
|
matches!(self, Self::Srgb)
|
2021-11-29 22:23:39 +00:00
|
|
|
}
|
|
|
|
|
2022-01-03 17:43:55 +00:00
|
|
|
/// Returns true is all channels are linear.
|
2021-11-29 22:23:39 +00:00
|
|
|
pub const fn is_linear(self) -> bool {
|
2021-12-31 10:34:27 +00:00
|
|
|
matches!(self, Self::Linear)
|
2021-11-29 22:23:39 +00:00
|
|
|
}
|
2022-01-03 09:00:18 +00:00
|
|
|
|
2022-01-03 17:43:55 +00:00
|
|
|
/// Converts to an integer (0 if sRGB, 1 if all linear).
|
2022-01-03 09:00:18 +00:00
|
|
|
pub const fn as_u8(self) -> u8 {
|
|
|
|
self as u8
|
|
|
|
}
|
2021-11-29 22:23:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for ColorSpace {
|
|
|
|
fn default() -> Self {
|
2021-12-31 10:34:27 +00:00
|
|
|
Self::Srgb
|
2021-11-29 22:23:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<ColorSpace> for u8 {
|
2021-12-31 10:34:27 +00:00
|
|
|
#[inline]
|
|
|
|
fn from(colorspace: ColorSpace) -> Self {
|
2021-12-31 10:37:56 +00:00
|
|
|
colorspace as Self
|
2021-11-29 22:23:39 +00:00
|
|
|
}
|
|
|
|
}
|
2021-12-01 17:17:12 +00:00
|
|
|
|
2021-12-31 10:34:27 +00:00
|
|
|
impl TryFrom<u8> for ColorSpace {
|
|
|
|
type Error = Error;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn try_from(colorspace: u8) -> Result<Self> {
|
|
|
|
if unlikely(colorspace | 1 != 1) {
|
|
|
|
Err(Error::InvalidColorSpace { colorspace })
|
|
|
|
} else {
|
|
|
|
Ok(if colorspace == 0 { Self::Srgb } else { Self::Linear })
|
|
|
|
}
|
2021-12-01 17:17:12 +00:00
|
|
|
}
|
|
|
|
}
|
2022-01-02 21:47:13 +00:00
|
|
|
|
2022-01-03 17:43:55 +00:00
|
|
|
/// Number of 8-bit channels in a pixel.
|
2022-01-03 10:41:54 +00:00
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
|
2022-01-02 21:47:13 +00:00
|
|
|
#[repr(u8)]
|
|
|
|
pub enum Channels {
|
|
|
|
/// Three 8-bit channels (RGB)
|
|
|
|
Rgb = 3,
|
|
|
|
/// Four 8-bit channels (RGBA)
|
|
|
|
Rgba = 4,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Channels {
|
2022-01-03 17:43:55 +00:00
|
|
|
/// Returns true if there are 3 channels (RGB).
|
2022-01-02 21:47:13 +00:00
|
|
|
pub const fn is_rgb(self) -> bool {
|
|
|
|
matches!(self, Self::Rgb)
|
|
|
|
}
|
|
|
|
|
2022-01-03 17:43:55 +00:00
|
|
|
/// Returns true if there are 4 channels (RGBA).
|
2022-01-02 21:47:13 +00:00
|
|
|
pub const fn is_rgba(self) -> bool {
|
|
|
|
matches!(self, Self::Rgba)
|
|
|
|
}
|
|
|
|
|
2022-01-03 17:43:55 +00:00
|
|
|
/// Converts to an integer (3 if RGB, 4 if RGBA).
|
2022-01-02 21:47:13 +00:00
|
|
|
pub const fn as_u8(self) -> u8 {
|
|
|
|
self as u8
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for Channels {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self::Rgb
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<Channels> for u8 {
|
|
|
|
#[inline]
|
|
|
|
fn from(channels: Channels) -> Self {
|
|
|
|
channels as Self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TryFrom<u8> for Channels {
|
|
|
|
type Error = Error;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn try_from(channels: u8) -> Result<Self> {
|
|
|
|
if unlikely(channels != 3 && channels != 4) {
|
|
|
|
Err(Error::InvalidChannels { channels })
|
|
|
|
} else {
|
|
|
|
Ok(if channels == 3 { Self::Rgb } else { Self::Rgba })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|