From 6004badce2ad3d1e0d26f66fd48c1ed81ea5ac4c Mon Sep 17 00:00:00 2001 From: Suleyman TURKMEN Date: Mon, 10 Mar 2025 15:54:01 +0300 Subject: [PATCH] ImageCollection animations --- modules/imgcodecs/src/grfmt_gif.cpp | 5 +++ modules/imgcodecs/src/grfmt_png.cpp | 5 +++ modules/imgcodecs/test/test_animation.cpp | 45 +++++++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/modules/imgcodecs/src/grfmt_gif.cpp b/modules/imgcodecs/src/grfmt_gif.cpp index c229a45201..653b62ddc8 100644 --- a/modules/imgcodecs/src/grfmt_gif.cpp +++ b/modules/imgcodecs/src/grfmt_gif.cpp @@ -34,6 +34,11 @@ GifDecoder::~GifDecoder() { } bool GifDecoder::readHeader() { + if (m_frame_count > 1 /* if true, it means readHeader() was called before */) + { + return true; + } + if (!m_buf.empty()) { if (!m_strm.open(m_buf)) { return false; diff --git a/modules/imgcodecs/src/grfmt_png.cpp b/modules/imgcodecs/src/grfmt_png.cpp index 5eb4a379ae..dd5ac49a63 100644 --- a/modules/imgcodecs/src/grfmt_png.cpp +++ b/modules/imgcodecs/src/grfmt_png.cpp @@ -249,6 +249,11 @@ void PngDecoder::readDataFromBuf( void* _png_ptr, unsigned char* dst, size_t si bool PngDecoder::readHeader() { + if (m_frame_count > 1 /* if true, it means readHeader() was called before */) + { + return true; + } + // Declare dynamic variables before a potential longjmp. Chunk chunk; diff --git a/modules/imgcodecs/test/test_animation.cpp b/modules/imgcodecs/test/test_animation.cpp index 4e3f95013c..5bfb3dc231 100644 --- a/modules/imgcodecs/test/test_animation.cpp +++ b/modules/imgcodecs/test/test_animation.cpp @@ -543,6 +543,51 @@ TEST(Imgcodecs_APNG, imencode_rgba) EXPECT_EQ(read_frames.size(), s_animation.frames.size() - 2); } +typedef testing::TestWithParam Imgcodecs_ImageCollection; + +const string exts_multi[] = { +#ifdef HAVE_AVIF + ".avif", +#endif +#ifdef HAVE_IMGCODEC_GIF + ".gif", +#endif + ".png", +#ifdef HAVE_TIFF + ".tiff", +#endif +#ifdef HAVE_WEBP + ".webp", +#endif +}; + +TEST_P(Imgcodecs_ImageCollection, animations) +{ + Animation s_animation; + EXPECT_TRUE(fillFrames(s_animation, false)); + + string output = cv::tempfile(GetParam().c_str()); + ASSERT_TRUE(imwritemulti(output, s_animation.frames)); + vector read_frames; + ASSERT_TRUE(imreadmulti(output, read_frames, IMREAD_UNCHANGED)); + + { + ImageCollection collection(output, IMREAD_UNCHANGED); + EXPECT_EQ(read_frames.size(), collection.size()); + int i = 0; + for (auto&& frame : collection) + { + EXPECT_EQ(0, cvtest::norm(frame, read_frames[i], NORM_INF)); + ++i; + } + } + EXPECT_EQ(0, remove(output.c_str())); +} + +INSTANTIATE_TEST_CASE_P(/**/, + Imgcodecs_ImageCollection, + testing::ValuesIn(exts_multi)); + #endif // HAVE_PNG }} // namespace