Maraiah/maraiah/image/pict/rle.rs

95 lines
1.7 KiB
Rust

//! QuickDraw PICT format run length encoded data.
use crate::{bin::*, err::*};
/// Read run-length encoded data.
pub fn read<T>(b: &[u8], pitch: usize) -> ResultS<(Vec<T>, usize)>
where T: ReadRleData
{
let mut p = 0;
let mut o = Vec::with_capacity(pitch);
let sz = if pitch > 250 {
(usize::from(u16b(b)) + 2, p += 2).0
} else {
(usize::from(b[0]) + 1, p += 1).0
};
while p < sz {
let szf = b[p];
let cmp = szf & 0x80 != 0;
let len = usize::from(if cmp {!szf + 2} else {szf + 1});
p += 1;
o.reserve(len);
T::read_rle_data(b, &mut p, cmp, len, &mut o);
}
if o.len() == pitch {
Ok((o, p))
} else {
Err(err_msg("incorrect size for compressed scanline"))
}
}
pub trait ReadRleData: Sized
{
// Read a sequence of packed RLE data.
fn read_rle_data(b: &[u8],
p: &mut usize,
cmp: bool,
len: usize,
out: &mut Vec<Self>);
}
impl ReadRleData for u16
{
fn read_rle_data(b: &[u8],
p: &mut usize,
cmp: bool,
len: usize,
out: &mut Vec<Self>)
{
if cmp {
let d = u16b(&b[*p..*p + 2]);
*p += 2;
for _ in 0..len {
out.push(d);
}
} else {
for _ in 0..len {
let d = u16b(&b[*p..*p + 2]);
*p += 2;
out.push(d);
}
}
}
}
impl ReadRleData for u8
{
fn read_rle_data(b: &[u8],
p: &mut usize,
cmp: bool,
len: usize,
out: &mut Vec<Self>)
{
if cmp {
let d = b[*p];
*p += 1;
for _ in 0..len {
out.push(d);
}
} else {
for _ in 0..len {
let d = b[*p];
*p += 1;
out.push(d);
}
}
}
}
// EOF