//! Shapes file color lookup tables. use crate::{err::*, image::Color}; /// Reads a color from a color table into `clut`. pub fn read_color(b: &[u8], clut: &mut [ColorShp]) -> ResultS<()> { read_data! { endian: BIG, buf: b, size: 8, start: 0, data { let flag = u8[0]; let ind = u8[1]; let r = u16[2]; let g = u16[4]; let b = u16[6]; } } let cr = ok!(clut.get_mut(usize::from(ind)), "bad index")?; *cr = match flag { 128 => ColorShp::Lit {r, g, b}, 0 => ColorShp::Opaque{r, g, b}, _ => { return Err(err_msg("invalid flag in color")); } }; Ok(()) } /// Reads color tables from `b`. pub fn read(b: &[u8], tab_ofs: usize, tab_num: usize, clr_num: usize) -> ResultS> { let end = tab_num * clr_num * 8; let b = ok!(b.get(tab_ofs..tab_ofs + end), "bad offset")?; let mut v = vec![vec![ColorShp::Translucent; clr_num]; tab_num]; let mut p = 0; for clut in v.iter_mut().take(tab_num) { for _ in 0..clr_num { read_color(ok!(b.get(p..p + 8), "not enough data")?, clut)?; p += 8; } } Ok(v) } impl Color for ColorShp { fn r(&self) -> u16 { match *self { ColorShp::Translucent => 0, ColorShp::Opaque{r, ..} | ColorShp::Lit {r, ..} => r, } } fn g(&self) -> u16 { match *self { ColorShp::Translucent => 0, ColorShp::Opaque{g, ..} | ColorShp::Lit {g, ..} => g, } } fn b(&self) -> u16 { match *self { ColorShp::Translucent => 0, ColorShp::Opaque{b, ..} | ColorShp::Lit {b, ..} => b, } } fn a(&self) -> u16 { match *self { ColorShp::Translucent => 0, ColorShp::Opaque{..} | ColorShp::Lit {..} => u16::max_value(), } } } /// A color in a `Clut`. #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum ColorShp { /// A completely translucent color. Translucent, /// An opaque color which may be shaded. Opaque{/** The red component. */ r: u16, /** The green component. */ g: u16, /** The blue component. */ b: u16}, /// An opaque color which may not be shaded. Lit{/** The red component. */ r: u16, /** The green component. */ g: u16, /** The blue component. */ b: u16}, } /// A color collection. pub type Clut = Vec; // EOF