//! QuickDraw PICT indexed `PixMap`s. use crate::{bin::check_data, err::*, image::{*, pict::{pm, rle}}}; /// Reads an indexed `PixMap`. pub fn read(mut im: Image8, b: &[u8], hdr: pm::head::Header) -> ResultS { let clut = ok!(hdr.clut, "no CLUT in indexed mode")?; let mut p = 0; if hdr.pitch < 8 && hdr.depth == pm::head::Depth::_8 { // uncompressed 8-bit colormap indices for _ in 0..im.h() { for _ in 0..im.w() { let idx = usize::from(b[p]); im.cr.push(ok!(clut.get(idx), "bad index")?.clone()); p += 1; } } Ok(im) } else if hdr.rle { // RLE compressed 1, 2, 4 or 8 bit colormap indices for _ in 0..im.h() { let (d, pp) = rle::read::(&b[p..], hdr.pitch)?; let d = if hdr.depth < pm::head::Depth::_8 { expand_data(d, hdr.depth)? } else { d }; check_data(&d, im.w())?; p += pp; for &idx in &d { im.cr.push(ok!(clut.get(usize::from(idx)), "bad index")?.clone()); } } Ok(im) } else { bail!("invalid configuration") } } /// Expand packed pixel data based on bit depth. pub fn expand_data(b: Vec, depth: pm::head::Depth) -> ResultS> { let mut o = Vec::with_capacity(match depth { pm::head::Depth::_4 => b.len() * 2, pm::head::Depth::_2 => b.len() * 4, pm::head::Depth::_1 => b.len() * 8, _ => bail!("invalid bit depth"), }); for ch in b { match depth { pm::head::Depth::_4 => { for i in (0..=1).rev() { o.push(ch >> (i * 4) & 0xF_u8); } } pm::head::Depth::_2 => { for i in (0..=3).rev() { o.push(ch >> (i * 2) & 0x3_u8); } } pm::head::Depth::_1 => { for i in (0..=7).rev() { o.push(ch >> i & 0x1_u8); } } _ => bail!("invalid bit depth"), } } Ok(o) } // EOF