use std::io::{BufRead, Seek};
use image::{codecs::gif::GifDecoder, AnimationDecoder};
use crate::{examine, model::Classification, Model, Result};
pub struct GifParser<'a> {
frames: image::Frames<'a>,
model: &'a Model,
}
impl<'a> GifParser<'a> {
pub fn new<R: BufRead + Seek + 'a>(gif: GifDecoder<R>, model: &'a Model) -> Self {
let frames = gif.into_frames();
Self { frames, model }
}
}
impl<'a> Iterator for GifParser<'a> {
type Item = Result<Vec<Classification>>;
fn next(&mut self) -> Option<Self::Item> {
let frame = self.frames.next();
match frame {
Some(Ok(frame)) => Some(examine(self.model, &frame.into_buffer())),
Some(Err(e)) => Some(Err(e.into())),
None => None,
}
}
}
#[cfg(test)]
mod test {
use crate::MODEL;
use image::codecs::gif::GifDecoder;
use std::{fs::File, io::BufReader};
use super::{GifParser, Result};
#[tokio::test]
async fn test_gif() -> Result<()> {
let gif_path = concat!(env!("CARGO_MANIFEST_DIR"), "/test/puffBounce.gif");
let file = BufReader::new(File::open(gif_path)?);
let frames = GifParser::new(GifDecoder::new(file)?, &MODEL);
for frame in frames {
assert!(frame.is_ok());
}
Ok(())
}
}