CARVIEW |
Navigation Menu
-
-
Notifications
You must be signed in to change notification settings - Fork 56.2k
imgcodecs: implement imencodemulti() #26211
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
{ | ||
vector<Mat> imgs; | ||
Mat img(100, 100, CV_8UC1); | ||
imgs.push_back(img); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Kumataro could you test
vector<Mat> imgs;
Mat img(100, 100, CV_8UC1);
imgs.push_back(img);
imgs.push_back(img.clone());
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your comment ! I mistakenly thought that it was enough to support multiple images for imencode().
But it seems that encoding multiple images requests reading callback function. After appending it, it works well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your comment ! I mistakenly thought that it was enough to support multiple images for imencode().
But it seems that encoding multiple images requests reading callback function. After appending it, it works well.
Thank you for your contribution. to me looks perfect.
modules/imgcodecs/src/loadsave.cpp
Outdated
if( (!encoder->isFormatSupported(image.depth())) && (encoder->isFormatSupported(CV_8U)) ) | ||
{ | ||
CV_Assert( encoder->isFormatSupported(CV_8U) ); | ||
CV_LOG_ONCE_WARNING(NULL, "Unsupported depth image for selected encoder is fallbacked to CV_8U."); | ||
image.convertTo( temp, CV_8U ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log is good, but we get U.B., if the encoder does not support CV_8U by some reason.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your review. This change comes from #26211 (comment) .
If there are no problem, I agree with revert it.
if( !encoder->isFormatSupported(image.depth() ) )
{
CV_LOG_ONCE_WARNING(NULL, "Unsupported depth image for selected encoder is fallbacked to CV_8U.");
CV_Assert( encoder->isFormatSupported(CV_8U) );
image.convertTo( temp, CV_8U );
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your review, I fixed it.
@Kumataro Thanks a lot for the contribution! I hide the function implementation in cpp file and got rid of exceptions that are thrown outside of the function. The current image i/o contract is to be exception-safe and return bool status. |
@@ -405,14 +405,28 @@ The function imencode compresses the image and stores it in the memory buffer th | |||
result. See cv::imwrite for the list of supported formats and flags description. | |||
|
|||
@param ext File extension that defines the output format. Must include a leading period. | |||
@param img Image to be written. | |||
@param img Image to be compressed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Mat or vector of Mat) Image or Images to be compressed.
@asmorkalov imwrite() writes single and multiple images. AFAIK imwritemulti() is just for python. also imencode() behaves same as imwrite()
imwritemulti() definition is like
//! @brief multi-image overload for bindings
CV_WRAP static inline
bool imwritemulti(const String& filename, InputArrayOfArrays img,
const std::vector<int>& params = std::vector<int>())
{
return imwrite(filename, img, params);
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think imwritemulti() also be defined as CV_EXPORTS_W and needs documentation
>>> help(cv2.imwritemulti)
Help on built-in function imwritemulti:
imwritemulti(...)
imwritemulti(filename, img[, params]) -> retval
.
I'm sorry some tests for AVIF are failed. AVIF encoder called CV_CheckDepth() and exception is happened. AVIF encoder calls CV_CheckType() with bit_depth == 6, img.depth() == CV_8U. cv::Exception will be thrown. CV_CheckType(
img.type(),
(bit_depth == 8 && img.depth() == CV_8U) ||
((bit_depth == 10 || bit_depth == 12) && img.depth() == CV_16U),
"AVIF only supports bit depth of 8 with CV_8U input or "
"bit depth of 10 or 12 with CV_16U input"); AVIF tests expect that cv::Exception throws. But they doesn't. TEST_P(Imgcodecs_Avif_Image_EncodeDecodeSuite, imencode_imdecode) {
const cv::Mat& img_original = get_img_original();
ASSERT_FALSE(img_original.empty());
// Encode.
std::vector<unsigned char> buf;
if (!IsBitDepthValid()) {
EXPECT_THROW(cv::imencode(".avif", img_original, buf, encoding_params_),
cv::Exception);
return;
} Maybe try {
if (!isMultiImg)
code = encoder->write(write_vec[0], params);
else
code = encoder->writemulti(write_vec, params);
encoder->throwOnEror();
CV_Assert( code );
}
catch (const cv::Exception& e)
{
CV_LOG_ERROR(NULL, "imencode(): can't encode data: " << e.what());
code = false;
}
catch (...)
{
CV_LOG_ERROR(NULL, "imencode(): can't encode data: unknown exception");
code = false;
} I think (1) updation AVIF tests to use return value instead of exception or (2) removing try and catch in loadsave.cpp is needed. |
Yes, I changed the implementation that makes code exception safe. I propose to tune tests to handle status. |
cc @vrabaud |
Thank you for your comment, and I fixed to use status code instead of catching exception. |
@param buf Output buffer resized to fit the compressed image. | ||
@param params Format-specific parameters. See cv::imwrite and cv::ImwriteFlags. | ||
*/ | ||
CV_EXPORTS_W bool imencode( const String& ext, InputArray img, | ||
CV_OUT std::vector<uchar>& buf, | ||
const std::vector<int>& params = std::vector<int>()); | ||
|
||
/** @brief Encodes array of images into a memory buffer. | ||
|
||
The function is analog of cv::imencode for in-memory multi-page images compression. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function is analog to cv::imencode for in-memory multi-page image compression.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your review, I fixed this comment.
TEST(Imgcodecs_EXR, imencode_regression_26207_extra) | ||
{ | ||
// CV_8U is not supported depth for EXR Encoder. | ||
cv::Mat src(100, 100, CV_8UC1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I propose to initialize mat with some values: some color or random data. It's applicable for the all new tests.
- It makes test really deterministic
- It makes sanitizers happy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your comment, and I agree with you !
I fixed it, and set const
for their source images.
imgcodecs: implement imencodemulti() opencv#26211 Close opencv#26207 ### 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 - [x] There is a reference to the original bug report and related work - [x] 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
imgcodecs: implement imencodemulti() opencv#26211 Close opencv#26207 ### 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 - [x] There is a reference to the original bug report and related work - [x] 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
Close #26207
Pull Request Readiness Checklist
See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request
Patch to opencv_extra has the same branch name.