Maraiah/maraiah/image/pict/pm/ind.rs

87 lines
1.7 KiB
Rust

//! 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<Image8>
{
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::<u8>(&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<u8>, depth: pm::head::Depth) -> ResultS<Vec<u8>>
{
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