86 lines
2.2 KiB
Rust
86 lines
2.2 KiB
Rust
//! QuickDraw PICT indexed `PixMap`s.
|
|
|
|
use crate::{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), "invalid 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
|
|
};
|
|
|
|
p += pp;
|
|
|
|
for &idx in &d {
|
|
im.cr
|
|
.push(ok!(clut.get(usize::from(idx)), "invalid 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
|