Skip to content

Commit

Permalink
webp frames iterator is now ending iteration if no more frames are de…
Browse files Browse the repository at this point in the history
…codable (#2228)
  • Loading branch information
EmiOnGit authored May 16, 2024
1 parent bc05c8c commit 1207aca
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 2 deletions.
10 changes: 9 additions & 1 deletion src/codecs/webp/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,16 @@ impl<'a, R: 'a + Read + Seek> AnimationDecoder<'a> for WebPDecoder<R> {
fn into_frames(self) -> Frames<'a> {
struct FramesInner<R: Read + Seek> {
decoder: WebPDecoder<R>,
current: u32,
}
impl<R: Read + Seek> Iterator for FramesInner<R> {
type Item = ImageResult<Frame>;

fn next(&mut self) -> Option<Self::Item> {
if self.current == self.decoder.inner.num_frames() {
return None;
}
self.current += 1;
let (width, height) = self.decoder.inner.dimensions();

let (img, delay) = if self.decoder.inner.has_alpha() {
Expand All @@ -98,7 +103,10 @@ impl<'a, R: 'a + Read + Seek> AnimationDecoder<'a> for WebPDecoder<R> {
}
}

Frames::new(Box::new(FramesInner { decoder: self }))
Frames::new(Box::new(FramesInner {
decoder: self,
current: 0,
}))
}
}

Expand Down
33 changes: 32 additions & 1 deletion tests/regression.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
use std::{fs::File, io::BufReader, path::PathBuf};
use std::{
fs::{self, File},
io::{BufReader, Cursor},
path::PathBuf,
};

#[cfg(feature = "webp")]
use image::{codecs::webp::WebPDecoder, AnimationDecoder};

const BASE_PATH: [&str; 2] = [".", "tests"];
const IMAGE_DIR: &str = "images";
Expand Down Expand Up @@ -37,6 +44,30 @@ fn check_regressions() {
let _ = image::open(path);
})
}
/// Check that the WEBP frames iterator returns the right amount of frames.
#[test]
#[cfg(feature = "webp")]
fn check_webp_frames_regressions() {
let path: PathBuf = BASE_PATH
.iter()
.collect::<PathBuf>()
.join(IMAGE_DIR)
.join("webp/extended_images")
.join("*.webp");
let pattern = &*format!("{}", path.display());
for path in glob::glob(pattern).unwrap().filter_map(Result::ok) {
let bytes = fs::read(path).unwrap();
let cursor = Cursor::new(&bytes);
let frame_count = image_webp::WebPDecoder::new(cursor.clone())
.unwrap()
.num_frames() as usize;
let decoder = WebPDecoder::new(cursor).unwrap();
// The `take` guards against a potentially infinitely running iterator.
// Since we take `frame_count + 1`, we can assume that the last iteration already returns `None`.
let actual_frame_count = decoder.into_frames().take(frame_count + 1).count();
assert_eq!(actual_frame_count, frame_count);
}
}

/// Check that BMP files with large values could cause OOM issues are rejected.
///
Expand Down

0 comments on commit 1207aca

Please sign in to comment.