use std::io::{Read, Seek};
use imagefmt::{bmp, ColFmt};
use crate::{
buffer::{cast, Buffer},
color,
error::{self, Error},
pixel,
};
pub struct Decoder<R: Read + Seek> {
inner: R,
}
impl<R: Read + Seek> Decoder<R> {
#[inline]
pub fn new(input: R) -> Self {
Decoder { inner: input }
}
}
impl<P, C, R> super::Decoder<P, C> for Decoder<R>
where
P: pixel::Write<C>,
P: From<color::Rgb> + From<color::Rgba>,
C: pixel::Channel,
R: Read + Seek,
{
fn frame(&mut self) -> error::Result<Buffer<P, C, Vec<C>>> {
let image = bmp::read(self.inner.by_ref(), ColFmt::Auto)?;
macro_rules! buffer {
($ch:ty, $ty:path) => {{
Ok(cast::Into::<P, C>::into(Buffer::<$ty, $ch, _>::from_raw(
image.w as u32,
image.h as u32,
image.buf,
)
.map_err(|_| Error::Format("wrong dimensions".into()))?))
}};
}
match image.fmt {
ColFmt::RGB => buffer!(u8, color::Rgb),
ColFmt::RGBA => buffer!(u8, color::Rgba),
_ => Err(Error::Unsupported("unsupported color type".into())),
}
}
}