diff --git a/modules/imgcodecs/include/opencv2/imgcodecs.hpp b/modules/imgcodecs/include/opencv2/imgcodecs.hpp index c3a1d4b082..62d895e473 100644 --- a/modules/imgcodecs/include/opencv2/imgcodecs.hpp +++ b/modules/imgcodecs/include/opencv2/imgcodecs.hpp @@ -305,11 +305,13 @@ The function imreadmulti loads a specified range from a multi-page image from th */ CV_EXPORTS_W bool imreadmulti(const String& filename, CV_OUT std::vector& mats, int start, int count, int flags = IMREAD_ANYCOLOR); -/** @brief Returns the number of images inside the give file +/** @brief Returns the number of images inside the given file -The function imcount will return the number of pages in a multi-page image, or 1 for single-page images +The function imcount returns the number of pages in a multi-page image (e.g. TIFF), the number of frames in an animation (e.g. AVIF), and 1 otherwise. +If the image cannot be decoded, 0 is returned. @param filename Name of file to be loaded. @param flags Flag that can take values of cv::ImreadModes, default with cv::IMREAD_ANYCOLOR. +@todo when cv::IMREAD_LOAD_GDAL flag used the return value will be 0 or 1 because OpenCV's GDAL decoder doesn't support multi-page reading yet. */ CV_EXPORTS_W size_t imcount(const String& filename, int flags = IMREAD_ANYCOLOR); diff --git a/modules/imgcodecs/src/grfmt_avif.cpp b/modules/imgcodecs/src/grfmt_avif.cpp index d71843c3f0..c1d3682d0c 100644 --- a/modules/imgcodecs/src/grfmt_avif.cpp +++ b/modules/imgcodecs/src/grfmt_avif.cpp @@ -195,6 +195,7 @@ bool AvifDecoder::readHeader() { m_width = decoder_->image->width; m_height = decoder_->image->height; + m_frame_count = decoder_->imageCount; channels_ = (decoder_->image->yuvFormat == AVIF_PIXEL_FORMAT_YUV400) ? 1 : 3; if (decoder_->alphaPresent) ++channels_; bit_depth_ = decoder_->image->depth; diff --git a/modules/imgcodecs/src/grfmt_base.cpp b/modules/imgcodecs/src/grfmt_base.cpp index da343941bd..6ae9d98f24 100644 --- a/modules/imgcodecs/src/grfmt_base.cpp +++ b/modules/imgcodecs/src/grfmt_base.cpp @@ -54,6 +54,7 @@ BaseImageDecoder::BaseImageDecoder() m_buf_supported = false; m_scale_denom = 1; m_use_rgb = false; + m_frame_count = 1; } diff --git a/modules/imgcodecs/src/grfmt_base.hpp b/modules/imgcodecs/src/grfmt_base.hpp index 0d98c51ae2..9ae23b24df 100644 --- a/modules/imgcodecs/src/grfmt_base.hpp +++ b/modules/imgcodecs/src/grfmt_base.hpp @@ -64,6 +64,7 @@ public: int width() const { return m_width; } int height() const { return m_height; } + size_t getFrameCount() const { return m_frame_count; } virtual int type() const { return m_type; } ExifEntry_t getExifTag(const ExifTagName tag) const; @@ -93,6 +94,7 @@ protected: bool m_buf_supported; bool m_use_rgb; // flag of decode image as RGB order instead of BGR. ExifReader m_exif; + size_t m_frame_count; }; diff --git a/modules/imgcodecs/src/grfmt_tiff.cpp b/modules/imgcodecs/src/grfmt_tiff.cpp index 41607006e2..f68a6e5c0d 100644 --- a/modules/imgcodecs/src/grfmt_tiff.cpp +++ b/modules/imgcodecs/src/grfmt_tiff.cpp @@ -279,6 +279,7 @@ bool TiffDecoder::readHeader() m_width = wdth; m_height = hght; + m_frame_count = TIFFNumberOfDirectories(tif); if (ncn == 3 && photometric == PHOTOMETRIC_LOGLUV) { m_type = CV_32FC3; diff --git a/modules/imgcodecs/src/loadsave.cpp b/modules/imgcodecs/src/loadsave.cpp index 354f2a4b34..8eedb0d907 100644 --- a/modules/imgcodecs/src/loadsave.cpp +++ b/modules/imgcodecs/src/loadsave.cpp @@ -1263,26 +1263,8 @@ void ImageCollection::Impl::init(String const& filename, int flags) { m_decoder->setSource(filename); CV_Assert(m_decoder->readHeader()); - // count the pages of the image collection - size_t count = 1; - while(m_decoder->nextPage()) count++; - - m_size = count; + m_size = m_decoder->getFrameCount(); m_pages.resize(m_size); - // Reinitialize the decoder because we advanced to the last page while counting the pages of the image -#ifdef HAVE_GDAL - if (m_flags != IMREAD_UNCHANGED && (m_flags & IMREAD_LOAD_GDAL) == IMREAD_LOAD_GDAL) { - m_decoder = GdalDecoder().newDecoder(); - } - else { -#endif - m_decoder = findDecoder(m_filename); -#ifdef HAVE_GDAL - } -#endif - - m_decoder->setSource(m_filename); - m_decoder->readHeader(); } size_t ImageCollection::Impl::size() const { return m_size; } diff --git a/modules/imgcodecs/test/test_avif.cpp b/modules/imgcodecs/test/test_avif.cpp index 227c69556d..68678599b2 100644 --- a/modules/imgcodecs/test/test_avif.cpp +++ b/modules/imgcodecs/test/test_avif.cpp @@ -296,6 +296,7 @@ TEST_P(Imgcodecs_Avif_Animation_WriteReadSuite, encode_decode) { return; } EXPECT_NO_THROW(cv::imwritemulti(output, anim_original, encoding_params_)); + EXPECT_EQ(anim_original.size(), imcount(output)); // Read from file. std::vector anim;