use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
#[non_exhaustive]
pub enum ColorSpace {
#[default]
Bt709,
Bt470bg,
Smpte170m,
Bt2020Ncl,
Bt2020Cl,
Rgb,
Fcc,
Smpte240m,
Ycgco,
Unknown,
}
impl ColorSpace {
#[must_use]
pub const fn name(&self) -> &'static str {
match self {
Self::Bt709 => "bt709",
Self::Bt470bg => "bt470bg",
Self::Smpte170m => "smpte170m",
Self::Bt2020Ncl => "bt2020ncl",
Self::Bt2020Cl => "bt2020cl",
Self::Rgb => "rgb",
Self::Fcc => "fcc",
Self::Smpte240m => "smpte240m",
Self::Ycgco => "ycgco",
Self::Unknown => "unknown",
}
}
#[must_use]
pub const fn is_hd(&self) -> bool {
matches!(self, Self::Bt709)
}
#[must_use]
pub const fn is_sd(&self) -> bool {
matches!(self, Self::Bt470bg | Self::Smpte170m)
}
#[must_use]
pub const fn is_uhd(&self) -> bool {
matches!(self, Self::Bt2020Ncl | Self::Bt2020Cl)
}
#[must_use]
pub const fn is_unknown(&self) -> bool {
matches!(self, Self::Unknown)
}
}
impl fmt::Display for ColorSpace {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.name())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
#[non_exhaustive]
pub enum ColorRange {
#[default]
Limited,
Full,
Unknown,
}
impl ColorRange {
#[must_use]
pub const fn name(&self) -> &'static str {
match self {
Self::Limited => "limited",
Self::Full => "full",
Self::Unknown => "unknown",
}
}
#[must_use]
pub const fn is_full(&self) -> bool {
matches!(self, Self::Full)
}
#[must_use]
pub const fn is_limited(&self) -> bool {
matches!(self, Self::Limited)
}
#[must_use]
pub const fn is_unknown(&self) -> bool {
matches!(self, Self::Unknown)
}
#[must_use]
pub const fn luma_min_8bit(&self) -> u8 {
match self {
Self::Limited => 16,
Self::Full | Self::Unknown => 0,
}
}
#[must_use]
pub const fn luma_max_8bit(&self) -> u8 {
match self {
Self::Limited => 235,
Self::Full | Self::Unknown => 255,
}
}
}
impl fmt::Display for ColorRange {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.name())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
#[non_exhaustive]
pub enum ColorPrimaries {
#[default]
Bt709,
Bt470bg,
Smpte170m,
Smpte240m,
Film,
DciP3,
DisplayP3,
Bt2020,
Unknown,
}
impl ColorPrimaries {
#[must_use]
pub const fn name(&self) -> &'static str {
match self {
Self::Bt709 => "bt709",
Self::Bt470bg => "bt470bg",
Self::Smpte170m => "smpte170m",
Self::Smpte240m => "smpte240m",
Self::Film => "film",
Self::DciP3 => "dci-p3",
Self::DisplayP3 => "display-p3",
Self::Bt2020 => "bt2020",
Self::Unknown => "unknown",
}
}
#[must_use]
pub const fn is_wide_gamut(&self) -> bool {
matches!(self, Self::Bt2020 | Self::DciP3 | Self::DisplayP3)
}
#[must_use]
pub const fn is_unknown(&self) -> bool {
matches!(self, Self::Unknown)
}
}
impl fmt::Display for ColorPrimaries {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.name())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
#[non_exhaustive]
pub enum ColorTransfer {
#[default]
Bt709,
Gamma22,
Gamma28,
Smpte170m,
Smpte240m,
Linear,
Srgb,
Bt2020_10,
Bt2020_12,
Pq,
Hlg,
Unknown,
}
impl ColorTransfer {
#[must_use]
pub const fn name(&self) -> &'static str {
match self {
Self::Bt709 => "bt709",
Self::Gamma22 => "gamma22",
Self::Gamma28 => "gamma28",
Self::Smpte170m => "smpte170m",
Self::Smpte240m => "smpte240m",
Self::Linear => "linear",
Self::Srgb => "srgb",
Self::Bt2020_10 => "bt2020-10",
Self::Bt2020_12 => "bt2020-12",
Self::Pq => "pq",
Self::Hlg => "hlg",
Self::Unknown => "unknown",
}
}
#[must_use]
pub const fn is_hdr(&self) -> bool {
matches!(self, Self::Pq | Self::Hlg)
}
#[must_use]
pub const fn is_hlg(&self) -> bool {
matches!(self, Self::Hlg)
}
#[must_use]
pub const fn is_pq(&self) -> bool {
matches!(self, Self::Pq)
}
#[must_use]
pub const fn is_unknown(&self) -> bool {
matches!(self, Self::Unknown)
}
}
impl fmt::Display for ColorTransfer {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.name())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
#[non_exhaustive]
pub enum AlphaMode {
#[default]
Straight,
Premultiplied,
Unknown,
}
impl AlphaMode {
#[must_use]
pub const fn name(&self) -> &'static str {
match self {
Self::Straight => "straight",
Self::Premultiplied => "premultiplied",
Self::Unknown => "unknown",
}
}
#[must_use]
pub const fn is_straight(&self) -> bool {
matches!(self, Self::Straight)
}
#[must_use]
pub const fn is_premultiplied(&self) -> bool {
matches!(self, Self::Premultiplied)
}
#[must_use]
pub const fn is_unknown(&self) -> bool {
matches!(self, Self::Unknown)
}
}
impl fmt::Display for AlphaMode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.name())
}
}
#[cfg(test)]
mod tests {
use super::*;
mod color_space_tests {
use super::*;
#[test]
fn test_names() {
assert_eq!(ColorSpace::Bt709.name(), "bt709");
assert_eq!(ColorSpace::Bt470bg.name(), "bt470bg");
assert_eq!(ColorSpace::Smpte170m.name(), "smpte170m");
assert_eq!(ColorSpace::Bt2020Ncl.name(), "bt2020ncl");
assert_eq!(ColorSpace::Bt2020Cl.name(), "bt2020cl");
assert_eq!(ColorSpace::Rgb.name(), "rgb");
assert_eq!(ColorSpace::Fcc.name(), "fcc");
assert_eq!(ColorSpace::Smpte240m.name(), "smpte240m");
assert_eq!(ColorSpace::Ycgco.name(), "ycgco");
assert_eq!(ColorSpace::Unknown.name(), "unknown");
}
#[test]
fn test_display() {
assert_eq!(format!("{}", ColorSpace::Bt709), "bt709");
assert_eq!(format!("{}", ColorSpace::Bt2020Ncl), "bt2020ncl");
}
#[test]
fn test_default() {
assert_eq!(ColorSpace::default(), ColorSpace::Bt709);
}
#[test]
fn test_is_hd_sd_uhd() {
assert!(ColorSpace::Bt709.is_hd());
assert!(!ColorSpace::Bt709.is_sd());
assert!(!ColorSpace::Bt709.is_uhd());
assert!(!ColorSpace::Smpte170m.is_hd());
assert!(ColorSpace::Smpte170m.is_sd());
assert!(ColorSpace::Bt470bg.is_sd());
assert!(!ColorSpace::Smpte170m.is_uhd());
assert!(!ColorSpace::Bt2020Ncl.is_hd());
assert!(!ColorSpace::Bt2020Ncl.is_sd());
assert!(ColorSpace::Bt2020Ncl.is_uhd());
assert!(ColorSpace::Bt2020Cl.is_uhd());
}
#[test]
fn test_is_unknown() {
assert!(ColorSpace::Unknown.is_unknown());
assert!(!ColorSpace::Bt709.is_unknown());
}
#[test]
fn test_debug() {
assert_eq!(format!("{:?}", ColorSpace::Bt709), "Bt709");
assert_eq!(format!("{:?}", ColorSpace::Rgb), "Rgb");
}
#[test]
fn test_equality_and_hash() {
use std::collections::HashSet;
assert_eq!(ColorSpace::Bt709, ColorSpace::Bt709);
assert_ne!(ColorSpace::Bt709, ColorSpace::Smpte170m);
let mut set = HashSet::new();
set.insert(ColorSpace::Bt709);
set.insert(ColorSpace::Smpte170m);
assert!(set.contains(&ColorSpace::Bt709));
assert!(!set.contains(&ColorSpace::Bt2020Ncl));
}
#[test]
fn test_copy() {
let space = ColorSpace::Bt709;
let copied = space;
assert_eq!(space, copied);
}
}
mod color_range_tests {
use super::*;
#[test]
fn test_names() {
assert_eq!(ColorRange::Limited.name(), "limited");
assert_eq!(ColorRange::Full.name(), "full");
assert_eq!(ColorRange::Unknown.name(), "unknown");
}
#[test]
fn test_display() {
assert_eq!(format!("{}", ColorRange::Limited), "limited");
assert_eq!(format!("{}", ColorRange::Full), "full");
}
#[test]
fn test_default() {
assert_eq!(ColorRange::default(), ColorRange::Limited);
}
#[test]
fn test_is_full_limited() {
assert!(ColorRange::Full.is_full());
assert!(!ColorRange::Full.is_limited());
assert!(!ColorRange::Limited.is_full());
assert!(ColorRange::Limited.is_limited());
}
#[test]
fn test_is_unknown() {
assert!(ColorRange::Unknown.is_unknown());
assert!(!ColorRange::Limited.is_unknown());
}
#[test]
fn test_luma_values() {
assert_eq!(ColorRange::Limited.luma_min_8bit(), 16);
assert_eq!(ColorRange::Limited.luma_max_8bit(), 235);
assert_eq!(ColorRange::Full.luma_min_8bit(), 0);
assert_eq!(ColorRange::Full.luma_max_8bit(), 255);
assert_eq!(ColorRange::Unknown.luma_min_8bit(), 0);
assert_eq!(ColorRange::Unknown.luma_max_8bit(), 255);
}
#[test]
fn test_equality_and_hash() {
use std::collections::HashSet;
assert_eq!(ColorRange::Limited, ColorRange::Limited);
assert_ne!(ColorRange::Limited, ColorRange::Full);
let mut set = HashSet::new();
set.insert(ColorRange::Limited);
set.insert(ColorRange::Full);
assert!(set.contains(&ColorRange::Limited));
assert!(!set.contains(&ColorRange::Unknown));
}
}
mod color_primaries_tests {
use super::*;
#[test]
fn test_names() {
assert_eq!(ColorPrimaries::Bt709.name(), "bt709");
assert_eq!(ColorPrimaries::Bt470bg.name(), "bt470bg");
assert_eq!(ColorPrimaries::Smpte170m.name(), "smpte170m");
assert_eq!(ColorPrimaries::Smpte240m.name(), "smpte240m");
assert_eq!(ColorPrimaries::Film.name(), "film");
assert_eq!(ColorPrimaries::DciP3.name(), "dci-p3");
assert_eq!(ColorPrimaries::DisplayP3.name(), "display-p3");
assert_eq!(ColorPrimaries::Bt2020.name(), "bt2020");
assert_eq!(ColorPrimaries::Unknown.name(), "unknown");
}
#[test]
fn test_display() {
assert_eq!(format!("{}", ColorPrimaries::Bt709), "bt709");
assert_eq!(format!("{}", ColorPrimaries::Bt2020), "bt2020");
}
#[test]
fn test_default() {
assert_eq!(ColorPrimaries::default(), ColorPrimaries::Bt709);
}
#[test]
fn test_is_wide_gamut() {
assert!(ColorPrimaries::Bt2020.is_wide_gamut());
assert!(ColorPrimaries::DciP3.is_wide_gamut());
assert!(ColorPrimaries::DisplayP3.is_wide_gamut());
assert!(!ColorPrimaries::Bt709.is_wide_gamut());
assert!(!ColorPrimaries::Smpte170m.is_wide_gamut());
}
#[test]
fn test_is_unknown() {
assert!(ColorPrimaries::Unknown.is_unknown());
assert!(!ColorPrimaries::Bt709.is_unknown());
}
#[test]
fn test_equality_and_hash() {
use std::collections::HashSet;
assert_eq!(ColorPrimaries::Bt709, ColorPrimaries::Bt709);
assert_ne!(ColorPrimaries::Bt709, ColorPrimaries::Bt2020);
let mut set = HashSet::new();
set.insert(ColorPrimaries::Bt709);
set.insert(ColorPrimaries::Bt2020);
assert!(set.contains(&ColorPrimaries::Bt709));
assert!(!set.contains(&ColorPrimaries::Smpte170m));
}
}
mod color_transfer_tests {
use super::*;
#[test]
fn test_names() {
assert_eq!(ColorTransfer::Bt709.name(), "bt709");
assert_eq!(ColorTransfer::Gamma22.name(), "gamma22");
assert_eq!(ColorTransfer::Gamma28.name(), "gamma28");
assert_eq!(ColorTransfer::Smpte170m.name(), "smpte170m");
assert_eq!(ColorTransfer::Smpte240m.name(), "smpte240m");
assert_eq!(ColorTransfer::Linear.name(), "linear");
assert_eq!(ColorTransfer::Srgb.name(), "srgb");
assert_eq!(ColorTransfer::Bt2020_10.name(), "bt2020-10");
assert_eq!(ColorTransfer::Bt2020_12.name(), "bt2020-12");
assert_eq!(ColorTransfer::Pq.name(), "pq");
assert_eq!(ColorTransfer::Hlg.name(), "hlg");
assert_eq!(ColorTransfer::Unknown.name(), "unknown");
}
#[test]
fn test_display() {
assert_eq!(format!("{}", ColorTransfer::Hlg), "hlg");
assert_eq!(format!("{}", ColorTransfer::Pq), "pq");
assert_eq!(format!("{}", ColorTransfer::Bt709), "bt709");
}
#[test]
fn test_default() {
assert_eq!(ColorTransfer::default(), ColorTransfer::Bt709);
}
#[test]
fn hlg_is_hdr_should_return_true() {
assert!(ColorTransfer::Hlg.is_hdr());
assert!(ColorTransfer::Hlg.is_hlg());
assert!(!ColorTransfer::Hlg.is_pq());
}
#[test]
fn pq_is_hdr_should_return_true() {
assert!(ColorTransfer::Pq.is_hdr());
assert!(ColorTransfer::Pq.is_pq());
assert!(!ColorTransfer::Pq.is_hlg());
}
#[test]
fn sdr_transfers_are_not_hdr() {
assert!(!ColorTransfer::Bt709.is_hdr());
assert!(!ColorTransfer::Gamma22.is_hdr());
assert!(!ColorTransfer::Gamma28.is_hdr());
assert!(!ColorTransfer::Smpte170m.is_hdr());
assert!(!ColorTransfer::Smpte240m.is_hdr());
assert!(!ColorTransfer::Srgb.is_hdr());
assert!(!ColorTransfer::Bt2020_10.is_hdr());
assert!(!ColorTransfer::Bt2020_12.is_hdr());
assert!(!ColorTransfer::Linear.is_hdr());
}
#[test]
fn is_unknown_should_only_match_unknown() {
assert!(ColorTransfer::Unknown.is_unknown());
assert!(!ColorTransfer::Bt709.is_unknown());
assert!(!ColorTransfer::Hlg.is_unknown());
}
#[test]
fn test_equality_and_hash() {
use std::collections::HashSet;
assert_eq!(ColorTransfer::Hlg, ColorTransfer::Hlg);
assert_ne!(ColorTransfer::Hlg, ColorTransfer::Pq);
let mut set = HashSet::new();
set.insert(ColorTransfer::Hlg);
set.insert(ColorTransfer::Pq);
assert!(set.contains(&ColorTransfer::Hlg));
assert!(!set.contains(&ColorTransfer::Bt709));
}
}
mod alpha_mode_tests {
use super::*;
#[test]
fn test_names() {
assert_eq!(AlphaMode::Straight.name(), "straight");
assert_eq!(AlphaMode::Premultiplied.name(), "premultiplied");
assert_eq!(AlphaMode::Unknown.name(), "unknown");
}
#[test]
fn test_display() {
assert_eq!(format!("{}", AlphaMode::Straight), "straight");
assert_eq!(format!("{}", AlphaMode::Premultiplied), "premultiplied");
assert_eq!(format!("{}", AlphaMode::Unknown), "unknown");
}
#[test]
fn test_default() {
assert_eq!(AlphaMode::default(), AlphaMode::Straight);
}
#[test]
fn is_straight_should_only_match_straight() {
assert!(AlphaMode::Straight.is_straight());
assert!(!AlphaMode::Premultiplied.is_straight());
assert!(!AlphaMode::Unknown.is_straight());
}
#[test]
fn is_premultiplied_should_only_match_premultiplied() {
assert!(AlphaMode::Premultiplied.is_premultiplied());
assert!(!AlphaMode::Straight.is_premultiplied());
assert!(!AlphaMode::Unknown.is_premultiplied());
}
#[test]
fn is_unknown_should_only_match_unknown() {
assert!(AlphaMode::Unknown.is_unknown());
assert!(!AlphaMode::Straight.is_unknown());
assert!(!AlphaMode::Premultiplied.is_unknown());
}
#[test]
fn test_equality_and_hash() {
use std::collections::HashSet;
assert_eq!(AlphaMode::Straight, AlphaMode::Straight);
assert_ne!(AlphaMode::Premultiplied, AlphaMode::Straight);
let mut set = HashSet::new();
set.insert(AlphaMode::Straight);
assert!(set.contains(&AlphaMode::Straight));
assert!(!set.contains(&AlphaMode::Premultiplied));
}
}
}