//! Image and color representations. pub mod pict; pub mod ppm; pub mod tga; /// Creates a RGB8 color from a R5G5B5 format color. /// /// # Examples /// /// ``` /// use maraiah::image::{r5g5b5_to_rgb8, Color8}; /// /// assert_eq!(r5g5b5_to_rgb8(0x2345), Color8::new(64, 208, 40)); /// ``` #[inline] pub const fn r5g5b5_to_rgb8(rgb: u16) -> Color8 { let r = (rgb >> 10) as u8 & 0x1f; let g = (rgb >> 5) as u8 & 0x1f; let b = rgb as u8 & 0x1f; Color8::new(r << 3, g << 3, b << 3) } /// Creates a RGB16 color from a R5G5B5 format color. /// /// # Examples /// /// ``` /// use maraiah::image::{r5g5b5_to_rgb16, Color16}; /// /// assert_eq!(r5g5b5_to_rgb16(0x2345), /// Color16::new(0x4000, 0xD000, 0x2800)); /// ``` #[inline] pub const fn r5g5b5_to_rgb16(rgb: u16) -> Color16 { let r = rgb >> 10 & 0x1f; let g = rgb >> 5 & 0x1f; let b = rgb & 0x1f; Color16::new(r << 11, g << 11, b << 11) } /// Creates a RGB16 color from a RGB8 format color. /// /// # Examples /// /// ``` /// use maraiah::image; /// /// let inpl = image::r5g5b5_to_rgb8(0x2345); /// let inph = image::r5g5b5_to_rgb16(0x2345); /// /// assert_eq!(inph, image::rgb8_to_rgb16(inpl)); /// ``` pub fn rgb8_to_rgb16(cr: Color8) -> Color16 { Color16::new(cr.r(), cr.g(), cr.b()) } /// A generic color matrix image. pub trait Image { /// The type of color this image uses for each pixel. type Output: Color; /// Returns the width of the image. fn w(&self) -> usize; /// Returns the height of the image. fn h(&self) -> usize; /// Returns the color of the pixel at column `x` at row `y`. /// /// # Panics /// /// Panics if `x` is greater than the width of the image or `y` is greater /// than the height of the image. fn index(&self, x: usize, y: usize) -> &Self::Output; /// The same as `index`, but will not panic if out of bounds. fn get(&self, x: usize, y: usize) -> Option<&Self::Output> { if x < self.w() && y < self.h() { Some(self.index(x, y)) } else { None } } } /// A generic color matrix image, which may be mutated. pub trait ImageMut: Image { /// Returns the color of the pixel at column `x` at row `y`. /// /// # Panics /// /// Panics if `x` is greater than the width of the image or `y` is greater /// than the height of the image. fn index_mut(&mut self, x: usize, y: usize) -> &mut Self::Output; /// The same as `index_mut`, but will not panic if out of bounds. fn get_mut(&mut self, x: usize, y: usize) -> Option<&mut Self::Output> { if x < self.w() && y < self.h() { Some(self.index_mut(x, y)) } else { None } } } /// Any color which may be represented as RGBA16. pub trait Color: Sized + Copy + Clone + Eq + PartialEq { /// Returns the red component. fn r(&self) -> u16; /// Returns the green component. fn g(&self) -> u16; /// Returns the blue component. fn b(&self) -> u16; /// Returns the alpha component. fn a(&self) -> u16; } impl Image16 { /// Creates a new Image16 with no canvas. pub fn new(w: usize, h: usize) -> Self { Self{w, h, cr: Vec::with_capacity(w * h)} } /// Creates a new Image16 with an empty canvas. pub fn new_empty(w: usize, h: usize) -> Self { Self{w, h, cr: vec![Color16::new(0, 0, 0); w * h]} } } impl Image for Image16 { type Output = Color16; fn w(&self) -> usize {self.w} fn h(&self) -> usize {self.h} fn index(&self, x: usize, y: usize) -> &Self::Output { &self.cr[x + y * self.w] } } impl ImageMut for Image16 { fn index_mut(&mut self, x: usize, y: usize) -> &mut Self::Output { &mut self.cr[x + y * self.w] } } impl Image8 { /// Creates a new Image8 with no canvas. pub fn new(w: usize, h: usize) -> Self { Self{w, h, cr: Vec::with_capacity(w * h)} } /// Creates a new Image8 with an empty canvas. pub fn new_empty(w: usize, h: usize) -> Self { Self{w, h, cr: vec![Color8::new(0, 0, 0); w * h]} } } impl Image for Image8 { type Output = Color8; fn w(&self) -> usize {self.w} fn h(&self) -> usize {self.h} fn index(&self, x: usize, y: usize) -> &Self::Output { &self.cr[x + y * self.w] } } impl ImageMut for Image8 { fn index_mut(&mut self, x: usize, y: usize) -> &mut Self::Output { &mut self.cr[x + y * self.w] } } impl Color16 { pub const fn new(r: u16, g: u16, b: u16) -> Self {Self(r, g, b)} } impl Color for Color16 { fn r(&self) -> u16 {self.0} fn g(&self) -> u16 {self.1} fn b(&self) -> u16 {self.2} fn a(&self) -> u16 {u16::max_value()} } impl Color8 { pub const fn new(r: u8, g: u8, b: u8) -> Self {Self(r, g, b)} } impl Color for Color8 { fn r(&self) -> u16 {u16::from(self.0) << 8} fn g(&self) -> u16 {u16::from(self.1) << 8} fn b(&self) -> u16 {u16::from(self.2) << 8} fn a(&self) -> u16 {u16::max_value()} } /// An RGB16 color. #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct Color16(u16, u16, u16); /// An RGB8 color. #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct Color8(u8, u8, u8); /// An RGB16 image. #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[derive(Debug, Eq, PartialEq)] pub struct Image16 { w: usize, h: usize, /// The raw color data for this image. pub cr: Vec, } /// An RGB8 image. #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[derive(Debug, Eq, PartialEq)] pub struct Image8 { w: usize, h: usize, /// The raw color data for this image. pub cr: Vec, } // EOF