use std::{fmt, fmt::Display}; use rgb::{RGB16, RGBA8}; use crate::PngError; #[derive(Debug, PartialEq, Eq, Clone)] /// The color type used to represent this image pub enum ColorType { /// Grayscale, with one color channel Grayscale { /// Optional shade of gray that should be rendered as transparent transparent_shade: Option, }, /// RGB, with three color channels RGB { /// Optional color value that should be rendered as transparent transparent_color: Option, }, /// Indexed, with one byte per pixel representing a color from the palette Indexed { /// The palette containing the colors used, up to 256 entries palette: Vec, }, /// Grayscale + Alpha, with two color channels GrayscaleAlpha, /// RGBA, with four color channels RGBA, } impl Display for ColorType { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { ColorType::Grayscale { .. } => Display::fmt("Grayscale", f), ColorType::RGB { .. } => Display::fmt("RGB", f), ColorType::Indexed { palette } => { Display::fmt(&format!("Indexed ({} colors)", palette.len()), f) } ColorType::GrayscaleAlpha => Display::fmt("Grayscale + Alpha", f), ColorType::RGBA => Display::fmt("RGB + Alpha", f), } } } impl ColorType { /// Get the code used by the PNG specification to denote this color type #[inline] pub fn png_header_code(&self) -> u8 { match self { ColorType::Grayscale { .. } => 0, ColorType::RGB { .. } => 2, ColorType::Indexed { .. } => 3, ColorType::GrayscaleAlpha => 4, ColorType::RGBA => 6, } } #[inline] pub(crate) fn channels_per_pixel(&self) -> u8 { match self { ColorType::Grayscale { .. } | ColorType::Indexed { .. } => 1, ColorType::GrayscaleAlpha => 2, ColorType::RGB { .. } => 3, ColorType::RGBA => 4, } } #[inline] pub(crate) fn is_rgb(&self) -> bool { matches!(self, ColorType::RGB { .. } | ColorType::RGBA) } #[inline] pub(crate) fn is_gray(&self) -> bool { matches!( self, ColorType::Grayscale { .. } | ColorType::GrayscaleAlpha ) } #[inline] pub(crate) fn has_alpha(&self) -> bool { matches!(self, ColorType::GrayscaleAlpha | ColorType::RGBA) } #[inline] pub(crate) fn has_trns(&self) -> bool { match self { ColorType::Grayscale { transparent_shade } => transparent_shade.is_some(), ColorType::RGB { transparent_color } => transparent_color.is_some(), _ => false, } } } #[repr(u8)] #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] /// The number of bits to be used per channel per pixel pub enum BitDepth { /// One bit per channel per pixel One = 1, /// Two bits per channel per pixel Two = 2, /// Four bits per channel per pixel Four = 4, /// Eight bits per channel per pixel Eight = 8, /// Sixteen bits per channel per pixel Sixteen = 16, } impl TryFrom for BitDepth { type Error = PngError; fn try_from(value: u8) -> Result { match value { 1 => Ok(Self::One), 2 => Ok(Self::Two), 4 => Ok(Self::Four), 8 => Ok(Self::Eight), 16 => Ok(Self::Sixteen), _ => Err(PngError::new("Unexpected bit depth")), } } } impl Display for BitDepth { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { Display::fmt(&(*self as u8).to_string(), f) } }