//! Image and color representations. use crate::durandal::{err::*, traits::*}; use std::io; /// Creates a RGB8 color from a R5G5B5 format color. pub fn r5g5b5_to_rgb8(rgb: u16) -> Color8 { let r = rgb >> 10 & 0x1f; let g = rgb >> 5 & 0x1f; let b = rgb & 0x1f; Color8::new((r << 3 | r >> 2) as u8, (g << 3 | g >> 2) as u8, (b << 3 | b >> 2) as u8) } /// Creates a RGB16 color from a R5G5B5 format color. pub 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. pub fn rgb8_to_rgb16(r: u8, g: u8, b: u8) -> Color16 { Color16::new(r as (u16) << 8, g as (u16) << 8, b as (u16) << 8) } /// Writes a PPM file from an image. pub fn write_ppm(out: &mut impl io::Write, im: &T) -> ResultS<()> { write!(out, "P3\n{} {}\n{}\n", im.w(), im.h(), T::Output::MAX)?; for y in 0..im.h() { for x in 0..im.w() { let cr = ok!(im.cr_at(x, y), "not enough data in image")?; write!(out, "{} {} {} ", cr.r(), cr.g(), cr.b())?; } } Ok(()) } pub trait Image { type Output: Color; fn w(&self) -> usize; fn h(&self) -> usize; fn cr_at(&self, x: usize, y: usize) -> Option<&Self::Output>; } pub trait Color { type Output: PrimInt; const MAX: u32; fn r(&self) -> Self::Output; fn g(&self) -> Self::Output; fn b(&self) -> Self::Output; fn a(&self) -> Self::Output; } impl Image16 { /// Creates a new Image16. pub fn new(w: usize, h: usize) -> Image16 { Image16{w, h, cr: Vec::with_capacity(w * h)} } } impl Image for Image16 { type Output = Color16; fn w(&self) -> usize {self.w} fn h(&self) -> usize {self.h} fn cr_at(&self, x: usize, y: usize) -> Option<&Color16> { self.cr.get(x + y * self.w) } } impl Image8 { /// Creates a new Image8. pub fn new(w: usize, h: usize) -> Image8 { Image8{w, h, cr: Vec::with_capacity(w * h)} } } impl Image for Image8 { type Output = Color8; fn w(&self) -> usize {self.w} fn h(&self) -> usize {self.h} fn cr_at(&self, x: usize, y: usize) -> Option<&Color8> { self.cr.get(x + y * self.w) } } impl Color16 { pub const fn new(r: u16, g: u16, b: u16) -> Color16 { Color16(r, g, b) } } impl Color for Color16 { type Output = u16; const MAX: u32 = u16::max_value() as u32; 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) -> Color8 { Color8(r, g, b) } } impl Color for Color8 { type Output = u8; const MAX: u32 = u8::max_value() as u32; fn r(&self) -> u8 {self.0} fn g(&self) -> u8 {self.1} fn b(&self) -> u8 {self.2} fn a(&self) -> u8 {u8::max_value()} } /// A RGB16 color. #[derive(Clone, Debug, PartialEq)] pub struct Color16(u16, u16, u16); /// A RGB8 color. #[derive(Clone, Debug, PartialEq)] pub struct Color8(u8, u8, u8); /// RGB16 image. pub struct Image16 { w: usize, h: usize, pub cr: Vec, } /// RGB16 image. pub struct Image8 { w: usize, h: usize, pub cr: Vec, } // EOF