From afb91b552eaf57abb2c4a11266bf29812b274d53 Mon Sep 17 00:00:00 2001 From: thewoz Date: Fri, 29 Mar 2024 08:51:19 +0100 Subject: [PATCH] Merge pull request #24415 from thewoz:imread Add imread #24415 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [X] I agree to contribute to the project under Apache 2 License. - [X] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [X] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake Hello everyone, I created this new version of the imread function and I think it can be very useful in several cases. It is actually passed to it object on which you want to upload the image. The advantages can be different like in case one needs to open several large images all the same in sequence. one can use the same pointer and the system would not allocate memory each time. --- .../imgcodecs/include/opencv2/imgcodecs.hpp | 11 ++++++++ modules/imgcodecs/src/loadsave.cpp | 21 ++++++++++++++- modules/imgcodecs/test/test_png.cpp | 13 +++++++++ modules/python/test/test_imread.py | 27 +++++++++++++++++++ modules/python/test/test_pathlike.py | 2 +- 5 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 modules/python/test/test_imread.py diff --git a/modules/imgcodecs/include/opencv2/imgcodecs.hpp b/modules/imgcodecs/include/opencv2/imgcodecs.hpp index 85ddb838f5..df02eaf021 100644 --- a/modules/imgcodecs/include/opencv2/imgcodecs.hpp +++ b/modules/imgcodecs/include/opencv2/imgcodecs.hpp @@ -228,6 +228,17 @@ Currently, the following file formats are supported: */ CV_EXPORTS_W Mat imread( const String& filename, int flags = IMREAD_COLOR ); +/** @brief Loads an image from a file. + +This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts and the return value. +@param filename Name of file to be loaded. +@param dst object in which the image will be loaded. +@param flags Flag that can take values of cv::ImreadModes +@note +The image passing through the img parameter can be pre-allocated. The memory is reused if the shape and the type match with the load image. + */ +CV_EXPORTS_W void imread( const String& filename, OutputArray dst, int flags = IMREAD_COLOR ); + /** @brief Loads a multi-page image from a file. The function imreadmulti loads a multi-page image from the specified file into a vector of Mat objects. diff --git a/modules/imgcodecs/src/loadsave.cpp b/modules/imgcodecs/src/loadsave.cpp index bc28efe49b..2586fc1fa4 100644 --- a/modules/imgcodecs/src/loadsave.cpp +++ b/modules/imgcodecs/src/loadsave.cpp @@ -457,7 +457,16 @@ imread_( const String& filename, int flags, Mat& mat ) type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1); } - mat.create( size.height, size.width, type ); + if (mat.empty()) + { + mat.create( size.height, size.width, type ); + } + else + { + CV_CheckEQ(size, mat.size(), ""); + CV_CheckTypeEQ(type, mat.type(), ""); + CV_Assert(mat.isContinuous()); + } // read the image data bool success = false; @@ -632,6 +641,16 @@ Mat imread( const String& filename, int flags ) return img; } +void imread( const String& filename, OutputArray dst, int flags ) +{ + CV_TRACE_FUNCTION(); + + Mat img = dst.getMat(); + + /// load the data + imread_(filename, flags, img); +} + /** * Read a multi-page image * diff --git a/modules/imgcodecs/test/test_png.cpp b/modules/imgcodecs/test/test_png.cpp index cdc7da39b2..655c59430d 100644 --- a/modules/imgcodecs/test/test_png.cpp +++ b/modules/imgcodecs/test/test_png.cpp @@ -7,6 +7,19 @@ namespace opencv_test { namespace { #if defined(HAVE_PNG) || defined(HAVE_SPNG) +TEST(Imgcodecs_Png, imread_passing_mat) +{ + const string root = cvtest::TS::ptr()->get_data_path(); + const string imgName = root + "../cv/shared/lena.png"; + + Mat ref = imread(imgName); + Mat img(ref.size(), ref.type()); + void* ptr = img.data; + imread(imgName, img); + EXPECT_EQ(cv::norm(ref, img, NORM_INF), 0); + EXPECT_EQ(img.data, ptr); +} + TEST(Imgcodecs_Png, write_big) { const string root = cvtest::TS::ptr()->get_data_path(); diff --git a/modules/python/test/test_imread.py b/modules/python/test/test_imread.py new file mode 100644 index 0000000000..b5f286d426 --- /dev/null +++ b/modules/python/test/test_imread.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python + +''' +Test for imread +''' + +# Python 2/3 compatibility +from __future__ import print_function + +import cv2 as cv +import numpy as np +import sys + +from tests_common import NewOpenCVTests + +class imread_test(NewOpenCVTests): + def test_imread_to_buffer(self): + path = self.extraTestDataPath + '/cv/shared/lena.png' + ref = cv.imread(path) + + img = np.zeros_like(ref) + cv.imread(path, img) + self.assertEqual(cv.norm(ref, img, cv.NORM_INF), 0.0) + + +if __name__ == '__main__': + NewOpenCVTests.bootstrap() diff --git a/modules/python/test/test_pathlike.py b/modules/python/test/test_pathlike.py index d654ce24ad..9122a757ce 100644 --- a/modules/python/test/test_pathlike.py +++ b/modules/python/test/test_pathlike.py @@ -28,7 +28,7 @@ class CanPassPathLike(NewOpenCVTests): def test_type_mismatch(self): import_path() # checks python version - with self.assertRaises(TypeError) as context: + with self.assertRaises(cv.error) as context: cv.imread(123) self.assertTrue('str or path-like' in str(context.exception))