From f9dd20eb07210f4759889f667fc8fc1ad90f55da Mon Sep 17 00:00:00 2001 From: alexlyulkov Date: Wed, 17 Apr 2024 09:38:21 +0300 Subject: [PATCH 01/14] Merge pull request #25414 from alexlyulkov:al/range-fixed Fixed ONNX range layer #25414 Partially address https://github.com/opencv/opencv/issues/25363 Fixed ONNX range layer. It should support any input type. Added tests (extra [PR](https://github.com/opencv/opencv_extra/pull/1170)) ### 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 - [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 --- modules/dnn/src/onnx/onnx_importer.cpp | 16 ++++++++-------- modules/dnn/test/test_onnx_importer.cpp | 6 ++++++ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/modules/dnn/src/onnx/onnx_importer.cpp b/modules/dnn/src/onnx/onnx_importer.cpp index f0b2febb88..b09a9ed360 100644 --- a/modules/dnn/src/onnx/onnx_importer.cpp +++ b/modules/dnn/src/onnx/onnx_importer.cpp @@ -3005,22 +3005,22 @@ void ONNXImporter::parseRange(LayerParams& layerParams, const opencv_onnx::NodeP CV_Assert(const_id.size() == 3); Mat startMat = getBlob(node_proto, 0); - CV_Assert(startMat.type() == CV_32SC1); - int start = startMat.at(0); + startMat.convertTo(startMat, CV_32F); + float start = startMat.at(0); Mat limitMat = getBlob(node_proto, 1); - CV_Assert(limitMat.type() == CV_32SC1); - int limit = limitMat.at(0); + limitMat.convertTo(limitMat, CV_32F); + float limit = limitMat.at(0); Mat deltaMat = getBlob(node_proto, 2); - CV_Assert(deltaMat.type() == CV_32SC1); - int delta = deltaMat.at(0); + deltaMat.convertTo(deltaMat, CV_32F); + float delta = deltaMat.at(0); int number_of_elements = std::max(int(std::ceil((limit - start) / delta)), 0); - Mat r(number_of_elements, 1, CV_32SC1); + Mat r(1, number_of_elements, CV_32FC1); // should be 1d tensor, but Mat doesn't support it for (int i = 0; i < number_of_elements; i++) { - r.at(i) = start + (i * delta); + r.at(i) = start + (i * delta); } addConstant(node_proto.output(0), r); constBlobsExtraInfo.insert(std::make_pair(node_proto.output(0), TensorInfo(1))); diff --git a/modules/dnn/test/test_onnx_importer.cpp b/modules/dnn/test/test_onnx_importer.cpp index 669d363afa..82b10fb1ba 100644 --- a/modules/dnn/test/test_onnx_importer.cpp +++ b/modules/dnn/test/test_onnx_importer.cpp @@ -804,6 +804,12 @@ TEST_P(Test_ONNX_layers, CumSumExclusiveInplace) testONNXModels("cumsum_exclusive_inplace"); } +TEST_P(Test_ONNX_layers, Range) +{ + testONNXModels("range_float"); + testONNXModels("range_float_negative"); +} + TEST_P(Test_ONNX_layers, Eltwise3D) { #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000) From f643964c6863dcbcdc83029c611b76cf9224a49b Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Thu, 11 Apr 2024 15:11:02 +0300 Subject: [PATCH 02/14] Added HAL function for popular bit-exact branch of GaussianBlur with sigma=0. --- modules/imgproc/src/hal_replacement.hpp | 25 +++++++++++++++++++++- modules/imgproc/src/smooth.dispatch.cpp | 28 +++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/modules/imgproc/src/hal_replacement.hpp b/modules/imgproc/src/hal_replacement.hpp index 5c6497bd80..6d1f2a4272 100644 --- a/modules/imgproc/src/hal_replacement.hpp +++ b/modules/imgproc/src/hal_replacement.hpp @@ -855,7 +855,7 @@ inline int hal_ni_boxFilter(const uchar* src_data, size_t src_step, uchar* dst_d //! @endcond /** - @brief Blurs an image using a Gaussian filter. + @brief Blurs an image using a generic Gaussian filter. @param src_data Source image data @param src_step Source image step @param dst_data Destination image data @@ -880,6 +880,29 @@ inline int hal_ni_gaussianBlur(const uchar* src_data, size_t src_step, uchar* ds #define cv_hal_gaussianBlur hal_ni_gaussianBlur //! @endcond +/** + @brief Blurs an image using a symmetric Gaussian filter with square kernel and sigma=0. + @param src_data Source image data + @param src_step Source image step + @param dst_data Destination image data + @param dst_step Destination image step + @param width Source image width + @param height Source image height + @param depth Depth of source and destination image + @param cn Number of channels + @param margin_left Left margins for source image + @param margin_top Top margins for source image + @param margin_right Right margins for source image + @param margin_bottom Bottom margins for source image + @param ksize Width of kernel + @param border_type Border type +*/ +inline int hal_ni_gaussianBlurBinomial(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int depth, int cn, size_t margin_left, size_t margin_top, size_t margin_right, size_t margin_bottom, size_t ksize, int border_type) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } + +//! @cond IGNORED +#define cv_hal_gaussianBlurBinomial hal_ni_gaussianBlurBinomial +//! @endcond + /** @brief Computes Sobel derivatives @param src_depth Depth of source image diff --git a/modules/imgproc/src/smooth.dispatch.cpp b/modules/imgproc/src/smooth.dispatch.cpp index 26566c7e03..d0f50a73bb 100644 --- a/modules/imgproc/src/smooth.dispatch.cpp +++ b/modules/imgproc/src/smooth.dispatch.cpp @@ -683,8 +683,22 @@ void GaussianBlur(InputArray _src, OutputArray _dst, Size ksize, if (src.data == dst.data) src = src.clone(); + + if ((sigma1 == 0.0) && (sigma2 == 0.0) && (ksize.height == ksize.width)) + { + Point ofs; + Size wsz(src.cols, src.rows); + Mat src2 = src; + if(!(borderType & BORDER_ISOLATED)) + src2.locateROI( wsz, ofs ); + + CALL_HAL(gaussianBlurBinomial, cv_hal_gaussianBlurBinomial, src2.ptr(), src2.step, dst.ptr(), dst.step, src2.cols, src2.rows, sdepth, cn, + ofs.x, ofs.y, wsz.width - src2.cols - ofs.x, wsz.height - src2.rows - ofs.y, ksize.width, borderType&~BORDER_ISOLATED); + } + CV_CPU_DISPATCH(GaussianBlurFixedPoint, (src, dst, (const uint16_t*)&fkx[0], (int)fkx.size(), (const uint16_t*)&fky[0], (int)fky.size(), borderType), CV_CPU_DISPATCH_MODES_ALL); + return; } } @@ -720,8 +734,22 @@ void GaussianBlur(InputArray _src, OutputArray _dst, Size ksize, if (src.data == dst.data) src = src.clone(); + + if ((sigma1 == 0.0) && (sigma2 == 0.0) && (ksize.height == ksize.width)) + { + Point ofs; + Size wsz(src.cols, src.rows); + Mat src2 = src; + if(!(borderType & BORDER_ISOLATED)) + src2.locateROI( wsz, ofs ); + + CALL_HAL(gaussianBlurBinomial, cv_hal_gaussianBlurBinomial, src2.ptr(), src2.step, dst.ptr(), dst.step, src2.cols, src2.rows, sdepth, cn, + ofs.x, ofs.y, wsz.width - src2.cols - ofs.x, wsz.height - src2.rows - ofs.y, ksize.width, borderType&~BORDER_ISOLATED); + } + CV_CPU_DISPATCH(GaussianBlurFixedPoint, (src, dst, (const uint32_t*)&fkx[0], (int)fkx.size(), (const uint32_t*)&fky[0], (int)fky.size(), borderType), CV_CPU_DISPATCH_MODES_ALL); + return; } } From a4b4808d9d6a21d67489aba181999c1ba6331d34 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Thu, 11 Apr 2024 15:57:42 +0300 Subject: [PATCH 03/14] New HAL API for remap --- modules/imgproc/src/hal_replacement.hpp | 30 +++++++++++++++++++++++++ modules/imgproc/src/imgwarp.cpp | 7 +++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/modules/imgproc/src/hal_replacement.hpp b/modules/imgproc/src/hal_replacement.hpp index 5c6497bd80..ca29eca6b6 100644 --- a/modules/imgproc/src/hal_replacement.hpp +++ b/modules/imgproc/src/hal_replacement.hpp @@ -298,6 +298,36 @@ inline int hal_ni_warpPerspective(int src_type, const uchar *src_data, size_t sr #define cv_hal_warpPerspective hal_ni_warpPerspective //! @endcond +/** + @brief hal_remap with floating point maps + @param src_type source and destination image type + @param src_data source image data + @param src_step source image step + @param src_width source image width + @param src_height source image height + @param dst_data destination image data + @param dst_step destination image step + @param dst_width destination image width + @param dst_height destination image height + @param mapx map for x values + @param mapx_step mapx matrix step + @param mapy map for y values + @param mapy_step mapy matrix step + @param interpolation interpolation mode (CV_HAL_INTER_NEAREST, ...) + @param border_type border processing mode (CV_HAL_BORDER_REFLECT, ...) + @param border_value values to use for CV_HAL_BORDER_CONSTANT mode + @sa cv::remap + */ +inline int hal_ni_remap32f(int src_type, const uchar *src_data, size_t src_step, int src_width, int src_height, + uchar *dst_data, size_t dst_step, int dst_width, int dst_height, + float* mapx, size_t mapx_step, float* mapy, size_t mapy_step, + int interpolation, int border_type, const double border_value[4]) +{ return CV_HAL_ERROR_NOT_IMPLEMENTED; } + +//! @cond IGNORED +#define cv_hal_remap32f hal_ni_remap32f +//! @endcond + /** @brief hal_cvtBGRtoBGR @param src_data source image data diff --git a/modules/imgproc/src/imgwarp.cpp b/modules/imgproc/src/imgwarp.cpp index 7c4567218b..d7c9c64c3c 100644 --- a/modules/imgproc/src/imgwarp.cpp +++ b/modules/imgproc/src/imgwarp.cpp @@ -1799,7 +1799,6 @@ void cv::remap( InputArray _src, OutputArray _dst, _dst.create( map1.size(), src.type() ); Mat dst = _dst.getMat(); - CV_OVX_RUN( src.type() == CV_8UC1 && dst.type() == CV_8UC1 && !ovx::skipSmallImages(src.cols, src.rows) && @@ -1816,6 +1815,12 @@ void cv::remap( InputArray _src, OutputArray _dst, if( dst.data == src.data ) src = src.clone(); + if ((map1.type() == CV_32FC1) && (map2.type() == CV_32FC1)) + { + CALL_HAL(remap32f, cv_hal_remap32f, src.type(), src.data, src.step, src.cols, src.rows, dst.data, dst.step, dst.cols, dst.rows, + map1.ptr(), map1.step, map2.ptr(), map2.step, interpolation, borderType, borderValue.val); + } + interpolation &= ~WARP_RELATIVE_MAP; if( interpolation == INTER_AREA ) interpolation = INTER_LINEAR; From 37ca0308a773a6504d3fceeb1efe6bf3c014a414 Mon Sep 17 00:00:00 2001 From: Linaname <30354029+Linaname@users.noreply.github.com> Date: Wed, 17 Apr 2024 13:26:56 +0500 Subject: [PATCH 04/14] Merge pull request #25402 from Linaname:4.x Handle top and left border masked pixels correctly in inpaint method #25402 Fixes #25389 ### 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 - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- modules/photo/src/inpaint.cpp | 8 ++++---- modules/photo/test/test_inpaint.cpp | 26 ++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/modules/photo/src/inpaint.cpp b/modules/photo/src/inpaint.cpp index d2d495e57e..d9a7dbc58b 100644 --- a/modules/photo/src/inpaint.cpp +++ b/modules/photo/src/inpaint.cpp @@ -340,7 +340,7 @@ icvTeleaInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQu gradI.y=0; } } - Ia[color] += (float)w * (float)(CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color)); + Ia[color] += (float)w * (float)(CV_MAT_3COLOR_ELEM(*out,uchar,k-1,l-1,color)); Jx[color] -= (float)w * (float)(gradI.x*r.x); Jy[color] -= (float)w * (float)(gradI.y*r.y); s[color] += w; @@ -452,7 +452,7 @@ icvTeleaInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQu gradI.y=0; } } - Ia += (float)w * (float)(CV_MAT_ELEM(*out,data_type,km,lm)); + Ia += (float)w * (float)(CV_MAT_ELEM(*out,data_type,k-1,l-1)); Jx -= (float)w * (float)(gradI.x*r.x); Jy -= (float)w * (float)(gradI.y*r.y); s += w; @@ -555,7 +555,7 @@ icvNSInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQueue dir = (float)fabs(VectorScalMult(r,gradI)/sqrt(VectorLength(r)*VectorLength(gradI))); } w = dst*dir; - Ia[color] += (float)w * (float)(CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color)); + Ia[color] += (float)w * (float)(CV_MAT_3COLOR_ELEM(*out,uchar,k-1,l-1,color)); s[color] += w; } } @@ -645,7 +645,7 @@ icvNSInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQueue dir = (float)fabs(VectorScalMult(r,gradI)/sqrt(VectorLength(r)*VectorLength(gradI))); } w = dst*dir; - Ia += (float)w * (float)(CV_MAT_ELEM(*out,data_type,km,lm)); + Ia += (float)w * (float)(CV_MAT_ELEM(*out,data_type,k-1,l-1)); s += w; } } diff --git a/modules/photo/test/test_inpaint.cpp b/modules/photo/test/test_inpaint.cpp index 1536490693..75bab57737 100644 --- a/modules/photo/test/test_inpaint.cpp +++ b/modules/photo/test/test_inpaint.cpp @@ -157,4 +157,30 @@ TEST(Photo_InpaintBorders, regression) ASSERT_TRUE(countNonZero(diff) == 0); } +typedef testing::TestWithParam> Photo_InpaintSmallBorders; + +TEST_P(Photo_InpaintSmallBorders, regression) +{ + int type = get<0>(GetParam()); + Mat img(5, 5, type, Scalar::all(128)); + Mat expected = img.clone(); + + Mat mask = Mat::zeros(5, 5, CV_8U); + mask(Rect(1, 1, 3, 3)) = 255; + + img.setTo(Scalar::all(0), mask); + + Mat inpainted, diff; + + inpaint(img, mask, inpainted, 1, INPAINT_TELEA); + cv::absdiff(inpainted, expected, diff); + ASSERT_EQ(countNonZero(diff.reshape(1)), 0); + + inpaint(img, mask, inpainted, 1, INPAINT_NS); + cv::absdiff(inpainted, expected, diff); + ASSERT_EQ(countNonZero(diff.reshape(1)), 0); +} + +INSTANTIATE_TEST_CASE_P(/*nothing*/, Photo_InpaintSmallBorders, Values(CV_8UC1, CV_8UC3)); + }} // namespace From 3cc83c7610e12b79349c4ae5e5d833a4c6bedd81 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Wed, 17 Apr 2024 12:59:49 +0300 Subject: [PATCH 05/14] Added FaceDetectorYN to OpenCV JS API. --- platforms/js/opencv_js.config.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platforms/js/opencv_js.config.py b/platforms/js/opencv_js.config.py index f3ed847ef5..1251062e4c 100644 --- a/platforms/js/opencv_js.config.py +++ b/platforms/js/opencv_js.config.py @@ -128,7 +128,9 @@ objdetect = {'': ['groupRectangles', 'getPredefinedDictionary', 'extendDictionar 'aruco_CharucoDetector': ['CharucoDetector', 'setBoard', 'setCharucoParameters', 'setDetectorParameters', 'setRefineParameters', 'detectBoard', 'detectDiamonds'], 'QRCodeDetectorAruco_Params': ['Params'], 'QRCodeDetectorAruco': ['QRCodeDetectorAruco', 'decode', 'detect', 'detectAndDecode', 'detectMulti', 'decodeMulti', 'detectAndDecodeMulti', 'setDetectorParameters', 'setArucoParameters'], - 'barcode_BarcodeDetector': ['BarcodeDetector', 'decode', 'detect', 'detectAndDecode', 'detectMulti', 'decodeMulti', 'detectAndDecodeMulti', 'decodeWithType', 'detectAndDecodeWithType'] + 'barcode_BarcodeDetector': ['BarcodeDetector', 'decode', 'detect', 'detectAndDecode', 'detectMulti', 'decodeMulti', 'detectAndDecodeMulti', 'decodeWithType', 'detectAndDecodeWithType'], + 'FaceDetectorYN': ['setInputSize', 'getInputSize', 'setScoreThreshold', 'getScoreThreshold', 'setNMSThreshold', 'getNMSThreshold', + 'setTopK', 'getTopK', 'detect', 'create'], } video = { From f9e95678700c8bf8b3e484a548b9856e40995ffb Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Wed, 17 Apr 2024 14:19:05 +0300 Subject: [PATCH 06/14] Merge pull request #25424 from mshabunin:fix-features2d-test features2d: reduce accuracy test avg memory consumption #25424 **Merge with contrib**: https://github.com/opencv/opencv_contrib/pull/3722 I've observed high memory consumption in the `opencv_test_features2d` (x86_64, Ubuntu 22.04, Debug): ![image](https://github.com/opencv/opencv/assets/3304494/419d65d9-d727-4d1e-bdec-dbde6681c188) It's always more than 180 MiB with peak at 535 MiB This was caused by pointers to the algorithm object instances stored in the tests parameters. I've replaced them with factory functions/lambdas with the following result: ![image](https://github.com/opencv/opencv/assets/3304494/bd4ff0ea-3db4-4ab8-8e6d-192a3826e99c) Now peak is at 355 MiB and permanent consumption level is ~ 1-2 MiB **Note:** current peak is caused by KAZE features allocating 8x image size utility buffers. Not sure if we can or should do anything about it: https://github.com/opencv/opencv/blob/66fb5021e9253e3decab376d00322eaf2b279c89/modules/features2d/src/kaze/KAZEFeatures.cpp#L61-L68 --- .../features2d/test/ocl/test_feature2d.cpp | 9 ++++---- .../test/test_descriptors_invariance.cpp | 16 +++++++------- .../test/test_descriptors_invariance.impl.hpp | 11 +++++++--- .../test/test_detectors_invariance.cpp | 22 +++++++++---------- .../test/test_detectors_invariance.impl.hpp | 8 +++++-- 5 files changed, 38 insertions(+), 28 deletions(-) diff --git a/modules/features2d/test/ocl/test_feature2d.cpp b/modules/features2d/test/ocl/test_feature2d.cpp index 7024854ce1..ad4008bb81 100644 --- a/modules/features2d/test/ocl/test_feature2d.cpp +++ b/modules/features2d/test/ocl/test_feature2d.cpp @@ -5,6 +5,7 @@ #include "../test_precomp.hpp" #include "cvconfig.h" #include "opencv2/ts/ocl_test.hpp" +#include #ifdef HAVE_OPENCL @@ -16,7 +17,7 @@ namespace ocl { "../stitching/a3.png", \ "../stitching/s2.jpg") -PARAM_TEST_CASE(Feature2DFixture, Ptr, std::string) +PARAM_TEST_CASE(Feature2DFixture, std::function()>, std::string) { std::string filename; Mat image, descriptors; @@ -27,7 +28,7 @@ PARAM_TEST_CASE(Feature2DFixture, Ptr, std::string) virtual void SetUp() { - feature = GET_PARAM(0); + feature = GET_PARAM(0)(); filename = GET_PARAM(1); image = readImage(filename); @@ -61,10 +62,10 @@ OCL_TEST_P(Feature2DFixture, DescriptorsSame) } OCL_INSTANTIATE_TEST_CASE_P(AKAZE, Feature2DFixture, - testing::Combine(testing::Values(AKAZE::create()), TEST_IMAGES)); + testing::Combine(testing::Values([]() { return AKAZE::create(); }), TEST_IMAGES)); OCL_INSTANTIATE_TEST_CASE_P(AKAZE_DESCRIPTOR_KAZE, Feature2DFixture, - testing::Combine(testing::Values(AKAZE::create(AKAZE::DESCRIPTOR_KAZE)), TEST_IMAGES)); + testing::Combine(testing::Values([]() { return AKAZE::create(AKAZE::DESCRIPTOR_KAZE); }), TEST_IMAGES)); }//ocl }//cvtest diff --git a/modules/features2d/test/test_descriptors_invariance.cpp b/modules/features2d/test/test_descriptors_invariance.cpp index 9faf56a1c8..0ac381f667 100644 --- a/modules/features2d/test/test_descriptors_invariance.cpp +++ b/modules/features2d/test/test_descriptors_invariance.cpp @@ -18,31 +18,31 @@ const static std::string IMAGE_BIKES = "detectors_descriptors_evaluation/images_ */ INSTANTIATE_TEST_CASE_P(SIFT, DescriptorRotationInvariance, - Value(IMAGE_TSUKUBA, SIFT::create(), SIFT::create(), 0.98f)); + Value(IMAGE_TSUKUBA, []() { return SIFT::create(); }, []() { return SIFT::create(); }, 0.98f)); INSTANTIATE_TEST_CASE_P(BRISK, DescriptorRotationInvariance, - Value(IMAGE_TSUKUBA, BRISK::create(), BRISK::create(), 0.99f)); + Value(IMAGE_TSUKUBA, []() { return BRISK::create(); }, []() { return BRISK::create(); }, 0.99f)); INSTANTIATE_TEST_CASE_P(ORB, DescriptorRotationInvariance, - Value(IMAGE_TSUKUBA, ORB::create(), ORB::create(), 0.99f)); + Value(IMAGE_TSUKUBA, []() { return ORB::create(); }, []() { return ORB::create(); }, 0.99f)); INSTANTIATE_TEST_CASE_P(AKAZE, DescriptorRotationInvariance, - Value(IMAGE_TSUKUBA, AKAZE::create(), AKAZE::create(), 0.99f)); + Value(IMAGE_TSUKUBA, []() { return AKAZE::create(); }, []() { return AKAZE::create(); }, 0.99f)); INSTANTIATE_TEST_CASE_P(AKAZE_DESCRIPTOR_KAZE, DescriptorRotationInvariance, - Value(IMAGE_TSUKUBA, AKAZE::create(AKAZE::DESCRIPTOR_KAZE), AKAZE::create(AKAZE::DESCRIPTOR_KAZE), 0.99f)); + Value(IMAGE_TSUKUBA, []() { return AKAZE::create(AKAZE::DESCRIPTOR_KAZE); }, []() { return AKAZE::create(AKAZE::DESCRIPTOR_KAZE); }, 0.99f)); /* * Descriptor's scale invariance check */ INSTANTIATE_TEST_CASE_P(SIFT, DescriptorScaleInvariance, - Value(IMAGE_BIKES, SIFT::create(0, 3, 0.09), SIFT::create(0, 3, 0.09), 0.78f)); + Value(IMAGE_BIKES, []() { return SIFT::create(0, 3, 0.09); }, []() { return SIFT::create(0, 3, 0.09); }, 0.78f)); INSTANTIATE_TEST_CASE_P(AKAZE, DescriptorScaleInvariance, - Value(IMAGE_BIKES, AKAZE::create(), AKAZE::create(), 0.6f)); + Value(IMAGE_BIKES, []() { return AKAZE::create(); }, []() { return AKAZE::create(); }, 0.6f)); INSTANTIATE_TEST_CASE_P(AKAZE_DESCRIPTOR_KAZE, DescriptorScaleInvariance, - Value(IMAGE_BIKES, AKAZE::create(AKAZE::DESCRIPTOR_KAZE), AKAZE::create(AKAZE::DESCRIPTOR_KAZE), 0.55f)); + Value(IMAGE_BIKES, []() { return AKAZE::create(AKAZE::DESCRIPTOR_KAZE); }, []() { return AKAZE::create(AKAZE::DESCRIPTOR_KAZE); }, 0.55f)); }} // namespace diff --git a/modules/features2d/test/test_descriptors_invariance.impl.hpp b/modules/features2d/test/test_descriptors_invariance.impl.hpp index 780e86e724..055500b1f9 100644 --- a/modules/features2d/test/test_descriptors_invariance.impl.hpp +++ b/modules/features2d/test/test_descriptors_invariance.impl.hpp @@ -3,12 +3,17 @@ // of this distribution and at http://opencv.org/license.html #include "test_invariance_utils.hpp" +#include namespace opencv_test { namespace { #define SHOW_DEBUG_LOG 1 -typedef tuple, Ptr, float> +// NOTE: using factory function (function()>) instead of object instance (Ptr) as a +// test parameter, because parameters exist during whole test program run and consume a lot of memory +typedef std::function()> DetectorFactory; +typedef std::function()> ExtractorFactory; +typedef tuple String_FeatureDetector_DescriptorExtractor_Float_t; @@ -61,8 +66,8 @@ protected: image0 = imread(filename); ASSERT_FALSE(image0.empty()) << "couldn't read input image"; - featureDetector = get<1>(GetParam()); - descriptorExtractor = get<2>(GetParam()); + featureDetector = get<1>(GetParam())(); + descriptorExtractor = get<2>(GetParam())(); minInliersRatio = get<3>(GetParam()); } diff --git a/modules/features2d/test/test_detectors_invariance.cpp b/modules/features2d/test/test_detectors_invariance.cpp index 11e7ecfedc..72fe87f63e 100644 --- a/modules/features2d/test/test_detectors_invariance.cpp +++ b/modules/features2d/test/test_detectors_invariance.cpp @@ -18,40 +18,40 @@ const static std::string IMAGE_BIKES = "detectors_descriptors_evaluation/images_ */ INSTANTIATE_TEST_CASE_P(SIFT, DetectorRotationInvariance, - Value(IMAGE_TSUKUBA, SIFT::create(), 0.45f, 0.70f)); + Value(IMAGE_TSUKUBA, []() { return SIFT::create(); }, 0.45f, 0.70f)); INSTANTIATE_TEST_CASE_P(BRISK, DetectorRotationInvariance, - Value(IMAGE_TSUKUBA, BRISK::create(), 0.45f, 0.76f)); + Value(IMAGE_TSUKUBA, []() { return BRISK::create(); }, 0.45f, 0.76f)); INSTANTIATE_TEST_CASE_P(ORB, DetectorRotationInvariance, - Value(IMAGE_TSUKUBA, ORB::create(), 0.5f, 0.76f)); + Value(IMAGE_TSUKUBA, []() { return ORB::create(); }, 0.5f, 0.76f)); INSTANTIATE_TEST_CASE_P(AKAZE, DetectorRotationInvariance, - Value(IMAGE_TSUKUBA, AKAZE::create(), 0.5f, 0.71f)); + Value(IMAGE_TSUKUBA, []() { return AKAZE::create(); }, 0.5f, 0.71f)); INSTANTIATE_TEST_CASE_P(AKAZE_DESCRIPTOR_KAZE, DetectorRotationInvariance, - Value(IMAGE_TSUKUBA, AKAZE::create(AKAZE::DESCRIPTOR_KAZE), 0.5f, 0.71f)); + Value(IMAGE_TSUKUBA, []() { return AKAZE::create(AKAZE::DESCRIPTOR_KAZE); }, 0.5f, 0.71f)); /* * Detector's scale invariance check */ INSTANTIATE_TEST_CASE_P(SIFT, DetectorScaleInvariance, - Value(IMAGE_BIKES, SIFT::create(0, 3, 0.09), 0.60f, 0.98f)); + Value(IMAGE_BIKES, []() { return SIFT::create(0, 3, 0.09); }, 0.60f, 0.98f)); INSTANTIATE_TEST_CASE_P(BRISK, DetectorScaleInvariance, - Value(IMAGE_BIKES, BRISK::create(), 0.08f, 0.49f)); + Value(IMAGE_BIKES, []() { return BRISK::create(); }, 0.08f, 0.49f)); INSTANTIATE_TEST_CASE_P(ORB, DetectorScaleInvariance, - Value(IMAGE_BIKES, ORB::create(), 0.08f, 0.49f)); + Value(IMAGE_BIKES, []() { return ORB::create(); }, 0.08f, 0.49f)); INSTANTIATE_TEST_CASE_P(KAZE, DetectorScaleInvariance, - Value(IMAGE_BIKES, KAZE::create(), 0.08f, 0.49f)); + Value(IMAGE_BIKES, []() { return KAZE::create(); }, 0.08f, 0.49f)); INSTANTIATE_TEST_CASE_P(AKAZE, DetectorScaleInvariance, - Value(IMAGE_BIKES, AKAZE::create(), 0.08f, 0.49f)); + Value(IMAGE_BIKES, []() { return AKAZE::create(); }, 0.08f, 0.49f)); INSTANTIATE_TEST_CASE_P(AKAZE_DESCRIPTOR_KAZE, DetectorScaleInvariance, - Value(IMAGE_BIKES, AKAZE::create(AKAZE::DESCRIPTOR_KAZE), 0.08f, 0.49f)); + Value(IMAGE_BIKES, []() { return AKAZE::create(AKAZE::DESCRIPTOR_KAZE); }, 0.08f, 0.49f)); }} // namespace diff --git a/modules/features2d/test/test_detectors_invariance.impl.hpp b/modules/features2d/test/test_detectors_invariance.impl.hpp index e50316fed9..a602333509 100644 --- a/modules/features2d/test/test_detectors_invariance.impl.hpp +++ b/modules/features2d/test/test_detectors_invariance.impl.hpp @@ -3,12 +3,16 @@ // of this distribution and at http://opencv.org/license.html #include "test_invariance_utils.hpp" +#include namespace opencv_test { namespace { #define SHOW_DEBUG_LOG 1 -typedef tuple, float, float> String_FeatureDetector_Float_Float_t; +// NOTE: using factory function (function()>) instead of object instance (Ptr) as a +// test parameter, because parameters exist during whole test program run and consume a lot of memory +typedef std::function()> DetectorFactory; +typedef tuple String_FeatureDetector_Float_Float_t; static @@ -56,7 +60,7 @@ protected: image0 = imread(filename); ASSERT_FALSE(image0.empty()) << "couldn't read input image"; - featureDetector = get<1>(GetParam()); + featureDetector = get<1>(GetParam())(); minKeyPointMatchesRatio = get<2>(GetParam()); minInliersRatio = get<3>(GetParam()); } From 85673afb47941c4c833c18ee8dd3921435b132e5 Mon Sep 17 00:00:00 2001 From: Vincent Rabaud Date: Wed, 17 Apr 2024 14:36:44 +0200 Subject: [PATCH 07/14] Bump libwebp to v1.4.0 --- 3rdparty/libwebp/sharpyuv/sharpyuv.c | 69 ++++++++------ 3rdparty/libwebp/sharpyuv/sharpyuv.h | 10 +- 3rdparty/libwebp/sharpyuv/sharpyuv_dsp.c | 4 +- 3rdparty/libwebp/sharpyuv/sharpyuv_gamma.c | 34 +++---- 3rdparty/libwebp/src/dec/alpha_dec.c | 26 ++++-- 3rdparty/libwebp/src/dec/idec_dec.c | 50 ++++++---- 3rdparty/libwebp/src/dec/vp8_dec.c | 20 ++-- 3rdparty/libwebp/src/dec/vp8_dec.h | 17 ++-- 3rdparty/libwebp/src/dec/vp8i_dec.h | 15 +-- 3rdparty/libwebp/src/dec/vp8li_dec.h | 25 ++--- 3rdparty/libwebp/src/dec/webp_dec.c | 48 ++++++---- 3rdparty/libwebp/src/dec/webpi_dec.h | 6 +- 3rdparty/libwebp/src/demux/anim_decode.c | 22 +++-- 3rdparty/libwebp/src/demux/demux.c | 4 +- 3rdparty/libwebp/src/dsp/cpu.c | 12 --- 3rdparty/libwebp/src/dsp/dec.c | 25 +++-- 3rdparty/libwebp/src/dsp/dec_mips32.c | 56 ++++-------- 3rdparty/libwebp/src/dsp/dec_mips_dsp_r2.c | 16 ++-- 3rdparty/libwebp/src/dsp/dec_msa.c | 10 +- 3rdparty/libwebp/src/dsp/dec_neon.c | 17 ++-- 3rdparty/libwebp/src/dsp/dec_sse2.c | 34 ++++--- 3rdparty/libwebp/src/dsp/dsp.h | 5 + 3rdparty/libwebp/src/dsp/enc.c | 21 ++--- 3rdparty/libwebp/src/dsp/enc_mips32.c | 20 ++-- 3rdparty/libwebp/src/dsp/enc_mips_dsp_r2.c | 4 +- 3rdparty/libwebp/src/dsp/enc_neon.c | 5 +- 3rdparty/libwebp/src/dsp/filters.c | 26 +++--- .../libwebp/src/dsp/filters_mips_dsp_r2.c | 26 +++--- 3rdparty/libwebp/src/dsp/filters_msa.c | 22 +++-- 3rdparty/libwebp/src/dsp/filters_neon.c | 26 +++--- 3rdparty/libwebp/src/dsp/filters_sse2.c | 26 +++--- 3rdparty/libwebp/src/dsp/lossless_neon.c | 6 +- 3rdparty/libwebp/src/dsp/mips_macro.h | 42 +++++---- 3rdparty/libwebp/src/dsp/rescaler_neon.c | 2 +- 3rdparty/libwebp/src/dsp/upsampling_sse2.c | 12 +-- 3rdparty/libwebp/src/dsp/upsampling_sse41.c | 8 +- 3rdparty/libwebp/src/enc/alpha_enc.c | 9 +- 3rdparty/libwebp/src/enc/vp8i_enc.h | 4 +- 3rdparty/libwebp/src/enc/vp8l_enc.c | 33 +++---- 3rdparty/libwebp/src/enc/vp8li_enc.h | 4 +- 3rdparty/libwebp/src/mux/anim_encode.c | 33 ++++++- 3rdparty/libwebp/src/mux/muxedit.c | 16 ++-- 3rdparty/libwebp/src/mux/muxi.h | 4 +- 3rdparty/libwebp/src/mux/muxread.c | 22 +++-- 3rdparty/libwebp/src/utils/huffman_utils.c | 5 +- 3rdparty/libwebp/src/utils/huffman_utils.h | 11 ++- 3rdparty/libwebp/src/webp/decode.h | 77 ++++++++-------- 3rdparty/libwebp/src/webp/demux.h | 46 +++++----- 3rdparty/libwebp/src/webp/encode.h | 83 +++++++++-------- 3rdparty/libwebp/src/webp/mux.h | 91 ++++++++++++++++--- 3rdparty/libwebp/src/webp/mux_types.h | 3 +- 3rdparty/libwebp/src/webp/types.h | 37 ++++++-- 52 files changed, 701 insertions(+), 548 deletions(-) diff --git a/3rdparty/libwebp/sharpyuv/sharpyuv.c b/3rdparty/libwebp/sharpyuv/sharpyuv.c index b94885a6c3..7cbf668fbb 100644 --- a/3rdparty/libwebp/sharpyuv/sharpyuv.c +++ b/3rdparty/libwebp/sharpyuv/sharpyuv.c @@ -90,8 +90,8 @@ static WEBP_INLINE void UpdateW(const fixed_y_t* src, fixed_y_t* dst, int w, int rgb_bit_depth, SharpYuvTransferFunctionType transfer_type) { const int bit_depth = rgb_bit_depth + GetPrecisionShift(rgb_bit_depth); - int i; - for (i = 0; i < w; ++i) { + int i = 0; + do { const uint32_t R = SharpYuvGammaToLinear(src[0 * w + i], bit_depth, transfer_type); const uint32_t G = @@ -100,14 +100,14 @@ static WEBP_INLINE void UpdateW(const fixed_y_t* src, fixed_y_t* dst, int w, SharpYuvGammaToLinear(src[2 * w + i], bit_depth, transfer_type); const uint32_t Y = RGBToGray(R, G, B); dst[i] = (fixed_y_t)SharpYuvLinearToGamma(Y, bit_depth, transfer_type); - } + } while (++i < w); } static void UpdateChroma(const fixed_y_t* src1, const fixed_y_t* src2, fixed_t* dst, int uv_w, int rgb_bit_depth, SharpYuvTransferFunctionType transfer_type) { - int i; - for (i = 0; i < uv_w; ++i) { + int i = 0; + do { const int r = ScaleDown(src1[0 * uv_w + 0], src1[0 * uv_w + 1], src2[0 * uv_w + 0], src2[0 * uv_w + 1], rgb_bit_depth, transfer_type); @@ -124,15 +124,15 @@ static void UpdateChroma(const fixed_y_t* src1, const fixed_y_t* src2, dst += 1; src1 += 2; src2 += 2; - } + } while (++i < uv_w); } static void StoreGray(const fixed_y_t* rgb, fixed_y_t* y, int w) { - int i; + int i = 0; assert(w > 0); - for (i = 0; i < w; ++i) { + do { y[i] = RGBToGray(rgb[0 * w + i], rgb[1 * w + i], rgb[2 * w + i]); - } + } while (++i < w); } //------------------------------------------------------------------------------ @@ -158,9 +158,9 @@ static void ImportOneRow(const uint8_t* const r_ptr, // Convert the rgb_step from a number of bytes to a number of uint8_t or // uint16_t values depending the bit depth. const int step = (rgb_bit_depth > 8) ? rgb_step / 2 : rgb_step; - int i; + int i = 0; const int w = (pic_width + 1) & ~1; - for (i = 0; i < pic_width; ++i) { + do { const int off = i * step; const int shift = GetPrecisionShift(rgb_bit_depth); if (rgb_bit_depth == 8) { @@ -172,7 +172,7 @@ static void ImportOneRow(const uint8_t* const r_ptr, dst[i + 1 * w] = Shift(((uint16_t*)g_ptr)[off], shift); dst[i + 2 * w] = Shift(((uint16_t*)b_ptr)[off], shift); } - } + } while (++i < pic_width); if (pic_width & 1) { // replicate rightmost pixel dst[pic_width + 0 * w] = dst[pic_width + 0 * w - 1]; dst[pic_width + 1 * w] = dst[pic_width + 1 * w - 1]; @@ -240,8 +240,11 @@ static int ConvertWRGBToYUV(const fixed_y_t* best_y, const fixed_t* best_uv, const int sfix = GetPrecisionShift(rgb_bit_depth); const int yuv_max = (1 << yuv_bit_depth) - 1; - for (best_uv = best_uv_base, j = 0; j < height; ++j) { - for (i = 0; i < width; ++i) { + best_uv = best_uv_base; + j = 0; + do { + i = 0; + do { const int off = (i >> 1); const int W = best_y[i]; const int r = best_uv[off + 0 * uv_w] + W; @@ -253,19 +256,22 @@ static int ConvertWRGBToYUV(const fixed_y_t* best_y, const fixed_t* best_uv, } else { ((uint16_t*)y_ptr)[i] = clip(y, yuv_max); } - } + } while (++i < width); best_y += w; best_uv += (j & 1) * 3 * uv_w; y_ptr += y_stride; - } - for (best_uv = best_uv_base, j = 0; j < uv_h; ++j) { - for (i = 0; i < uv_w; ++i) { - const int off = i; + } while (++j < height); + + best_uv = best_uv_base; + j = 0; + do { + i = 0; + do { // Note r, g and b values here are off by W, but a constant offset on all // 3 components doesn't change the value of u and v with a YCbCr matrix. - const int r = best_uv[off + 0 * uv_w]; - const int g = best_uv[off + 1 * uv_w]; - const int b = best_uv[off + 2 * uv_w]; + const int r = best_uv[i + 0 * uv_w]; + const int g = best_uv[i + 1 * uv_w]; + const int b = best_uv[i + 2 * uv_w]; const int u = RGBToYUVComponent(r, g, b, yuv_matrix->rgb_to_u, sfix); const int v = RGBToYUVComponent(r, g, b, yuv_matrix->rgb_to_v, sfix); if (yuv_bit_depth <= 8) { @@ -275,11 +281,11 @@ static int ConvertWRGBToYUV(const fixed_y_t* best_y, const fixed_t* best_uv, ((uint16_t*)u_ptr)[i] = clip(u, yuv_max); ((uint16_t*)v_ptr)[i] = clip(v, yuv_max); } - } + } while (++i < uv_w); best_uv += 3 * uv_w; u_ptr += u_stride; v_ptr += v_stride; - } + } while (++j < uv_h); return 1; } @@ -292,7 +298,7 @@ static void* SafeMalloc(uint64_t nmemb, size_t size) { return malloc((size_t)total_size); } -#define SAFE_ALLOC(W, H, T) ((T*)SafeMalloc((W) * (H), sizeof(T))) +#define SAFE_ALLOC(W, H, T) ((T*)SafeMalloc((uint64_t)(W) * (H), sizeof(T))) static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr, const uint8_t* b_ptr, int rgb_step, int rgb_stride, @@ -307,6 +313,7 @@ static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr, const int h = (height + 1) & ~1; const int uv_w = w >> 1; const int uv_h = h >> 1; + const int y_bit_depth = rgb_bit_depth + GetPrecisionShift(rgb_bit_depth); uint64_t prev_diff_y_sum = ~0; int j, iter; @@ -377,7 +384,8 @@ static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr, best_uv = best_uv_base; target_y = target_y_base; target_uv = target_uv_base; - for (j = 0; j < h; j += 2) { + j = 0; + do { fixed_y_t* const src1 = tmp_buffer + 0 * w; fixed_y_t* const src2 = tmp_buffer + 3 * w; { @@ -394,15 +402,15 @@ static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr, // update two rows of Y and one row of RGB diff_y_sum += - SharpYuvUpdateY(target_y, best_rgb_y, best_y, 2 * w, - rgb_bit_depth + GetPrecisionShift(rgb_bit_depth)); + SharpYuvUpdateY(target_y, best_rgb_y, best_y, 2 * w, y_bit_depth); SharpYuvUpdateRGB(target_uv, best_rgb_uv, best_uv, 3 * uv_w); best_y += 2 * w; best_uv += 3 * uv_w; target_y += 2 * w; target_uv += 3 * uv_w; - } + j += 2; + } while (j < h); // test exit condition if (iter > 0) { if (diff_y_sum < diff_y_threshold) break; @@ -426,6 +434,7 @@ static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr, free(tmp_buffer); return ok; } + #undef SAFE_ALLOC #if defined(WEBP_USE_THREAD) && !defined(_WIN32) @@ -524,7 +533,7 @@ int SharpYuvConvertWithOptions(const void* r_ptr, const void* g_ptr, if (yuv_bit_depth != 8 && yuv_bit_depth != 10 && yuv_bit_depth != 12) { return 0; } - if (rgb_bit_depth > 8 && (rgb_step % 2 != 0 || rgb_stride %2 != 0)) { + if (rgb_bit_depth > 8 && (rgb_step % 2 != 0 || rgb_stride % 2 != 0)) { // Step/stride should be even for uint16_t buffers. return 0; } diff --git a/3rdparty/libwebp/sharpyuv/sharpyuv.h b/3rdparty/libwebp/sharpyuv/sharpyuv.h index 23a69ce39c..fe95891599 100644 --- a/3rdparty/libwebp/sharpyuv/sharpyuv.h +++ b/3rdparty/libwebp/sharpyuv/sharpyuv.h @@ -22,15 +22,13 @@ extern "C" { #else // This explicitly marks library functions and allows for changing the // signature for e.g., Windows DLL builds. -#if defined(__GNUC__) && __GNUC__ >= 4 +#if defined(_WIN32) && defined(WEBP_DLL) +#define SHARPYUV_EXTERN __declspec(dllexport) +#elif defined(__GNUC__) && __GNUC__ >= 4 #define SHARPYUV_EXTERN extern __attribute__((visibility("default"))) #else -#if defined(_MSC_VER) && defined(WEBP_DLL) -#define SHARPYUV_EXTERN __declspec(dllexport) -#else #define SHARPYUV_EXTERN extern -#endif /* _MSC_VER && WEBP_DLL */ -#endif /* __GNUC__ >= 4 */ +#endif /* defined(_WIN32) && defined(WEBP_DLL) */ #endif /* WEBP_EXTERN */ #endif /* SHARPYUV_EXTERN */ diff --git a/3rdparty/libwebp/sharpyuv/sharpyuv_dsp.c b/3rdparty/libwebp/sharpyuv/sharpyuv_dsp.c index 0da3efc0b8..94a40ec686 100644 --- a/3rdparty/libwebp/sharpyuv/sharpyuv_dsp.c +++ b/3rdparty/libwebp/sharpyuv/sharpyuv_dsp.c @@ -17,6 +17,7 @@ #include #include "sharpyuv/sharpyuv_cpu.h" +#include "src/webp/types.h" //----------------------------------------------------------------------------- @@ -69,8 +70,7 @@ uint64_t (*SharpYuvUpdateY)(const uint16_t* src, const uint16_t* ref, void (*SharpYuvUpdateRGB)(const int16_t* src, const int16_t* ref, int16_t* dst, int len); void (*SharpYuvFilterRow)(const int16_t* A, const int16_t* B, int len, - const uint16_t* best_y, uint16_t* out, - int bit_depth); + const uint16_t* best_y, uint16_t* out, int bit_depth); extern VP8CPUInfo SharpYuvGetCPUInfo; extern void InitSharpYuvSSE2(void); diff --git a/3rdparty/libwebp/sharpyuv/sharpyuv_gamma.c b/3rdparty/libwebp/sharpyuv/sharpyuv_gamma.c index fecadc6480..09028428ac 100644 --- a/3rdparty/libwebp/sharpyuv/sharpyuv_gamma.c +++ b/3rdparty/libwebp/sharpyuv/sharpyuv_gamma.c @@ -156,19 +156,19 @@ static float FromLinear709(float linear) { } static float ToLinear470M(float gamma) { - return Powf(CLAMP(gamma, 0.f, 1.f), 1.f / 2.2f); + return Powf(CLAMP(gamma, 0.f, 1.f), 2.2f); } static float FromLinear470M(float linear) { - return Powf(CLAMP(linear, 0.f, 1.f), 2.2f); + return Powf(CLAMP(linear, 0.f, 1.f), 1.f / 2.2f); } static float ToLinear470Bg(float gamma) { - return Powf(CLAMP(gamma, 0.f, 1.f), 1.f / 2.8f); + return Powf(CLAMP(gamma, 0.f, 1.f), 2.8f); } static float FromLinear470Bg(float linear) { - return Powf(CLAMP(linear, 0.f, 1.f), 2.8f); + return Powf(CLAMP(linear, 0.f, 1.f), 1.f / 2.8f); } static float ToLinearSmpte240(float gamma) { @@ -194,26 +194,26 @@ static float FromLinearSmpte240(float linear) { } static float ToLinearLog100(float gamma) { - return (gamma < 0.01f) ? 0.0f : 1.0f + Log10f(MIN(gamma, 1.f)) / 2.0f; + // The function is non-bijective so choose the middle of [0, 0.01]. + const float mid_interval = 0.01f / 2.f; + return (gamma <= 0.0f) ? mid_interval + : Powf(10.0f, 2.f * (MIN(gamma, 1.f) - 1.0f)); } static float FromLinearLog100(float linear) { - // The function is non-bijective so choose the middle of [0, 0.01]. - const float mid_interval = 0.01f / 2.f; - return (linear <= 0.0f) ? mid_interval - : Powf(10.0f, 2.f * (MIN(linear, 1.f) - 1.0f)); + return (linear < 0.01f) ? 0.0f : 1.0f + Log10f(MIN(linear, 1.f)) / 2.0f; } static float ToLinearLog100Sqrt10(float gamma) { - return (gamma < 0.00316227766f) ? 0.0f - : 1.0f + Log10f(MIN(gamma, 1.f)) / 2.5f; + // The function is non-bijective so choose the middle of [0, 0.00316227766f[. + const float mid_interval = 0.00316227766f / 2.f; + return (gamma <= 0.0f) ? mid_interval + : Powf(10.0f, 2.5f * (MIN(gamma, 1.f) - 1.0f)); } static float FromLinearLog100Sqrt10(float linear) { - // The function is non-bijective so choose the middle of [0, 0.00316227766f[. - const float mid_interval = 0.00316227766f / 2.f; - return (linear < 0.0f) ? mid_interval - : Powf(10.0f, 2.5f * (MIN(linear, 1.f) - 1.0f)); + return (linear < 0.00316227766f) ? 0.0f + : 1.0f + Log10f(MIN(linear, 1.f)) / 2.5f; } static float ToLinearIec61966(float gamma) { @@ -282,11 +282,11 @@ static float FromLinearPq(float linear) { } static float ToLinearSmpte428(float gamma) { - return Powf(0.91655527974030934f * MAX(gamma, 0.f), 1.f / 2.6f); + return Powf(MAX(gamma, 0.f), 2.6f) / 0.91655527974030934f; } static float FromLinearSmpte428(float linear) { - return Powf(MAX(linear, 0.f), 2.6f) / 0.91655527974030934f; + return Powf(0.91655527974030934f * MAX(linear, 0.f), 1.f / 2.6f); } // Conversion in BT.2100 requires RGB info. Simplify to gamma correction here. diff --git a/3rdparty/libwebp/src/dec/alpha_dec.c b/3rdparty/libwebp/src/dec/alpha_dec.c index 663255c42f..b6c874fb84 100644 --- a/3rdparty/libwebp/src/dec/alpha_dec.c +++ b/3rdparty/libwebp/src/dec/alpha_dec.c @@ -13,18 +13,20 @@ #include #include "src/dec/alphai_dec.h" +#include "src/dec/vp8_dec.h" #include "src/dec/vp8i_dec.h" #include "src/dec/vp8li_dec.h" #include "src/dsp/dsp.h" #include "src/utils/quant_levels_dec_utils.h" #include "src/utils/utils.h" #include "src/webp/format_constants.h" +#include "src/webp/types.h" //------------------------------------------------------------------------------ // ALPHDecoder object. // Allocates a new alpha decoder instance. -static ALPHDecoder* ALPHNew(void) { +WEBP_NODISCARD static ALPHDecoder* ALPHNew(void) { ALPHDecoder* const dec = (ALPHDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec)); return dec; } @@ -45,9 +47,9 @@ static void ALPHDelete(ALPHDecoder* const dec) { // header for alpha data stored using lossless compression. // Returns false in case of error in alpha header (data too short, invalid // compression method or filter, error in lossless header data etc). -static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data, - size_t data_size, const VP8Io* const src_io, - uint8_t* output) { +WEBP_NODISCARD static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data, + size_t data_size, const VP8Io* const src_io, + uint8_t* output) { int ok = 0; const uint8_t* const alpha_data = data + ALPHA_HEADER_LEN; const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN; @@ -79,7 +81,9 @@ static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data, } // Copy the necessary parameters from src_io to io - VP8InitIo(io); + if (!VP8InitIo(io)) { + return 0; + } WebPInitCustomIo(NULL, io); io->opaque = dec; io->width = src_io->width; @@ -107,7 +111,8 @@ static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data, // starting from row number 'row'. It assumes that rows up to (row - 1) have // already been decoded. // Returns false in case of bitstream error. -static int ALPHDecode(VP8Decoder* const dec, int row, int num_rows) { +WEBP_NODISCARD static int ALPHDecode(VP8Decoder* const dec, int row, + int num_rows) { ALPHDecoder* const alph_dec = dec->alph_dec_; const int width = alph_dec->width_; const int height = alph_dec->io_.crop_bottom; @@ -138,7 +143,8 @@ static int ALPHDecode(VP8Decoder* const dec, int row, int num_rows) { return 1; } -static int AllocateAlphaPlane(VP8Decoder* const dec, const VP8Io* const io) { +WEBP_NODISCARD static int AllocateAlphaPlane(VP8Decoder* const dec, + const VP8Io* const io) { const int stride = io->width; const int height = io->crop_bottom; const uint64_t alpha_size = (uint64_t)stride * height; @@ -166,9 +172,9 @@ void WebPDeallocateAlphaMemory(VP8Decoder* const dec) { //------------------------------------------------------------------------------ // Main entry point. -const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, - const VP8Io* const io, - int row, int num_rows) { +WEBP_NODISCARD const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, + const VP8Io* const io, + int row, int num_rows) { const int width = io->width; const int height = io->crop_bottom; diff --git a/3rdparty/libwebp/src/dec/idec_dec.c b/3rdparty/libwebp/src/dec/idec_dec.c index 9035df5659..ad042a1ffc 100644 --- a/3rdparty/libwebp/src/dec/idec_dec.c +++ b/3rdparty/libwebp/src/dec/idec_dec.c @@ -17,8 +17,10 @@ #include "src/dec/alphai_dec.h" #include "src/dec/webpi_dec.h" +#include "src/dec/vp8_dec.h" #include "src/dec/vp8i_dec.h" #include "src/utils/utils.h" +#include "src/webp/decode.h" // In append mode, buffer allocations increase as multiples of this value. // Needs to be a power of 2. @@ -161,8 +163,9 @@ static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) { // Appends data to the end of MemBuffer->buf_. It expands the allocated memory // size if required and also updates VP8BitReader's if new memory is allocated. -static int AppendToMemBuffer(WebPIDecoder* const idec, - const uint8_t* const data, size_t data_size) { +WEBP_NODISCARD static int AppendToMemBuffer(WebPIDecoder* const idec, + const uint8_t* const data, + size_t data_size) { VP8Decoder* const dec = (VP8Decoder*)idec->dec_; MemBuffer* const mem = &idec->mem_; const int need_compressed_alpha = NeedCompressedAlpha(idec); @@ -203,8 +206,9 @@ static int AppendToMemBuffer(WebPIDecoder* const idec, return 1; } -static int RemapMemBuffer(WebPIDecoder* const idec, - const uint8_t* const data, size_t data_size) { +WEBP_NODISCARD static int RemapMemBuffer(WebPIDecoder* const idec, + const uint8_t* const data, + size_t data_size) { MemBuffer* const mem = &idec->mem_; const uint8_t* const old_buf = mem->buf_; const uint8_t* const old_start = @@ -237,7 +241,8 @@ static void ClearMemBuffer(MemBuffer* const mem) { } } -static int CheckMemBufferMode(MemBuffer* const mem, MemBufferMode expected) { +WEBP_NODISCARD static int CheckMemBufferMode(MemBuffer* const mem, + MemBufferMode expected) { if (mem->mode_ == MEM_MODE_NONE) { mem->mode_ = expected; // switch to the expected mode } else if (mem->mode_ != expected) { @@ -248,7 +253,7 @@ static int CheckMemBufferMode(MemBuffer* const mem, MemBufferMode expected) { } // To be called last. -static VP8StatusCode FinishDecoding(WebPIDecoder* const idec) { +WEBP_NODISCARD static VP8StatusCode FinishDecoding(WebPIDecoder* const idec) { const WebPDecoderOptions* const options = idec->params_.options; WebPDecBuffer* const output = idec->params_.output; @@ -258,8 +263,10 @@ static VP8StatusCode FinishDecoding(WebPIDecoder* const idec) { if (status != VP8_STATUS_OK) return status; } if (idec->final_output_ != NULL) { - WebPCopyDecBufferPixels(output, idec->final_output_); // do the slow-copy + const VP8StatusCode status = WebPCopyDecBufferPixels( + output, idec->final_output_); // do the slow-copy WebPFreeDecBuffer(&idec->output_); + if (status != VP8_STATUS_OK) return status; *output = *idec->final_output_; idec->final_output_ = NULL; } @@ -288,7 +295,7 @@ static void RestoreContext(const MBContext* context, VP8Decoder* const dec, static VP8StatusCode IDecError(WebPIDecoder* const idec, VP8StatusCode error) { if (idec->state_ == STATE_VP8_DATA) { // Synchronize the thread, clean-up and check for errors. - VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_); + (void)VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_); } idec->state_ = STATE_ERROR; return error; @@ -329,6 +336,7 @@ static VP8StatusCode DecodeWebPHeaders(WebPIDecoder* const idec) { if (dec == NULL) { return VP8_STATUS_OUT_OF_MEMORY; } + dec->incremental_ = 1; idec->dec_ = dec; dec->alpha_data_ = headers.alpha_data; dec->alpha_data_size_ = headers.alpha_data_size; @@ -601,8 +609,9 @@ static VP8StatusCode IDecode(WebPIDecoder* idec) { //------------------------------------------------------------------------------ // Internal constructor -static WebPIDecoder* NewDecoder(WebPDecBuffer* const output_buffer, - const WebPBitstreamFeatures* const features) { +WEBP_NODISCARD static WebPIDecoder* NewDecoder( + WebPDecBuffer* const output_buffer, + const WebPBitstreamFeatures* const features) { WebPIDecoder* idec = (WebPIDecoder*)WebPSafeCalloc(1ULL, sizeof(*idec)); if (idec == NULL) { return NULL; @@ -614,8 +623,10 @@ static WebPIDecoder* NewDecoder(WebPDecBuffer* const output_buffer, idec->last_mb_y_ = -1; InitMemBuffer(&idec->mem_); - WebPInitDecBuffer(&idec->output_); - VP8InitIo(&idec->io_); + if (!WebPInitDecBuffer(&idec->output_) || !VP8InitIo(&idec->io_)) { + WebPSafeFree(idec); + return NULL; + } WebPResetDecParams(&idec->params_); if (output_buffer == NULL || WebPAvoidSlowMemory(output_buffer, features)) { @@ -674,7 +685,8 @@ void WebPIDelete(WebPIDecoder* idec) { if (!idec->is_lossless_) { if (idec->state_ == STATE_VP8_DATA) { // Synchronize the thread, clean-up and check for errors. - VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_); + // TODO(vrabaud) do we care about the return result? + (void)VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_); } VP8Delete((VP8Decoder*)idec->dec_); } else { @@ -851,8 +863,8 @@ const WebPDecBuffer* WebPIDecodedArea(const WebPIDecoder* idec, return src; } -uint8_t* WebPIDecGetRGB(const WebPIDecoder* idec, int* last_y, - int* width, int* height, int* stride) { +WEBP_NODISCARD uint8_t* WebPIDecGetRGB(const WebPIDecoder* idec, int* last_y, + int* width, int* height, int* stride) { const WebPDecBuffer* const src = GetOutputBuffer(idec); if (src == NULL) return NULL; if (src->colorspace >= MODE_YUV) { @@ -867,10 +879,10 @@ uint8_t* WebPIDecGetRGB(const WebPIDecoder* idec, int* last_y, return src->u.RGBA.rgba; } -uint8_t* WebPIDecGetYUVA(const WebPIDecoder* idec, int* last_y, - uint8_t** u, uint8_t** v, uint8_t** a, - int* width, int* height, - int* stride, int* uv_stride, int* a_stride) { +WEBP_NODISCARD uint8_t* WebPIDecGetYUVA(const WebPIDecoder* idec, int* last_y, + uint8_t** u, uint8_t** v, uint8_t** a, + int* width, int* height, int* stride, + int* uv_stride, int* a_stride) { const WebPDecBuffer* const src = GetOutputBuffer(idec); if (src == NULL) return NULL; if (src->colorspace < MODE_YUV) { diff --git a/3rdparty/libwebp/src/dec/vp8_dec.c b/3rdparty/libwebp/src/dec/vp8_dec.c index 20b92e84c4..2ee8900605 100644 --- a/3rdparty/libwebp/src/dec/vp8_dec.c +++ b/3rdparty/libwebp/src/dec/vp8_dec.c @@ -86,6 +86,8 @@ void VP8Delete(VP8Decoder* const dec) { int VP8SetError(VP8Decoder* const dec, VP8StatusCode error, const char* const msg) { + // VP8_STATUS_SUSPENDED is only meaningful in incremental decoding. + assert(dec->incremental_ || error != VP8_STATUS_SUSPENDED); // The oldest error reported takes precedence over the new one. if (dec->status_ == VP8_STATUS_OK) { dec->status_ = error; @@ -190,12 +192,12 @@ static int ParseSegmentHeader(VP8BitReader* br, } // Paragraph 9.5 -// This function returns VP8_STATUS_SUSPENDED if we don't have all the -// necessary data in 'buf'. -// This case is not necessarily an error (for incremental decoding). -// Still, no bitreader is ever initialized to make it possible to read -// unavailable memory. -// If we don't even have the partitions' sizes, than VP8_STATUS_NOT_ENOUGH_DATA +// If we don't have all the necessary data in 'buf', this function returns +// VP8_STATUS_SUSPENDED in incremental decoding, VP8_STATUS_NOT_ENOUGH_DATA +// otherwise. +// In incremental decoding, this case is not necessarily an error. Still, no +// bitreader is ever initialized to make it possible to read unavailable memory. +// If we don't even have the partitions' sizes, then VP8_STATUS_NOT_ENOUGH_DATA // is returned, and this is an unrecoverable error. // If the partitions were positioned ok, VP8_STATUS_OK is returned. static VP8StatusCode ParsePartitions(VP8Decoder* const dec, @@ -225,8 +227,10 @@ static VP8StatusCode ParsePartitions(VP8Decoder* const dec, sz += 3; } VP8InitBitReader(dec->parts_ + last_part, part_start, size_left); - return (part_start < buf_end) ? VP8_STATUS_OK : - VP8_STATUS_SUSPENDED; // Init is ok, but there's not enough data + if (part_start < buf_end) return VP8_STATUS_OK; + return dec->incremental_ + ? VP8_STATUS_SUSPENDED // Init is ok, but there's not enough data + : VP8_STATUS_NOT_ENOUGH_DATA; } // Paragraph 9.4 diff --git a/3rdparty/libwebp/src/dec/vp8_dec.h b/3rdparty/libwebp/src/dec/vp8_dec.h index a05405df72..91fe104093 100644 --- a/3rdparty/libwebp/src/dec/vp8_dec.h +++ b/3rdparty/libwebp/src/dec/vp8_dec.h @@ -15,6 +15,7 @@ #define WEBP_DEC_VP8_DEC_H_ #include "src/webp/decode.h" +#include "src/webp/types.h" #ifdef __cplusplus extern "C" { @@ -108,16 +109,14 @@ struct VP8Io { }; // Internal, version-checked, entry point -int VP8InitIoInternal(VP8Io* const, int); +WEBP_NODISCARD int VP8InitIoInternal(VP8Io* const, int); // Set the custom IO function pointers and user-data. The setter for IO hooks // should be called before initiating incremental decoding. Returns true if // WebPIDecoder object is successfully modified, false otherwise. -int WebPISetIOHooks(WebPIDecoder* const idec, - VP8IoPutHook put, - VP8IoSetupHook setup, - VP8IoTeardownHook teardown, - void* user_data); +WEBP_NODISCARD int WebPISetIOHooks(WebPIDecoder* const idec, VP8IoPutHook put, + VP8IoSetupHook setup, + VP8IoTeardownHook teardown, void* user_data); // Main decoding object. This is an opaque structure. typedef struct VP8Decoder VP8Decoder; @@ -128,17 +127,17 @@ VP8Decoder* VP8New(void); // Must be called to make sure 'io' is initialized properly. // Returns false in case of version mismatch. Upon such failure, no other // decoding function should be called (VP8Decode, VP8GetHeaders, ...) -static WEBP_INLINE int VP8InitIo(VP8Io* const io) { +WEBP_NODISCARD static WEBP_INLINE int VP8InitIo(VP8Io* const io) { return VP8InitIoInternal(io, WEBP_DECODER_ABI_VERSION); } // Decode the VP8 frame header. Returns true if ok. // Note: 'io->data' must be pointing to the start of the VP8 frame header. -int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io); +WEBP_NODISCARD int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io); // Decode a picture. Will call VP8GetHeaders() if it wasn't done already. // Returns false in case of error. -int VP8Decode(VP8Decoder* const dec, VP8Io* const io); +WEBP_NODISCARD int VP8Decode(VP8Decoder* const dec, VP8Io* const io); // Return current status of the decoder: VP8StatusCode VP8Status(VP8Decoder* const dec); diff --git a/3rdparty/libwebp/src/dec/vp8i_dec.h b/3rdparty/libwebp/src/dec/vp8i_dec.h index 1ae4ff62f2..cb21d475ae 100644 --- a/3rdparty/libwebp/src/dec/vp8i_dec.h +++ b/3rdparty/libwebp/src/dec/vp8i_dec.h @@ -21,6 +21,7 @@ #include "src/utils/random_utils.h" #include "src/utils/thread_utils.h" #include "src/dsp/dsp.h" +#include "src/webp/types.h" #ifdef __cplusplus extern "C" { @@ -31,8 +32,8 @@ extern "C" { // version numbers #define DEC_MAJ_VERSION 1 -#define DEC_MIN_VERSION 3 -#define DEC_REV_VERSION 1 +#define DEC_MIN_VERSION 4 +#define DEC_REV_VERSION 0 // YUV-cache parameters. Cache is 32-bytes wide (= one cacheline). // Constraints are: We need to store one 16x16 block of luma samples (y), @@ -186,6 +187,7 @@ struct VP8Decoder { // Main data source VP8BitReader br_; + int incremental_; // if true, incremental decoding is expected // headers VP8FrameHeader frm_hdr_; @@ -281,7 +283,7 @@ int VP8ParseIntraModeRow(VP8BitReader* const br, VP8Decoder* const dec); void VP8ParseQuant(VP8Decoder* const dec); // in frame.c -int VP8InitFrame(VP8Decoder* const dec, VP8Io* const io); +WEBP_NODISCARD int VP8InitFrame(VP8Decoder* const dec, VP8Io* const io); // Call io->setup() and finish setting up scan parameters. // After this call returns, one must always call VP8ExitCritical() with the // same parameters. Both functions should be used in pair. Returns VP8_STATUS_OK @@ -289,7 +291,7 @@ int VP8InitFrame(VP8Decoder* const dec, VP8Io* const io); VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io); // Must always be called in pair with VP8EnterCritical(). // Returns false in case of error. -int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io); +WEBP_NODISCARD int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io); // Return the multi-threading method to use (0=off), depending // on options and bitstream size. Only for lossy decoding. int VP8GetThreadMethod(const WebPDecoderOptions* const options, @@ -299,11 +301,12 @@ int VP8GetThreadMethod(const WebPDecoderOptions* const options, void VP8InitDithering(const WebPDecoderOptions* const options, VP8Decoder* const dec); // Process the last decoded row (filtering + output). -int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io); +WEBP_NODISCARD int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io); // To be called at the start of a new scanline, to initialize predictors. void VP8InitScanline(VP8Decoder* const dec); // Decode one macroblock. Returns false if there is not enough data. -int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br); +WEBP_NODISCARD int VP8DecodeMB(VP8Decoder* const dec, + VP8BitReader* const token_br); // in alpha.c const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, diff --git a/3rdparty/libwebp/src/dec/vp8li_dec.h b/3rdparty/libwebp/src/dec/vp8li_dec.h index b057573f6c..9a13bcc98d 100644 --- a/3rdparty/libwebp/src/dec/vp8li_dec.h +++ b/3rdparty/libwebp/src/dec/vp8li_dec.h @@ -20,6 +20,7 @@ #include "src/utils/bit_reader_utils.h" #include "src/utils/color_cache_utils.h" #include "src/utils/huffman_utils.h" +#include "src/webp/types.h" #ifdef __cplusplus extern "C" { @@ -99,25 +100,26 @@ struct ALPHDecoder; // Defined in dec/alphai.h. // Decodes image header for alpha data stored using lossless compression. // Returns false in case of error. -int VP8LDecodeAlphaHeader(struct ALPHDecoder* const alph_dec, - const uint8_t* const data, size_t data_size); +WEBP_NODISCARD int VP8LDecodeAlphaHeader(struct ALPHDecoder* const alph_dec, + const uint8_t* const data, + size_t data_size); // Decodes *at least* 'last_row' rows of alpha. If some of the initial rows are // already decoded in previous call(s), it will resume decoding from where it // was paused. // Returns false in case of bitstream error. -int VP8LDecodeAlphaImageStream(struct ALPHDecoder* const alph_dec, - int last_row); +WEBP_NODISCARD int VP8LDecodeAlphaImageStream( + struct ALPHDecoder* const alph_dec, int last_row); // Allocates and initialize a new lossless decoder instance. -VP8LDecoder* VP8LNew(void); +WEBP_NODISCARD VP8LDecoder* VP8LNew(void); // Decodes the image header. Returns false in case of error. -int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io); +WEBP_NODISCARD int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io); // Decodes an image. It's required to decode the lossless header before calling // this function. Returns false in case of error, with updated dec->status_. -int VP8LDecodeImage(VP8LDecoder* const dec); +WEBP_NODISCARD int VP8LDecodeImage(VP8LDecoder* const dec); // Resets the decoder in its initial state, reclaiming memory. // Preserves the dec->status_ value. @@ -133,11 +135,10 @@ void VP8LDelete(VP8LDecoder* const dec); // 'num_htree_groups' groups. If 'num_htree_groups_max' > 'num_htree_groups', // some of those indices map to -1. This is used for non-balanced codes to // limit memory usage. -int ReadHuffmanCodesHelper(int color_cache_bits, int num_htree_groups, - int num_htree_groups_max, const int* const mapping, - VP8LDecoder* const dec, - HuffmanTables* const huffman_tables, - HTreeGroup** const htree_groups); +WEBP_NODISCARD int ReadHuffmanCodesHelper( + int color_cache_bits, int num_htree_groups, int num_htree_groups_max, + const int* const mapping, VP8LDecoder* const dec, + HuffmanTables* const huffman_tables, HTreeGroup** const htree_groups); //------------------------------------------------------------------------------ diff --git a/3rdparty/libwebp/src/dec/webp_dec.c b/3rdparty/libwebp/src/dec/webp_dec.c index f557868b99..49ef205c8b 100644 --- a/3rdparty/libwebp/src/dec/webp_dec.c +++ b/3rdparty/libwebp/src/dec/webp_dec.c @@ -13,11 +13,14 @@ #include +#include "src/dec/vp8_dec.h" #include "src/dec/vp8i_dec.h" #include "src/dec/vp8li_dec.h" #include "src/dec/webpi_dec.h" #include "src/utils/utils.h" #include "src/webp/mux_types.h" // ALPHA_FLAG +#include "src/webp/decode.h" +#include "src/webp/types.h" //------------------------------------------------------------------------------ // RIFF layout is: @@ -444,8 +447,9 @@ void WebPResetDecParams(WebPDecParams* const params) { // "Into" decoding variants // Main flow -static VP8StatusCode DecodeInto(const uint8_t* const data, size_t data_size, - WebPDecParams* const params) { +WEBP_NODISCARD static VP8StatusCode DecodeInto(const uint8_t* const data, + size_t data_size, + WebPDecParams* const params) { VP8StatusCode status; VP8Io io; WebPHeaderStructure headers; @@ -459,7 +463,9 @@ static VP8StatusCode DecodeInto(const uint8_t* const data, size_t data_size, } assert(params != NULL); - VP8InitIo(&io); + if (!VP8InitIo(&io)) { + return VP8_STATUS_INVALID_PARAM; + } io.data = headers.data + headers.offset; io.data_size = headers.data_size - headers.offset; WebPInitCustomIo(params, &io); // Plug the I/O functions. @@ -523,17 +529,16 @@ static VP8StatusCode DecodeInto(const uint8_t* const data, size_t data_size, } // Helpers -static uint8_t* DecodeIntoRGBABuffer(WEBP_CSP_MODE colorspace, - const uint8_t* const data, - size_t data_size, - uint8_t* const rgba, - int stride, size_t size) { +WEBP_NODISCARD static uint8_t* DecodeIntoRGBABuffer(WEBP_CSP_MODE colorspace, + const uint8_t* const data, + size_t data_size, + uint8_t* const rgba, + int stride, size_t size) { WebPDecParams params; WebPDecBuffer buf; - if (rgba == NULL) { + if (rgba == NULL || !WebPInitDecBuffer(&buf)) { return NULL; } - WebPInitDecBuffer(&buf); WebPResetDecParams(¶ms); params.output = &buf; buf.colorspace = colorspace; @@ -578,8 +583,7 @@ uint8_t* WebPDecodeYUVInto(const uint8_t* data, size_t data_size, uint8_t* v, size_t v_size, int v_stride) { WebPDecParams params; WebPDecBuffer output; - if (luma == NULL) return NULL; - WebPInitDecBuffer(&output); + if (luma == NULL || !WebPInitDecBuffer(&output)) return NULL; WebPResetDecParams(¶ms); params.output = &output; output.colorspace = MODE_YUV; @@ -601,13 +605,17 @@ uint8_t* WebPDecodeYUVInto(const uint8_t* data, size_t data_size, //------------------------------------------------------------------------------ -static uint8_t* Decode(WEBP_CSP_MODE mode, const uint8_t* const data, - size_t data_size, int* const width, int* const height, - WebPDecBuffer* const keep_info) { +WEBP_NODISCARD static uint8_t* Decode(WEBP_CSP_MODE mode, + const uint8_t* const data, + size_t data_size, int* const width, + int* const height, + WebPDecBuffer* const keep_info) { WebPDecParams params; WebPDecBuffer output; - WebPInitDecBuffer(&output); + if (!WebPInitDecBuffer(&output)) { + return NULL; + } WebPResetDecParams(¶ms); params.output = &output; output.colorspace = mode; @@ -733,7 +741,9 @@ int WebPInitDecoderConfigInternal(WebPDecoderConfig* config, } memset(config, 0, sizeof(*config)); DefaultFeatures(&config->input); - WebPInitDecBuffer(&config->output); + if (!WebPInitDecBuffer(&config->output)) { + return 0; + } return 1; } @@ -772,7 +782,9 @@ VP8StatusCode WebPDecode(const uint8_t* data, size_t data_size, if (WebPAvoidSlowMemory(params.output, &config->input)) { // decoding to slow memory: use a temporary in-mem buffer to decode into. WebPDecBuffer in_mem_buffer; - WebPInitDecBuffer(&in_mem_buffer); + if (!WebPInitDecBuffer(&in_mem_buffer)) { + return VP8_STATUS_INVALID_PARAM; + } in_mem_buffer.colorspace = config->output.colorspace; in_mem_buffer.width = config->input.width; in_mem_buffer.height = config->input.height; diff --git a/3rdparty/libwebp/src/dec/webpi_dec.h b/3rdparty/libwebp/src/dec/webpi_dec.h index 3b97388c71..77bf5264b7 100644 --- a/3rdparty/libwebp/src/dec/webpi_dec.h +++ b/3rdparty/libwebp/src/dec/webpi_dec.h @@ -20,6 +20,7 @@ extern "C" { #include "src/utils/rescaler_utils.h" #include "src/dec/vp8_dec.h" +#include "src/webp/decode.h" //------------------------------------------------------------------------------ // WebPDecParams: Decoding output parameters. Transient internal object. @@ -87,8 +88,9 @@ void WebPInitCustomIo(WebPDecParams* const params, VP8Io* const io); // Setup crop_xxx fields, mb_w and mb_h in io. 'src_colorspace' refers // to the *compressed* format, not the output one. -int WebPIoInitFromOptions(const WebPDecoderOptions* const options, - VP8Io* const io, WEBP_CSP_MODE src_colorspace); +WEBP_NODISCARD int WebPIoInitFromOptions( + const WebPDecoderOptions* const options, VP8Io* const io, + WEBP_CSP_MODE src_colorspace); //------------------------------------------------------------------------------ // Internal functions regarding WebPDecBuffer memory (in buffer.c). diff --git a/3rdparty/libwebp/src/demux/anim_decode.c b/3rdparty/libwebp/src/demux/anim_decode.c index e077ffb536..27f0e2b0bb 100644 --- a/3rdparty/libwebp/src/demux/anim_decode.c +++ b/3rdparty/libwebp/src/demux/anim_decode.c @@ -20,6 +20,7 @@ #include "src/utils/utils.h" #include "src/webp/decode.h" #include "src/webp/demux.h" +#include "src/webp/types.h" #define NUM_CHANNELS 4 @@ -68,8 +69,9 @@ int WebPAnimDecoderOptionsInitInternal(WebPAnimDecoderOptions* dec_options, return 1; } -static int ApplyDecoderOptions(const WebPAnimDecoderOptions* const dec_options, - WebPAnimDecoder* const dec) { +WEBP_NODISCARD static int ApplyDecoderOptions( + const WebPAnimDecoderOptions* const dec_options, + WebPAnimDecoder* const dec) { WEBP_CSP_MODE mode; WebPDecoderConfig* config = &dec->config_; assert(dec_options != NULL); @@ -82,7 +84,9 @@ static int ApplyDecoderOptions(const WebPAnimDecoderOptions* const dec_options, dec->blend_func_ = (mode == MODE_RGBA || mode == MODE_BGRA) ? &BlendPixelRowNonPremult : &BlendPixelRowPremult; - WebPInitDecoderConfig(config); + if (!WebPInitDecoderConfig(config)) { + return 0; + } config->output.colorspace = mode; config->output.is_external_memory = 1; config->options.use_threads = dec_options->use_threads; @@ -157,8 +161,8 @@ static int IsFullFrame(int width, int height, int canvas_width, } // Clear the canvas to transparent. -static int ZeroFillCanvas(uint8_t* buf, uint32_t canvas_width, - uint32_t canvas_height) { +WEBP_NODISCARD static int ZeroFillCanvas(uint8_t* buf, uint32_t canvas_width, + uint32_t canvas_height) { const uint64_t size = (uint64_t)canvas_width * canvas_height * NUM_CHANNELS * sizeof(*buf); if (!CheckSizeOverflow(size)) return 0; @@ -179,8 +183,8 @@ static void ZeroFillFrameRect(uint8_t* buf, int buf_stride, int x_offset, } // Copy width * height pixels from 'src' to 'dst'. -static int CopyCanvas(const uint8_t* src, uint8_t* dst, - uint32_t width, uint32_t height) { +WEBP_NODISCARD static int CopyCanvas(const uint8_t* src, uint8_t* dst, + uint32_t width, uint32_t height) { const uint64_t size = (uint64_t)width * height * NUM_CHANNELS; if (!CheckSizeOverflow(size)) return 0; assert(src != NULL && dst != NULL); @@ -424,7 +428,9 @@ int WebPAnimDecoderGetNext(WebPAnimDecoder* dec, WebPDemuxReleaseIterator(&dec->prev_iter_); dec->prev_iter_ = iter; dec->prev_frame_was_keyframe_ = is_key_frame; - CopyCanvas(dec->curr_frame_, dec->prev_frame_disposed_, width, height); + if (!CopyCanvas(dec->curr_frame_, dec->prev_frame_disposed_, width, height)) { + goto Error; + } if (dec->prev_iter_.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) { ZeroFillFrameRect(dec->prev_frame_disposed_, width * NUM_CHANNELS, dec->prev_iter_.x_offset, dec->prev_iter_.y_offset, diff --git a/3rdparty/libwebp/src/demux/demux.c b/3rdparty/libwebp/src/demux/demux.c index fd45a2500e..d01c6a7464 100644 --- a/3rdparty/libwebp/src/demux/demux.c +++ b/3rdparty/libwebp/src/demux/demux.c @@ -24,8 +24,8 @@ #include "src/webp/format_constants.h" #define DMUX_MAJ_VERSION 1 -#define DMUX_MIN_VERSION 3 -#define DMUX_REV_VERSION 1 +#define DMUX_MIN_VERSION 4 +#define DMUX_REV_VERSION 0 typedef struct { size_t start_; // start location of the data diff --git a/3rdparty/libwebp/src/dsp/cpu.c b/3rdparty/libwebp/src/dsp/cpu.c index 2234c77b35..8ba8f68335 100644 --- a/3rdparty/libwebp/src/dsp/cpu.c +++ b/3rdparty/libwebp/src/dsp/cpu.c @@ -36,18 +36,6 @@ static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) { : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3]) : "a"(info_type), "c"(0)); } -#elif defined(__x86_64__) && \ - (defined(__code_model_medium__) || defined(__code_model_large__)) && \ - defined(__PIC__) -static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) { - __asm__ volatile ( - "xchg{q}\t{%%rbx}, %q1\n" - "cpuid\n" - "xchg{q}\t{%%rbx}, %q1\n" - : "=a"(cpu_info[0]), "=&r"(cpu_info[1]), "=c"(cpu_info[2]), - "=d"(cpu_info[3]) - : "a"(info_type), "c"(0)); -} #elif defined(__i386__) || defined(__x86_64__) static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) { __asm__ volatile ( diff --git a/3rdparty/libwebp/src/dsp/dec.c b/3rdparty/libwebp/src/dsp/dec.c index 33d8df8a62..451d649d58 100644 --- a/3rdparty/libwebp/src/dsp/dec.c +++ b/3rdparty/libwebp/src/dsp/dec.c @@ -37,9 +37,6 @@ static WEBP_INLINE uint8_t clip_8b(int v) { STORE(3, y, DC - (d)); \ } while (0) -#define MUL1(a) ((((a) * 20091) >> 16) + (a)) -#define MUL2(a) (((a) * 35468) >> 16) - #if !WEBP_NEON_OMIT_C_CODE static void TransformOne_C(const int16_t* in, uint8_t* dst) { int C[4 * 4], *tmp; @@ -48,8 +45,10 @@ static void TransformOne_C(const int16_t* in, uint8_t* dst) { for (i = 0; i < 4; ++i) { // vertical pass const int a = in[0] + in[8]; // [-4096, 4094] const int b = in[0] - in[8]; // [-4095, 4095] - const int c = MUL2(in[4]) - MUL1(in[12]); // [-3783, 3783] - const int d = MUL1(in[4]) + MUL2(in[12]); // [-3785, 3781] + const int c = WEBP_TRANSFORM_AC3_MUL2(in[4]) - + WEBP_TRANSFORM_AC3_MUL1(in[12]); // [-3783, 3783] + const int d = WEBP_TRANSFORM_AC3_MUL1(in[4]) + + WEBP_TRANSFORM_AC3_MUL2(in[12]); // [-3785, 3781] tmp[0] = a + d; // [-7881, 7875] tmp[1] = b + c; // [-7878, 7878] tmp[2] = b - c; // [-7878, 7878] @@ -69,8 +68,10 @@ static void TransformOne_C(const int16_t* in, uint8_t* dst) { const int dc = tmp[0] + 4; const int a = dc + tmp[8]; const int b = dc - tmp[8]; - const int c = MUL2(tmp[4]) - MUL1(tmp[12]); - const int d = MUL1(tmp[4]) + MUL2(tmp[12]); + const int c = + WEBP_TRANSFORM_AC3_MUL2(tmp[4]) - WEBP_TRANSFORM_AC3_MUL1(tmp[12]); + const int d = + WEBP_TRANSFORM_AC3_MUL1(tmp[4]) + WEBP_TRANSFORM_AC3_MUL2(tmp[12]); STORE(0, 0, a + d); STORE(1, 0, b + c); STORE(2, 0, b - c); @@ -83,17 +84,15 @@ static void TransformOne_C(const int16_t* in, uint8_t* dst) { // Simplified transform when only in[0], in[1] and in[4] are non-zero static void TransformAC3_C(const int16_t* in, uint8_t* dst) { const int a = in[0] + 4; - const int c4 = MUL2(in[4]); - const int d4 = MUL1(in[4]); - const int c1 = MUL2(in[1]); - const int d1 = MUL1(in[1]); + const int c4 = WEBP_TRANSFORM_AC3_MUL2(in[4]); + const int d4 = WEBP_TRANSFORM_AC3_MUL1(in[4]); + const int c1 = WEBP_TRANSFORM_AC3_MUL2(in[1]); + const int d1 = WEBP_TRANSFORM_AC3_MUL1(in[1]); STORE2(0, a + d4, d1, c1); STORE2(1, a + c4, d1, c1); STORE2(2, a - c4, d1, c1); STORE2(3, a - d4, d1, c1); } -#undef MUL1 -#undef MUL2 #undef STORE2 static void TransformTwo_C(const int16_t* in, uint8_t* dst, int do_two) { diff --git a/3rdparty/libwebp/src/dsp/dec_mips32.c b/3rdparty/libwebp/src/dsp/dec_mips32.c index e4e70966d2..f0e7de4ac4 100644 --- a/3rdparty/libwebp/src/dsp/dec_mips32.c +++ b/3rdparty/libwebp/src/dsp/dec_mips32.c @@ -18,8 +18,8 @@ #include "src/dsp/mips_macro.h" -static const int kC1 = 20091 + (1 << 16); -static const int kC2 = 35468; +static const int kC1 = WEBP_TRANSFORM_AC3_C1; +static const int kC2 = WEBP_TRANSFORM_AC3_C2; static WEBP_INLINE int abs_mips32(int x) { const int sign = x >> 31; @@ -219,7 +219,7 @@ static void TransformOne(const int16_t* in, uint8_t* dst) { int temp0, temp1, temp2, temp3, temp4; int temp5, temp6, temp7, temp8, temp9; int temp10, temp11, temp12, temp13, temp14; - int temp15, temp16, temp17, temp18; + int temp15, temp16, temp17, temp18, temp19; int16_t* p_in = (int16_t*)in; // loops unrolled and merged to avoid usage of tmp buffer @@ -233,16 +233,14 @@ static void TransformOne(const int16_t* in, uint8_t* dst) { "addu %[temp16], %[temp0], %[temp8] \n\t" "subu %[temp0], %[temp0], %[temp8] \n\t" "mul %[temp8], %[temp4], %[kC2] \n\t" - "mul %[temp17], %[temp12], %[kC1] \n\t" - "mul %[temp4], %[temp4], %[kC1] \n\t" + MUL_SHIFT_C1(temp17, temp12) + MUL_SHIFT_C1_IO(temp4, temp19) "mul %[temp12], %[temp12], %[kC2] \n\t" "lh %[temp1], 2(%[in]) \n\t" "lh %[temp5], 10(%[in]) \n\t" "lh %[temp9], 18(%[in]) \n\t" "lh %[temp13], 26(%[in]) \n\t" "sra %[temp8], %[temp8], 16 \n\t" - "sra %[temp17], %[temp17], 16 \n\t" - "sra %[temp4], %[temp4], 16 \n\t" "sra %[temp12], %[temp12], 16 \n\t" "lh %[temp2], 4(%[in]) \n\t" "lh %[temp6], 12(%[in]) \n\t" @@ -261,49 +259,43 @@ static void TransformOne(const int16_t* in, uint8_t* dst) { "addu %[temp12], %[temp0], %[temp17] \n\t" "subu %[temp0], %[temp0], %[temp17] \n\t" "mul %[temp9], %[temp5], %[kC2] \n\t" - "mul %[temp17], %[temp13], %[kC1] \n\t" - "mul %[temp5], %[temp5], %[kC1] \n\t" + MUL_SHIFT_C1(temp17, temp13) + MUL_SHIFT_C1_IO(temp5, temp19) "mul %[temp13], %[temp13], %[kC2] \n\t" "sra %[temp9], %[temp9], 16 \n\t" - "sra %[temp17], %[temp17], 16 \n\t" "subu %[temp17], %[temp9], %[temp17] \n\t" - "sra %[temp5], %[temp5], 16 \n\t" "sra %[temp13], %[temp13], 16 \n\t" "addu %[temp5], %[temp5], %[temp13] \n\t" "addu %[temp13], %[temp1], %[temp17] \n\t" "subu %[temp1], %[temp1], %[temp17] \n\t" - "mul %[temp17], %[temp14], %[kC1] \n\t" + MUL_SHIFT_C1(temp17, temp14) "mul %[temp14], %[temp14], %[kC2] \n\t" "addu %[temp9], %[temp16], %[temp5] \n\t" "subu %[temp5], %[temp16], %[temp5] \n\t" "addu %[temp16], %[temp2], %[temp10] \n\t" "subu %[temp2], %[temp2], %[temp10] \n\t" "mul %[temp10], %[temp6], %[kC2] \n\t" - "mul %[temp6], %[temp6], %[kC1] \n\t" - "sra %[temp17], %[temp17], 16 \n\t" + MUL_SHIFT_C1_IO(temp6, temp19) "sra %[temp14], %[temp14], 16 \n\t" "sra %[temp10], %[temp10], 16 \n\t" - "sra %[temp6], %[temp6], 16 \n\t" "subu %[temp17], %[temp10], %[temp17] \n\t" "addu %[temp6], %[temp6], %[temp14] \n\t" "addu %[temp10], %[temp16], %[temp6] \n\t" "subu %[temp6], %[temp16], %[temp6] \n\t" "addu %[temp14], %[temp2], %[temp17] \n\t" "subu %[temp2], %[temp2], %[temp17] \n\t" - "mul %[temp17], %[temp15], %[kC1] \n\t" + MUL_SHIFT_C1(temp17, temp15) "mul %[temp15], %[temp15], %[kC2] \n\t" "addu %[temp16], %[temp3], %[temp11] \n\t" "subu %[temp3], %[temp3], %[temp11] \n\t" "mul %[temp11], %[temp7], %[kC2] \n\t" - "mul %[temp7], %[temp7], %[kC1] \n\t" + MUL_SHIFT_C1_IO(temp7, temp19) "addiu %[temp8], %[temp8], 4 \n\t" "addiu %[temp12], %[temp12], 4 \n\t" "addiu %[temp0], %[temp0], 4 \n\t" "addiu %[temp4], %[temp4], 4 \n\t" - "sra %[temp17], %[temp17], 16 \n\t" "sra %[temp15], %[temp15], 16 \n\t" "sra %[temp11], %[temp11], 16 \n\t" - "sra %[temp7], %[temp7], 16 \n\t" "subu %[temp17], %[temp11], %[temp17] \n\t" "addu %[temp7], %[temp7], %[temp15] \n\t" "addu %[temp15], %[temp3], %[temp17] \n\t" @@ -313,48 +305,40 @@ static void TransformOne(const int16_t* in, uint8_t* dst) { "addu %[temp16], %[temp8], %[temp10] \n\t" "subu %[temp8], %[temp8], %[temp10] \n\t" "mul %[temp10], %[temp9], %[kC2] \n\t" - "mul %[temp17], %[temp11], %[kC1] \n\t" - "mul %[temp9], %[temp9], %[kC1] \n\t" + MUL_SHIFT_C1(temp17, temp11) + MUL_SHIFT_C1_IO(temp9, temp19) "mul %[temp11], %[temp11], %[kC2] \n\t" "sra %[temp10], %[temp10], 16 \n\t" - "sra %[temp17], %[temp17], 16 \n\t" - "sra %[temp9], %[temp9], 16 \n\t" "sra %[temp11], %[temp11], 16 \n\t" "subu %[temp17], %[temp10], %[temp17] \n\t" "addu %[temp11], %[temp9], %[temp11] \n\t" "addu %[temp10], %[temp12], %[temp14] \n\t" "subu %[temp12], %[temp12], %[temp14] \n\t" "mul %[temp14], %[temp13], %[kC2] \n\t" - "mul %[temp9], %[temp15], %[kC1] \n\t" - "mul %[temp13], %[temp13], %[kC1] \n\t" + MUL_SHIFT_C1(temp9, temp15) + MUL_SHIFT_C1_IO(temp13, temp19) "mul %[temp15], %[temp15], %[kC2] \n\t" "sra %[temp14], %[temp14], 16 \n\t" - "sra %[temp9], %[temp9], 16 \n\t" - "sra %[temp13], %[temp13], 16 \n\t" "sra %[temp15], %[temp15], 16 \n\t" "subu %[temp9], %[temp14], %[temp9] \n\t" "addu %[temp15], %[temp13], %[temp15] \n\t" "addu %[temp14], %[temp0], %[temp2] \n\t" "subu %[temp0], %[temp0], %[temp2] \n\t" "mul %[temp2], %[temp1], %[kC2] \n\t" - "mul %[temp13], %[temp3], %[kC1] \n\t" - "mul %[temp1], %[temp1], %[kC1] \n\t" + MUL_SHIFT_C1(temp13, temp3) + MUL_SHIFT_C1_IO(temp1, temp19) "mul %[temp3], %[temp3], %[kC2] \n\t" "sra %[temp2], %[temp2], 16 \n\t" - "sra %[temp13], %[temp13], 16 \n\t" - "sra %[temp1], %[temp1], 16 \n\t" "sra %[temp3], %[temp3], 16 \n\t" "subu %[temp13], %[temp2], %[temp13] \n\t" "addu %[temp3], %[temp1], %[temp3] \n\t" "addu %[temp2], %[temp4], %[temp6] \n\t" "subu %[temp4], %[temp4], %[temp6] \n\t" "mul %[temp6], %[temp5], %[kC2] \n\t" - "mul %[temp1], %[temp7], %[kC1] \n\t" - "mul %[temp5], %[temp5], %[kC1] \n\t" + MUL_SHIFT_C1(temp1, temp7) + MUL_SHIFT_C1_IO(temp5, temp19) "mul %[temp7], %[temp7], %[kC2] \n\t" "sra %[temp6], %[temp6], 16 \n\t" - "sra %[temp1], %[temp1], 16 \n\t" - "sra %[temp5], %[temp5], 16 \n\t" "sra %[temp7], %[temp7], 16 \n\t" "subu %[temp1], %[temp6], %[temp1] \n\t" "addu %[temp7], %[temp5], %[temp7] \n\t" @@ -542,7 +526,7 @@ static void TransformOne(const int16_t* in, uint8_t* dst) { [temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11), [temp12]"=&r"(temp12), [temp13]"=&r"(temp13), [temp14]"=&r"(temp14), [temp15]"=&r"(temp15), [temp16]"=&r"(temp16), [temp17]"=&r"(temp17), - [temp18]"=&r"(temp18) + [temp18]"=&r"(temp18), [temp19]"=&r"(temp19) : [in]"r"(p_in), [kC1]"r"(kC1), [kC2]"r"(kC2), [dst]"r"(dst) : "memory", "hi", "lo" ); diff --git a/3rdparty/libwebp/src/dsp/dec_mips_dsp_r2.c b/3rdparty/libwebp/src/dsp/dec_mips_dsp_r2.c index b0936bc46e..0ba706a2ef 100644 --- a/3rdparty/libwebp/src/dsp/dec_mips_dsp_r2.c +++ b/3rdparty/libwebp/src/dsp/dec_mips_dsp_r2.c @@ -18,10 +18,8 @@ #include "src/dsp/mips_macro.h" -static const int kC1 = 20091 + (1 << 16); -static const int kC2 = 35468; - -#define MUL(a, b) (((a) * (b)) >> 16) +static const int kC1 = WEBP_TRANSFORM_AC3_C1; +static const int kC2 = WEBP_TRANSFORM_AC3_C2; static void TransformDC(const int16_t* in, uint8_t* dst) { int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9, temp10; @@ -49,10 +47,10 @@ static void TransformDC(const int16_t* in, uint8_t* dst) { static void TransformAC3(const int16_t* in, uint8_t* dst) { const int a = in[0] + 4; - int c4 = MUL(in[4], kC2); - const int d4 = MUL(in[4], kC1); - const int c1 = MUL(in[1], kC2); - const int d1 = MUL(in[1], kC1); + int c4 = WEBP_TRANSFORM_AC3_MUL2(in[4]); + const int d4 = WEBP_TRANSFORM_AC3_MUL1(in[4]); + const int c1 = WEBP_TRANSFORM_AC3_MUL2(in[1]); + const int d1 = WEBP_TRANSFORM_AC3_MUL1(in[1]); int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9; int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18; @@ -479,8 +477,6 @@ static void HFilter8i(uint8_t* u, uint8_t* v, int stride, FilterLoop24(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh); } -#undef MUL - //------------------------------------------------------------------------------ // Simple In-loop filtering (Paragraph 15.2) diff --git a/3rdparty/libwebp/src/dsp/dec_msa.c b/3rdparty/libwebp/src/dsp/dec_msa.c index 8090622b7b..58d1730192 100644 --- a/3rdparty/libwebp/src/dsp/dec_msa.c +++ b/3rdparty/libwebp/src/dsp/dec_msa.c @@ -37,8 +37,6 @@ d1_m = d_tmp1_m + d_tmp2_m; \ BUTTERFLY_4(a1_m, b1_m, c1_m, d1_m, out0, out1, out2, out3); \ } -#define MULT1(a) ((((a) * 20091) >> 16) + (a)) -#define MULT2(a) (((a) * 35468) >> 16) static void TransformOne(const int16_t* in, uint8_t* dst) { v8i16 input0, input1; @@ -124,10 +122,10 @@ static void TransformDC(const int16_t* in, uint8_t* dst) { static void TransformAC3(const int16_t* in, uint8_t* dst) { const int a = in[0] + 4; - const int c4 = MULT2(in[4]); - const int d4 = MULT1(in[4]); - const int in2 = MULT2(in[1]); - const int in3 = MULT1(in[1]); + const int c4 = WEBP_TRANSFORM_AC3_MUL2(in[4]); + const int d4 = WEBP_TRANSFORM_AC3_MUL1(in[4]); + const int in2 = WEBP_TRANSFORM_AC3_MUL2(in[1]); + const int in3 = WEBP_TRANSFORM_AC3_MUL1(in[1]); v4i32 tmp0 = { 0 }; v4i32 out0 = __msa_fill_w(a + d4); v4i32 out1 = __msa_fill_w(a + c4); diff --git a/3rdparty/libwebp/src/dsp/dec_neon.c b/3rdparty/libwebp/src/dsp/dec_neon.c index 22784cf15a..83b3a1f970 100644 --- a/3rdparty/libwebp/src/dsp/dec_neon.c +++ b/3rdparty/libwebp/src/dsp/dec_neon.c @@ -1000,8 +1000,9 @@ static void HFilter8i_NEON(uint8_t* u, uint8_t* v, int stride, // libwebp adds 1 << 16 to cospi8sqrt2minus1 (kC1). However, this causes the // same issue with kC1 and vqdmulh that we work around by down shifting kC2 -static const int16_t kC1 = 20091; -static const int16_t kC2 = 17734; // half of kC2, actually. See comment above. +static const int16_t kC1 = WEBP_TRANSFORM_AC3_C1; +static const int16_t kC2 = + WEBP_TRANSFORM_AC3_C2 / 2; // half of kC2, actually. See comment above. #if defined(WEBP_USE_INTRINSICS) static WEBP_INLINE void Transpose8x2_NEON(const int16x8_t in0, @@ -1255,15 +1256,12 @@ static void TransformWHT_NEON(const int16_t* in, int16_t* out) { //------------------------------------------------------------------------------ -#define MUL(a, b) (((a) * (b)) >> 16) static void TransformAC3_NEON(const int16_t* in, uint8_t* dst) { - static const int kC1_full = 20091 + (1 << 16); - static const int kC2_full = 35468; const int16x4_t A = vld1_dup_s16(in); - const int16x4_t c4 = vdup_n_s16(MUL(in[4], kC2_full)); - const int16x4_t d4 = vdup_n_s16(MUL(in[4], kC1_full)); - const int c1 = MUL(in[1], kC2_full); - const int d1 = MUL(in[1], kC1_full); + const int16x4_t c4 = vdup_n_s16(WEBP_TRANSFORM_AC3_MUL2(in[4])); + const int16x4_t d4 = vdup_n_s16(WEBP_TRANSFORM_AC3_MUL1(in[4])); + const int c1 = WEBP_TRANSFORM_AC3_MUL2(in[1]); + const int d1 = WEBP_TRANSFORM_AC3_MUL1(in[1]); const uint64_t cd = (uint64_t)( d1 & 0xffff) << 0 | (uint64_t)( c1 & 0xffff) << 16 | (uint64_t)(-c1 & 0xffff) << 32 | @@ -1274,7 +1272,6 @@ static void TransformAC3_NEON(const int16_t* in, uint8_t* dst) { const int16x8_t m2_m3 = vcombine_s16(vqsub_s16(B, c4), vqsub_s16(B, d4)); Add4x4_NEON(m0_m1, m2_m3, dst); } -#undef MUL //------------------------------------------------------------------------------ // 4x4 diff --git a/3rdparty/libwebp/src/dsp/dec_sse2.c b/3rdparty/libwebp/src/dsp/dec_sse2.c index 01e6bcb636..ff3a28555b 100644 --- a/3rdparty/libwebp/src/dsp/dec_sse2.c +++ b/3rdparty/libwebp/src/dsp/dec_sse2.c @@ -196,15 +196,13 @@ static void Transform_SSE2(const int16_t* in, uint8_t* dst, int do_two) { } #if (USE_TRANSFORM_AC3 == 1) -#define MUL(a, b) (((a) * (b)) >> 16) + static void TransformAC3(const int16_t* in, uint8_t* dst) { - static const int kC1 = 20091 + (1 << 16); - static const int kC2 = 35468; const __m128i A = _mm_set1_epi16(in[0] + 4); - const __m128i c4 = _mm_set1_epi16(MUL(in[4], kC2)); - const __m128i d4 = _mm_set1_epi16(MUL(in[4], kC1)); - const int c1 = MUL(in[1], kC2); - const int d1 = MUL(in[1], kC1); + const __m128i c4 = _mm_set1_epi16(WEBP_TRANSFORM_AC3_MUL2(in[4])); + const __m128i d4 = _mm_set1_epi16(WEBP_TRANSFORM_AC3_MUL1(in[4])); + const int c1 = WEBP_TRANSFORM_AC3_MUL2(in[1]); + const int d1 = WEBP_TRANSFORM_AC3_MUL1(in[1]); const __m128i CD = _mm_set_epi16(0, 0, 0, 0, -d1, -c1, c1, d1); const __m128i B = _mm_adds_epi16(A, CD); const __m128i m0 = _mm_adds_epi16(B, d4); @@ -238,7 +236,7 @@ static void TransformAC3(const int16_t* in, uint8_t* dst) { WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(dst2)); WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(dst3)); } -#undef MUL + #endif // USE_TRANSFORM_AC3 //------------------------------------------------------------------------------ @@ -259,15 +257,15 @@ static WEBP_INLINE void SignedShift8b_SSE2(__m128i* const x) { *x = _mm_packs_epi16(lo_1, hi_1); } -#define FLIP_SIGN_BIT2(a, b) { \ +#define FLIP_SIGN_BIT2(a, b) do { \ (a) = _mm_xor_si128(a, sign_bit); \ (b) = _mm_xor_si128(b, sign_bit); \ -} +} while (0) -#define FLIP_SIGN_BIT4(a, b, c, d) { \ +#define FLIP_SIGN_BIT4(a, b, c, d) do { \ FLIP_SIGN_BIT2(a, b); \ FLIP_SIGN_BIT2(c, d); \ -} +} while (0) // input/output is uint8_t static WEBP_INLINE void GetNotHEV_SSE2(const __m128i* const p1, @@ -645,12 +643,12 @@ static void SimpleHFilter16i_SSE2(uint8_t* p, int stride, int thresh) { (m) = _mm_max_epu8(m, MM_ABS(p2, p1)); \ } while (0) -#define LOAD_H_EDGES4(p, stride, e1, e2, e3, e4) { \ +#define LOAD_H_EDGES4(p, stride, e1, e2, e3, e4) do { \ (e1) = _mm_loadu_si128((__m128i*)&(p)[0 * (stride)]); \ (e2) = _mm_loadu_si128((__m128i*)&(p)[1 * (stride)]); \ (e3) = _mm_loadu_si128((__m128i*)&(p)[2 * (stride)]); \ (e4) = _mm_loadu_si128((__m128i*)&(p)[3 * (stride)]); \ -} +} while (0) #define LOADUV_H_EDGE(p, u, v, stride) do { \ const __m128i U = _mm_loadl_epi64((__m128i*)&(u)[(stride)]); \ @@ -658,18 +656,18 @@ static void SimpleHFilter16i_SSE2(uint8_t* p, int stride, int thresh) { (p) = _mm_unpacklo_epi64(U, V); \ } while (0) -#define LOADUV_H_EDGES4(u, v, stride, e1, e2, e3, e4) { \ +#define LOADUV_H_EDGES4(u, v, stride, e1, e2, e3, e4) do { \ LOADUV_H_EDGE(e1, u, v, 0 * (stride)); \ LOADUV_H_EDGE(e2, u, v, 1 * (stride)); \ LOADUV_H_EDGE(e3, u, v, 2 * (stride)); \ LOADUV_H_EDGE(e4, u, v, 3 * (stride)); \ -} +} while (0) -#define STOREUV(p, u, v, stride) { \ +#define STOREUV(p, u, v, stride) do { \ _mm_storel_epi64((__m128i*)&(u)[(stride)], p); \ (p) = _mm_srli_si128(p, 8); \ _mm_storel_epi64((__m128i*)&(v)[(stride)], p); \ -} +} while (0) static WEBP_INLINE void ComplexMask_SSE2(const __m128i* const p1, const __m128i* const p0, diff --git a/3rdparty/libwebp/src/dsp/dsp.h b/3rdparty/libwebp/src/dsp/dsp.h index d2000b8efc..23bc296514 100644 --- a/3rdparty/libwebp/src/dsp/dsp.h +++ b/3rdparty/libwebp/src/dsp/dsp.h @@ -203,6 +203,11 @@ extern VP8DecIdct VP8TransformDC; extern VP8DecIdct VP8TransformDCUV; extern VP8WHT VP8TransformWHT; +#define WEBP_TRANSFORM_AC3_C1 20091 +#define WEBP_TRANSFORM_AC3_C2 35468 +#define WEBP_TRANSFORM_AC3_MUL1(a) ((((a) * WEBP_TRANSFORM_AC3_C1) >> 16) + (a)) +#define WEBP_TRANSFORM_AC3_MUL2(a) (((a) * WEBP_TRANSFORM_AC3_C2) >> 16) + // *dst is the destination block, with stride BPS. Boundary samples are // assumed accessible when needed. typedef void (*VP8PredFunc)(uint8_t* dst); diff --git a/3rdparty/libwebp/src/dsp/enc.c b/3rdparty/libwebp/src/dsp/enc.c index 2ba97ba8d6..395ad05b0b 100644 --- a/3rdparty/libwebp/src/dsp/enc.c +++ b/3rdparty/libwebp/src/dsp/enc.c @@ -109,10 +109,6 @@ static WEBP_TSAN_IGNORE_FUNCTION void InitTables(void) { #define STORE(x, y, v) \ dst[(x) + (y) * BPS] = clip_8b(ref[(x) + (y) * BPS] + ((v) >> 3)) -static const int kC1 = 20091 + (1 << 16); -static const int kC2 = 35468; -#define MUL(a, b) (((a) * (b)) >> 16) - static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in, uint8_t* dst) { int C[4 * 4], *tmp; @@ -121,8 +117,10 @@ static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in, for (i = 0; i < 4; ++i) { // vertical pass const int a = in[0] + in[8]; const int b = in[0] - in[8]; - const int c = MUL(in[4], kC2) - MUL(in[12], kC1); - const int d = MUL(in[4], kC1) + MUL(in[12], kC2); + const int c = + WEBP_TRANSFORM_AC3_MUL2(in[4]) - WEBP_TRANSFORM_AC3_MUL1(in[12]); + const int d = + WEBP_TRANSFORM_AC3_MUL1(in[4]) + WEBP_TRANSFORM_AC3_MUL2(in[12]); tmp[0] = a + d; tmp[1] = b + c; tmp[2] = b - c; @@ -134,10 +132,12 @@ static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in, tmp = C; for (i = 0; i < 4; ++i) { // horizontal pass const int dc = tmp[0] + 4; - const int a = dc + tmp[8]; - const int b = dc - tmp[8]; - const int c = MUL(tmp[4], kC2) - MUL(tmp[12], kC1); - const int d = MUL(tmp[4], kC1) + MUL(tmp[12], kC2); + const int a = dc + tmp[8]; + const int b = dc - tmp[8]; + const int c = + WEBP_TRANSFORM_AC3_MUL2(tmp[4]) - WEBP_TRANSFORM_AC3_MUL1(tmp[12]); + const int d = + WEBP_TRANSFORM_AC3_MUL1(tmp[4]) + WEBP_TRANSFORM_AC3_MUL2(tmp[12]); STORE(0, i, a + d); STORE(1, i, b + c); STORE(2, i, b - c); @@ -222,7 +222,6 @@ static void FTransformWHT_C(const int16_t* in, int16_t* out) { } #endif // !WEBP_NEON_OMIT_C_CODE -#undef MUL #undef STORE //------------------------------------------------------------------------------ diff --git a/3rdparty/libwebp/src/dsp/enc_mips32.c b/3rdparty/libwebp/src/dsp/enc_mips32.c index 618f0fc0ee..50518a5f1a 100644 --- a/3rdparty/libwebp/src/dsp/enc_mips32.c +++ b/3rdparty/libwebp/src/dsp/enc_mips32.c @@ -21,8 +21,8 @@ #include "src/enc/vp8i_enc.h" #include "src/enc/cost_enc.h" -static const int kC1 = 20091 + (1 << 16); -static const int kC2 = 35468; +static const int kC1 = WEBP_TRANSFORM_AC3_C1; +static const int kC2 = WEBP_TRANSFORM_AC3_C2; // macro for one vertical pass in ITransformOne // MUL macro inlined @@ -30,7 +30,7 @@ static const int kC2 = 35468; // A..D - offsets in bytes to load from in buffer // TEMP0..TEMP3 - registers for corresponding tmp elements // TEMP4..TEMP5 - temporary registers -#define VERTICAL_PASS(A, B, C, D, TEMP4, TEMP0, TEMP1, TEMP2, TEMP3) \ +#define VERTICAL_PASS(A, B, C, D, TEMP4, TEMP0, TEMP1, TEMP2, TEMP3) \ "lh %[temp16], " #A "(%[temp20]) \n\t" \ "lh %[temp18], " #B "(%[temp20]) \n\t" \ "lh %[temp17], " #C "(%[temp20]) \n\t" \ @@ -38,12 +38,10 @@ static const int kC2 = 35468; "addu %[" #TEMP4 "], %[temp16], %[temp18] \n\t" \ "subu %[temp16], %[temp16], %[temp18] \n\t" \ "mul %[" #TEMP0 "], %[temp17], %[kC2] \n\t" \ - "mul %[temp18], %[temp19], %[kC1] \n\t" \ - "mul %[temp17], %[temp17], %[kC1] \n\t" \ + MUL_SHIFT_C1_IO(temp17, temp18) \ + MUL_SHIFT_C1(temp18, temp19) \ "mul %[temp19], %[temp19], %[kC2] \n\t" \ "sra %[" #TEMP0 "], %[" #TEMP0 "], 16 \n\n" \ - "sra %[temp18], %[temp18], 16 \n\n" \ - "sra %[temp17], %[temp17], 16 \n\n" \ "sra %[temp19], %[temp19], 16 \n\n" \ "subu %[" #TEMP2 "], %[" #TEMP0 "], %[temp18] \n\t" \ "addu %[" #TEMP3 "], %[temp17], %[temp19] \n\t" \ @@ -58,17 +56,15 @@ static const int kC2 = 35468; // temp0..temp15 holds tmp[0]..tmp[15] // A - offset in bytes to load from ref and store to dst buffer // TEMP0, TEMP4, TEMP8 and TEMP12 - registers for corresponding tmp elements -#define HORIZONTAL_PASS(A, TEMP0, TEMP4, TEMP8, TEMP12) \ +#define HORIZONTAL_PASS(A, TEMP0, TEMP4, TEMP8, TEMP12) \ "addiu %[" #TEMP0 "], %[" #TEMP0 "], 4 \n\t" \ "addu %[temp16], %[" #TEMP0 "], %[" #TEMP8 "] \n\t" \ "subu %[temp17], %[" #TEMP0 "], %[" #TEMP8 "] \n\t" \ "mul %[" #TEMP0 "], %[" #TEMP4 "], %[kC2] \n\t" \ - "mul %[" #TEMP8 "], %[" #TEMP12 "], %[kC1] \n\t" \ - "mul %[" #TEMP4 "], %[" #TEMP4 "], %[kC1] \n\t" \ + MUL_SHIFT_C1_IO(TEMP4, TEMP8) \ + MUL_SHIFT_C1(TEMP8, TEMP12) \ "mul %[" #TEMP12 "], %[" #TEMP12 "], %[kC2] \n\t" \ "sra %[" #TEMP0 "], %[" #TEMP0 "], 16 \n\t" \ - "sra %[" #TEMP8 "], %[" #TEMP8 "], 16 \n\t" \ - "sra %[" #TEMP4 "], %[" #TEMP4 "], 16 \n\t" \ "sra %[" #TEMP12 "], %[" #TEMP12 "], 16 \n\t" \ "subu %[temp18], %[" #TEMP0 "], %[" #TEMP8 "] \n\t" \ "addu %[temp19], %[" #TEMP4 "], %[" #TEMP12 "] \n\t" \ diff --git a/3rdparty/libwebp/src/dsp/enc_mips_dsp_r2.c b/3rdparty/libwebp/src/dsp/enc_mips_dsp_r2.c index 9ddd895086..e1431f3bef 100644 --- a/3rdparty/libwebp/src/dsp/enc_mips_dsp_r2.c +++ b/3rdparty/libwebp/src/dsp/enc_mips_dsp_r2.c @@ -20,8 +20,8 @@ #include "src/enc/cost_enc.h" #include "src/enc/vp8i_enc.h" -static const int kC1 = 20091 + (1 << 16); -static const int kC2 = 35468; +static const int kC1 = WEBP_TRANSFORM_AC3_C1; +static const int kC2 = WEBP_TRANSFORM_AC3_C2; // O - output // I - input (macro doesn't change it) diff --git a/3rdparty/libwebp/src/dsp/enc_neon.c b/3rdparty/libwebp/src/dsp/enc_neon.c index 714800367b..6f641c9a76 100644 --- a/3rdparty/libwebp/src/dsp/enc_neon.c +++ b/3rdparty/libwebp/src/dsp/enc_neon.c @@ -27,8 +27,9 @@ // This code is pretty much the same as TransformOne in the dec_neon.c, except // for subtraction to *ref. See the comments there for algorithmic explanations. -static const int16_t kC1 = 20091; -static const int16_t kC2 = 17734; // half of kC2, actually. See comment above. +static const int16_t kC1 = WEBP_TRANSFORM_AC3_C1; +static const int16_t kC2 = + WEBP_TRANSFORM_AC3_C2 / 2; // half of kC2, actually. See comment above. // This code works but is *slower* than the inlined-asm version below // (with gcc-4.6). So we disable it for now. Later, it'll be conditional to diff --git a/3rdparty/libwebp/src/dsp/filters.c b/3rdparty/libwebp/src/dsp/filters.c index c1350d5c9d..c9232ff16a 100644 --- a/3rdparty/libwebp/src/dsp/filters.c +++ b/3rdparty/libwebp/src/dsp/filters.c @@ -19,14 +19,16 @@ //------------------------------------------------------------------------------ // Helpful macro. -# define SANITY_CHECK(in, out) \ - assert((in) != NULL); \ - assert((out) != NULL); \ - assert(width > 0); \ - assert(height > 0); \ - assert(stride >= width); \ - assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ - (void)height; // Silence unused warning. +#define DCHECK(in, out) \ + do { \ + assert((in) != NULL); \ + assert((out) != NULL); \ + assert(width > 0); \ + assert(height > 0); \ + assert(stride >= width); \ + assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ + (void)height; /* Silence unused warning. */ \ + } while (0) #if !WEBP_NEON_OMIT_C_CODE static WEBP_INLINE void PredictLine_C(const uint8_t* src, const uint8_t* pred, @@ -49,7 +51,7 @@ static WEBP_INLINE void DoHorizontalFilter_C(const uint8_t* in, const uint8_t* preds; const size_t start_offset = row * stride; const int last_row = row + num_rows; - SANITY_CHECK(in, out); + DCHECK(in, out); in += start_offset; out += start_offset; preds = inverse ? out : in; @@ -86,7 +88,7 @@ static WEBP_INLINE void DoVerticalFilter_C(const uint8_t* in, const uint8_t* preds; const size_t start_offset = row * stride; const int last_row = row + num_rows; - SANITY_CHECK(in, out); + DCHECK(in, out); in += start_offset; out += start_offset; preds = inverse ? out : in; @@ -131,7 +133,7 @@ static WEBP_INLINE void DoGradientFilter_C(const uint8_t* in, const uint8_t* preds; const size_t start_offset = row * stride; const int last_row = row + num_rows; - SANITY_CHECK(in, out); + DCHECK(in, out); in += start_offset; out += start_offset; preds = inverse ? out : in; @@ -165,7 +167,7 @@ static WEBP_INLINE void DoGradientFilter_C(const uint8_t* in, } #endif // !WEBP_NEON_OMIT_C_CODE -#undef SANITY_CHECK +#undef DCHECK //------------------------------------------------------------------------------ diff --git a/3rdparty/libwebp/src/dsp/filters_mips_dsp_r2.c b/3rdparty/libwebp/src/dsp/filters_mips_dsp_r2.c index 9382b12823..eca866f578 100644 --- a/3rdparty/libwebp/src/dsp/filters_mips_dsp_r2.c +++ b/3rdparty/libwebp/src/dsp/filters_mips_dsp_r2.c @@ -24,14 +24,16 @@ //------------------------------------------------------------------------------ // Helpful macro. -# define SANITY_CHECK(in, out) \ - assert(in != NULL); \ - assert(out != NULL); \ - assert(width > 0); \ - assert(height > 0); \ - assert(stride >= width); \ - assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ - (void)height; // Silence unused warning. +#define DCHECK(in, out) \ + do { \ + assert(in != NULL); \ + assert(out != NULL); \ + assert(width > 0); \ + assert(height > 0); \ + assert(stride >= width); \ + assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ + (void)height; /* Silence unused warning. */ \ + } while (0) #define DO_PREDICT_LINE(SRC, DST, LENGTH, INVERSE) do { \ const uint8_t* psrc = (uint8_t*)(SRC); \ @@ -200,7 +202,7 @@ static WEBP_INLINE void DoHorizontalFilter_MIPSdspR2(const uint8_t* in, const uint8_t* preds; const size_t start_offset = row * stride; const int last_row = row + num_rows; - SANITY_CHECK(in, out); + DCHECK(in, out); in += start_offset; out += start_offset; preds = in; @@ -248,7 +250,7 @@ static WEBP_INLINE void DoVerticalFilter_MIPSdspR2(const uint8_t* in, const uint8_t* preds; const size_t start_offset = row * stride; const int last_row = row + num_rows; - SANITY_CHECK(in, out); + DCHECK(in, out); in += start_offset; out += start_offset; preds = in; @@ -316,7 +318,7 @@ static void DoGradientFilter_MIPSdspR2(const uint8_t* in, const uint8_t* preds; const size_t start_offset = row * stride; const int last_row = row + num_rows; - SANITY_CHECK(in, out); + DCHECK(in, out); in += start_offset; out += start_offset; preds = in; @@ -378,7 +380,7 @@ static void GradientUnfilter_MIPSdspR2(const uint8_t* prev, const uint8_t* in, #undef DO_PREDICT_LINE_VERTICAL #undef PREDICT_LINE_ONE_PASS #undef DO_PREDICT_LINE -#undef SANITY_CHECK +#undef DCHECK //------------------------------------------------------------------------------ // Entry point diff --git a/3rdparty/libwebp/src/dsp/filters_msa.c b/3rdparty/libwebp/src/dsp/filters_msa.c index 14c437d141..33a1b20b70 100644 --- a/3rdparty/libwebp/src/dsp/filters_msa.c +++ b/3rdparty/libwebp/src/dsp/filters_msa.c @@ -56,12 +56,14 @@ static WEBP_INLINE void PredictLineInverse0(const uint8_t* src, //------------------------------------------------------------------------------ // Helpful macro. -#define SANITY_CHECK(in, out) \ - assert(in != NULL); \ - assert(out != NULL); \ - assert(width > 0); \ - assert(height > 0); \ - assert(stride >= width); +#define DCHECK(in, out) \ + do { \ + assert(in != NULL); \ + assert(out != NULL); \ + assert(width > 0); \ + assert(height > 0); \ + assert(stride >= width); \ + } while (0) //------------------------------------------------------------------------------ // Horrizontal filter @@ -72,7 +74,7 @@ static void HorizontalFilter_MSA(const uint8_t* data, int width, int height, const uint8_t* in = data; uint8_t* out = filtered_data; int row = 1; - SANITY_CHECK(in, out); + DCHECK(in, out); // Leftmost pixel is the same as input for topmost scanline. out[0] = in[0]; @@ -135,7 +137,7 @@ static void GradientFilter_MSA(const uint8_t* data, int width, int height, const uint8_t* preds = data; uint8_t* out = filtered_data; int row = 1; - SANITY_CHECK(in, out); + DCHECK(in, out); // left prediction for top scan-line out[0] = in[0]; @@ -163,7 +165,7 @@ static void VerticalFilter_MSA(const uint8_t* data, int width, int height, const uint8_t* preds = data; uint8_t* out = filtered_data; int row = 1; - SANITY_CHECK(in, out); + DCHECK(in, out); // Very first top-left pixel is copied. out[0] = in[0]; @@ -182,7 +184,7 @@ static void VerticalFilter_MSA(const uint8_t* data, int width, int height, } } -#undef SANITY_CHECK +#undef DCHECK //------------------------------------------------------------------------------ // Entry point diff --git a/3rdparty/libwebp/src/dsp/filters_neon.c b/3rdparty/libwebp/src/dsp/filters_neon.c index 3e6a578ea7..b49e515af1 100644 --- a/3rdparty/libwebp/src/dsp/filters_neon.c +++ b/3rdparty/libwebp/src/dsp/filters_neon.c @@ -21,14 +21,16 @@ //------------------------------------------------------------------------------ // Helpful macros. -# define SANITY_CHECK(in, out) \ - assert(in != NULL); \ - assert(out != NULL); \ - assert(width > 0); \ - assert(height > 0); \ - assert(stride >= width); \ - assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ - (void)height; // Silence unused warning. +#define DCHECK(in, out) \ + do { \ + assert(in != NULL); \ + assert(out != NULL); \ + assert(width > 0); \ + assert(height > 0); \ + assert(stride >= width); \ + assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ + (void)height; /* Silence unused warning. */ \ + } while (0) // load eight u8 and widen to s16 #define U8_TO_S16(A) vreinterpretq_s16_u16(vmovl_u8(A)) @@ -71,7 +73,7 @@ static WEBP_INLINE void DoHorizontalFilter_NEON(const uint8_t* in, uint8_t* out) { const size_t start_offset = row * stride; const int last_row = row + num_rows; - SANITY_CHECK(in, out); + DCHECK(in, out); in += start_offset; out += start_offset; @@ -110,7 +112,7 @@ static WEBP_INLINE void DoVerticalFilter_NEON(const uint8_t* in, uint8_t* out) { const size_t start_offset = row * stride; const int last_row = row + num_rows; - SANITY_CHECK(in, out); + DCHECK(in, out); in += start_offset; out += start_offset; @@ -172,7 +174,7 @@ static WEBP_INLINE void DoGradientFilter_NEON(const uint8_t* in, uint8_t* out) { const size_t start_offset = row * stride; const int last_row = row + num_rows; - SANITY_CHECK(in, out); + DCHECK(in, out); in += start_offset; out += start_offset; @@ -201,7 +203,7 @@ static void GradientFilter_NEON(const uint8_t* data, int width, int height, filtered_data); } -#undef SANITY_CHECK +#undef DCHECK //------------------------------------------------------------------------------ // Inverse transforms diff --git a/3rdparty/libwebp/src/dsp/filters_sse2.c b/3rdparty/libwebp/src/dsp/filters_sse2.c index 5c33ec15e2..bb4b5d5874 100644 --- a/3rdparty/libwebp/src/dsp/filters_sse2.c +++ b/3rdparty/libwebp/src/dsp/filters_sse2.c @@ -23,14 +23,16 @@ //------------------------------------------------------------------------------ // Helpful macro. -# define SANITY_CHECK(in, out) \ - assert((in) != NULL); \ - assert((out) != NULL); \ - assert(width > 0); \ - assert(height > 0); \ - assert(stride >= width); \ - assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ - (void)height; // Silence unused warning. +#define DCHECK(in, out) \ + do { \ + assert((in) != NULL); \ + assert((out) != NULL); \ + assert(width > 0); \ + assert(height > 0); \ + assert(stride >= width); \ + assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ + (void)height; /* Silence unused warning. */ \ + } while (0) static void PredictLineTop_SSE2(const uint8_t* src, const uint8_t* pred, uint8_t* dst, int length) { @@ -78,7 +80,7 @@ static WEBP_INLINE void DoHorizontalFilter_SSE2(const uint8_t* in, uint8_t* out) { const size_t start_offset = row * stride; const int last_row = row + num_rows; - SANITY_CHECK(in, out); + DCHECK(in, out); in += start_offset; out += start_offset; @@ -111,7 +113,7 @@ static WEBP_INLINE void DoVerticalFilter_SSE2(const uint8_t* in, uint8_t* out) { const size_t start_offset = row * stride; const int last_row = row + num_rows; - SANITY_CHECK(in, out); + DCHECK(in, out); in += start_offset; out += start_offset; @@ -174,7 +176,7 @@ static WEBP_INLINE void DoGradientFilter_SSE2(const uint8_t* in, uint8_t* out) { const size_t start_offset = row * stride; const int last_row = row + num_rows; - SANITY_CHECK(in, out); + DCHECK(in, out); in += start_offset; out += start_offset; @@ -197,7 +199,7 @@ static WEBP_INLINE void DoGradientFilter_SSE2(const uint8_t* in, } } -#undef SANITY_CHECK +#undef DCHECK //------------------------------------------------------------------------------ diff --git a/3rdparty/libwebp/src/dsp/lossless_neon.c b/3rdparty/libwebp/src/dsp/lossless_neon.c index ddc9b61711..e9960db38a 100644 --- a/3rdparty/libwebp/src/dsp/lossless_neon.c +++ b/3rdparty/libwebp/src/dsp/lossless_neon.c @@ -146,9 +146,9 @@ static void ConvertBGRAToRGB_NEON(const uint32_t* src, #define LOAD_U32P_AS_U8(IN) vreinterpret_u8_u32(vld1_u32((IN))) #define LOADQ_U32_AS_U8(IN) vreinterpretq_u8_u32(vdupq_n_u32((IN))) #define LOADQ_U32P_AS_U8(IN) vreinterpretq_u8_u32(vld1q_u32((IN))) -#define GET_U8_AS_U32(IN) vget_lane_u32(vreinterpret_u32_u8((IN)), 0); -#define GETQ_U8_AS_U32(IN) vgetq_lane_u32(vreinterpretq_u32_u8((IN)), 0); -#define STOREQ_U8_AS_U32P(OUT, IN) vst1q_u32((OUT), vreinterpretq_u32_u8((IN))); +#define GET_U8_AS_U32(IN) vget_lane_u32(vreinterpret_u32_u8((IN)), 0) +#define GETQ_U8_AS_U32(IN) vgetq_lane_u32(vreinterpretq_u32_u8((IN)), 0) +#define STOREQ_U8_AS_U32P(OUT, IN) vst1q_u32((OUT), vreinterpretq_u32_u8((IN))) #define ROTATE32_LEFT(L) vextq_u8((L), (L), 12) // D|C|B|A -> C|B|A|D static WEBP_INLINE uint8x8_t Average2_u8_NEON(uint32_t a0, uint32_t a1) { diff --git a/3rdparty/libwebp/src/dsp/mips_macro.h b/3rdparty/libwebp/src/dsp/mips_macro.h index 44aba9b71d..e810d3d382 100644 --- a/3rdparty/libwebp/src/dsp/mips_macro.h +++ b/3rdparty/libwebp/src/dsp/mips_macro.h @@ -45,28 +45,38 @@ "ulw %[" #O2 "], " #I3 "+" XSTR(I9) "*" #I7 "(%[" #I0 "]) \n\t" \ "ulw %[" #O3 "], " #I4 "+" XSTR(I9) "*" #I8 "(%[" #I0 "]) \n\t" + +// O - output +// I - input (macro doesn't change it so it should be different from I) +#define MUL_SHIFT_C1(O, I) \ + "mul %[" #O "], %[" #I "], %[kC1] \n\t" \ + "sra %[" #O "], %[" #O "], 16 \n\t" \ + "addu %[" #O "], %[" #O "], %[" #I "] \n\t" +#define MUL_SHIFT_C2(O, I) \ + "mul %[" #O "], %[" #I "], %[kC2] \n\t" \ + "sra %[" #O "], %[" #O "], 16 \n\t" + +// Same as #define MUL_SHIFT_C1 but I and O are the same. It stores the +// intermediary result in TMP. +#define MUL_SHIFT_C1_IO(IO, TMP) \ + "mul %[" #TMP "], %[" #IO "], %[kC1] \n\t" \ + "sra %[" #TMP "], %[" #TMP "], 16 \n\t" \ + "addu %[" #IO "], %[" #TMP "], %[" #IO "] \n\t" + // O - output // IO - input/output // I - input (macro doesn't change it) #define MUL_SHIFT_SUM(O0, O1, O2, O3, O4, O5, O6, O7, \ IO0, IO1, IO2, IO3, \ I0, I1, I2, I3, I4, I5, I6, I7) \ - "mul %[" #O0 "], %[" #I0 "], %[kC2] \n\t" \ - "mul %[" #O1 "], %[" #I0 "], %[kC1] \n\t" \ - "mul %[" #O2 "], %[" #I1 "], %[kC2] \n\t" \ - "mul %[" #O3 "], %[" #I1 "], %[kC1] \n\t" \ - "mul %[" #O4 "], %[" #I2 "], %[kC2] \n\t" \ - "mul %[" #O5 "], %[" #I2 "], %[kC1] \n\t" \ - "mul %[" #O6 "], %[" #I3 "], %[kC2] \n\t" \ - "mul %[" #O7 "], %[" #I3 "], %[kC1] \n\t" \ - "sra %[" #O0 "], %[" #O0 "], 16 \n\t" \ - "sra %[" #O1 "], %[" #O1 "], 16 \n\t" \ - "sra %[" #O2 "], %[" #O2 "], 16 \n\t" \ - "sra %[" #O3 "], %[" #O3 "], 16 \n\t" \ - "sra %[" #O4 "], %[" #O4 "], 16 \n\t" \ - "sra %[" #O5 "], %[" #O5 "], 16 \n\t" \ - "sra %[" #O6 "], %[" #O6 "], 16 \n\t" \ - "sra %[" #O7 "], %[" #O7 "], 16 \n\t" \ + MUL_SHIFT_C2(O0, I0) \ + MUL_SHIFT_C1(O1, I0) \ + MUL_SHIFT_C2(O2, I1) \ + MUL_SHIFT_C1(O3, I1) \ + MUL_SHIFT_C2(O4, I2) \ + MUL_SHIFT_C1(O5, I2) \ + MUL_SHIFT_C2(O6, I3) \ + MUL_SHIFT_C1(O7, I3) \ "addu %[" #IO0 "], %[" #IO0 "], %[" #I4 "] \n\t" \ "addu %[" #IO1 "], %[" #IO1 "], %[" #I5 "] \n\t" \ "subu %[" #IO2 "], %[" #IO2 "], %[" #I6 "] \n\t" \ diff --git a/3rdparty/libwebp/src/dsp/rescaler_neon.c b/3rdparty/libwebp/src/dsp/rescaler_neon.c index b976a852cf..957a92dbc9 100644 --- a/3rdparty/libwebp/src/dsp/rescaler_neon.c +++ b/3rdparty/libwebp/src/dsp/rescaler_neon.c @@ -32,7 +32,7 @@ #define STORE_32x8(SRC0, SRC1, DST) do { \ vst1q_u32((DST) + 0, SRC0); \ vst1q_u32((DST) + 4, SRC1); \ -} while (0); +} while (0) #if (WEBP_RESCALER_RFIX == 32) #define MAKE_HALF_CST(C) vdupq_n_s32((int32_t)((C) >> 1)) diff --git a/3rdparty/libwebp/src/dsp/upsampling_sse2.c b/3rdparty/libwebp/src/dsp/upsampling_sse2.c index 08b6d0b1cf..77b4f7221e 100644 --- a/3rdparty/libwebp/src/dsp/upsampling_sse2.c +++ b/3rdparty/libwebp/src/dsp/upsampling_sse2.c @@ -58,7 +58,7 @@ } while (0) // Loads 17 pixels each from rows r1 and r2 and generates 32 pixels. -#define UPSAMPLE_32PIXELS(r1, r2, out) { \ +#define UPSAMPLE_32PIXELS(r1, r2, out) do { \ const __m128i one = _mm_set1_epi8(1); \ const __m128i a = _mm_loadu_si128((const __m128i*)&(r1)[0]); \ const __m128i b = _mm_loadu_si128((const __m128i*)&(r1)[1]); \ @@ -85,7 +85,7 @@ /* pack the alternate pixels */ \ PACK_AND_STORE(a, b, diag1, diag2, (out) + 0); /* store top */ \ PACK_AND_STORE(c, d, diag2, diag1, (out) + 2 * 32); /* store bottom */ \ -} +} while (0) // Turn the macro into a function for reducing code-size when non-critical static void Upsample32Pixels_SSE2(const uint8_t r1[], const uint8_t r2[], @@ -229,11 +229,11 @@ static void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ } \ } -YUV444_FUNC(Yuv444ToRgba_SSE2, VP8YuvToRgba32_SSE2, WebPYuv444ToRgba_C, 4); -YUV444_FUNC(Yuv444ToBgra_SSE2, VP8YuvToBgra32_SSE2, WebPYuv444ToBgra_C, 4); +YUV444_FUNC(Yuv444ToRgba_SSE2, VP8YuvToRgba32_SSE2, WebPYuv444ToRgba_C, 4) +YUV444_FUNC(Yuv444ToBgra_SSE2, VP8YuvToBgra32_SSE2, WebPYuv444ToBgra_C, 4) #if !defined(WEBP_REDUCE_CSP) -YUV444_FUNC(Yuv444ToRgb_SSE2, VP8YuvToRgb32_SSE2, WebPYuv444ToRgb_C, 3); -YUV444_FUNC(Yuv444ToBgr_SSE2, VP8YuvToBgr32_SSE2, WebPYuv444ToBgr_C, 3); +YUV444_FUNC(Yuv444ToRgb_SSE2, VP8YuvToRgb32_SSE2, WebPYuv444ToRgb_C, 3) +YUV444_FUNC(Yuv444ToBgr_SSE2, VP8YuvToBgr32_SSE2, WebPYuv444ToBgr_C, 3) YUV444_FUNC(Yuv444ToArgb_SSE2, VP8YuvToArgb32_SSE2, WebPYuv444ToArgb_C, 4) YUV444_FUNC(Yuv444ToRgba4444_SSE2, VP8YuvToRgba444432_SSE2, \ WebPYuv444ToRgba4444_C, 2) diff --git a/3rdparty/libwebp/src/dsp/upsampling_sse41.c b/3rdparty/libwebp/src/dsp/upsampling_sse41.c index 648d456027..e38c88d5e6 100644 --- a/3rdparty/libwebp/src/dsp/upsampling_sse41.c +++ b/3rdparty/libwebp/src/dsp/upsampling_sse41.c @@ -60,7 +60,7 @@ } while (0) // Loads 17 pixels each from rows r1 and r2 and generates 32 pixels. -#define UPSAMPLE_32PIXELS(r1, r2, out) { \ +#define UPSAMPLE_32PIXELS(r1, r2, out) do { \ const __m128i one = _mm_set1_epi8(1); \ const __m128i a = _mm_loadu_si128((const __m128i*)&(r1)[0]); \ const __m128i b = _mm_loadu_si128((const __m128i*)&(r1)[1]); \ @@ -87,7 +87,7 @@ /* pack the alternate pixels */ \ PACK_AND_STORE(a, b, diag1, diag2, (out) + 0); /* store top */ \ PACK_AND_STORE(c, d, diag2, diag1, (out) + 2 * 32); /* store bottom */ \ -} +} while (0) // Turn the macro into a function for reducing code-size when non-critical static void Upsample32Pixels_SSE41(const uint8_t r1[], const uint8_t r2[], @@ -217,8 +217,8 @@ static void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ } #if !defined(WEBP_REDUCE_CSP) -YUV444_FUNC(Yuv444ToRgb_SSE41, VP8YuvToRgb32_SSE41, WebPYuv444ToRgb_C, 3); -YUV444_FUNC(Yuv444ToBgr_SSE41, VP8YuvToBgr32_SSE41, WebPYuv444ToBgr_C, 3); +YUV444_FUNC(Yuv444ToRgb_SSE41, VP8YuvToRgb32_SSE41, WebPYuv444ToRgb_C, 3) +YUV444_FUNC(Yuv444ToBgr_SSE41, VP8YuvToBgr32_SSE41, WebPYuv444ToBgr_C, 3) #endif // WEBP_REDUCE_CSP WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444ConvertersSSE41(void) { diff --git a/3rdparty/libwebp/src/enc/alpha_enc.c b/3rdparty/libwebp/src/enc/alpha_enc.c index 4a599f88a9..c11a261c8a 100644 --- a/3rdparty/libwebp/src/enc/alpha_enc.c +++ b/3rdparty/libwebp/src/enc/alpha_enc.c @@ -20,6 +20,7 @@ #include "src/utils/filters_utils.h" #include "src/utils/quant_levels_utils.h" #include "src/utils/utils.h" +#include "src/webp/encode.h" #include "src/webp/format_constants.h" // ----------------------------------------------------------------------------- @@ -66,7 +67,7 @@ static int EncodeLossless(const uint8_t* const data, int width, int height, WebPDispatchAlphaToGreen(data, width, picture.width, picture.height, picture.argb, picture.argb_stride); - WebPConfigInit(&config); + if (!WebPConfigInit(&config)) return 0; config.lossless = 1; // Enable exact, or it would alter RGB values of transparent alpha, which is // normally OK but not here since we are not encoding the input image but an @@ -83,11 +84,7 @@ static int EncodeLossless(const uint8_t* const data, int width, int height, (use_quality_100 && effort_level == 6) ? 100 : 8.f * effort_level; assert(config.quality >= 0 && config.quality <= 100.f); - // TODO(urvang): Temporary fix to avoid generating images that trigger - // a decoder bug related to alpha with color cache. - // See: https://code.google.com/p/webp/issues/detail?id=239 - // Need to re-enable this later. - ok = VP8LEncodeStream(&config, &picture, bw, /*use_cache=*/0); + ok = VP8LEncodeStream(&config, &picture, bw); WebPPictureFree(&picture); ok = ok && !bw->error_; if (!ok) { diff --git a/3rdparty/libwebp/src/enc/vp8i_enc.h b/3rdparty/libwebp/src/enc/vp8i_enc.h index 19d9a6edb7..00ff1be795 100644 --- a/3rdparty/libwebp/src/enc/vp8i_enc.h +++ b/3rdparty/libwebp/src/enc/vp8i_enc.h @@ -31,8 +31,8 @@ extern "C" { // version numbers #define ENC_MAJ_VERSION 1 -#define ENC_MIN_VERSION 3 -#define ENC_REV_VERSION 1 +#define ENC_MIN_VERSION 4 +#define ENC_REV_VERSION 0 enum { MAX_LF_LEVELS = 64, // Maximum loop filter level MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost diff --git a/3rdparty/libwebp/src/enc/vp8l_enc.c b/3rdparty/libwebp/src/enc/vp8l_enc.c index c43d990d17..40eafa4169 100644 --- a/3rdparty/libwebp/src/enc/vp8l_enc.c +++ b/3rdparty/libwebp/src/enc/vp8l_enc.c @@ -820,10 +820,10 @@ static int EncodeImageNoHuffman(VP8LBitWriter* const bw, static int EncodeImageInternal( VP8LBitWriter* const bw, const uint32_t* const argb, VP8LHashChain* const hash_chain, VP8LBackwardRefs refs_array[4], int width, - int height, int quality, int low_effort, int use_cache, - const CrunchConfig* const config, int* cache_bits, int histogram_bits, - size_t init_byte_position, int* const hdr_size, int* const data_size, - const WebPPicture* const pic, int percent_range, int* const percent) { + int height, int quality, int low_effort, const CrunchConfig* const config, + int* cache_bits, int histogram_bits, size_t init_byte_position, + int* const hdr_size, int* const data_size, const WebPPicture* const pic, + int percent_range, int* const percent) { const uint32_t histogram_image_xysize = VP8LSubSampleSize(width, histogram_bits) * VP8LSubSampleSize(height, histogram_bits); @@ -871,13 +871,9 @@ static int EncodeImageInternal( percent_start += percent_range; remaining_percent -= percent_range; - if (use_cache) { - // If the value is different from zero, it has been set during the - // palette analysis. - cache_bits_init = (*cache_bits == 0) ? MAX_COLOR_CACHE_BITS : *cache_bits; - } else { - cache_bits_init = 0; - } + // If the value is different from zero, it has been set during the palette + // analysis. + cache_bits_init = (*cache_bits == 0) ? MAX_COLOR_CACHE_BITS : *cache_bits; // If several iterations will happen, clone into bw_best. if ((config->sub_configs_size_ > 1 || config->sub_configs_[0].do_no_cache_) && !VP8LBitWriterClone(bw, &bw_best)) { @@ -1466,7 +1462,6 @@ typedef struct { const WebPPicture* picture_; VP8LBitWriter* bw_; VP8LEncoder* enc_; - int use_cache_; CrunchConfig crunch_configs_[CRUNCH_CONFIGS_MAX]; int num_crunch_configs_; int red_and_blue_always_zero_; @@ -1479,7 +1474,6 @@ static int EncodeStreamHook(void* input, void* data2) { const WebPPicture* const picture = params->picture_; VP8LBitWriter* const bw = params->bw_; VP8LEncoder* const enc = params->enc_; - const int use_cache = params->use_cache_; const CrunchConfig* const crunch_configs = params->crunch_configs_; const int num_crunch_configs = params->num_crunch_configs_; const int red_and_blue_always_zero = params->red_and_blue_always_zero_; @@ -1567,7 +1561,7 @@ static int EncodeStreamHook(void* input, void* data2) { if (!MapImageFromPalette(enc, use_delta_palette)) goto Error; // If using a color cache, do not have it bigger than the number of // colors. - if (use_cache && enc->palette_size_ < (1 << MAX_COLOR_CACHE_BITS)) { + if (enc->palette_size_ < (1 << MAX_COLOR_CACHE_BITS)) { enc->cache_bits_ = BitsLog2Floor(enc->palette_size_) + 1; } } @@ -1611,7 +1605,7 @@ static int EncodeStreamHook(void* input, void* data2) { // Encode and write the transformed image. if (!EncodeImageInternal( bw, enc->argb_, &enc->hash_chain_, enc->refs_, enc->current_width_, - height, quality, low_effort, use_cache, &crunch_configs[idx], + height, quality, low_effort, &crunch_configs[idx], &enc->cache_bits_, enc->histo_bits_, byte_position, &hdr_size, &data_size, picture, remaining_percent, &percent)) { goto Error; @@ -1653,7 +1647,7 @@ static int EncodeStreamHook(void* input, void* data2) { int VP8LEncodeStream(const WebPConfig* const config, const WebPPicture* const picture, - VP8LBitWriter* const bw_main, int use_cache) { + VP8LBitWriter* const bw_main) { VP8LEncoder* const enc_main = VP8LEncoderNew(config, picture); VP8LEncoder* enc_side = NULL; CrunchConfig crunch_configs[CRUNCH_CONFIGS_MAX]; @@ -1675,7 +1669,9 @@ int VP8LEncodeStream(const WebPConfig* const config, } // Avoid "garbage value" error from Clang's static analysis tool. - WebPPictureInit(&picture_side); + if (!WebPPictureInit(&picture_side)) { + goto Error; + } // Analyze image (entropy, num_palettes etc) if (!EncoderAnalyze(enc_main, crunch_configs, &num_crunch_configs_main, @@ -1710,7 +1706,6 @@ int VP8LEncodeStream(const WebPConfig* const config, StreamEncodeContext* const param = (idx == 0) ? ¶ms_main : ¶ms_side; param->config_ = config; - param->use_cache_ = use_cache; param->red_and_blue_always_zero_ = red_and_blue_always_zero; if (idx == 0) { param->picture_ = picture; @@ -1864,7 +1859,7 @@ int VP8LEncodeImage(const WebPConfig* const config, if (!WebPReportProgress(picture, 2, &percent)) goto UserAbort; // Encode main image stream. - if (!VP8LEncodeStream(config, picture, &bw, 1 /*use_cache*/)) goto Error; + if (!VP8LEncodeStream(config, picture, &bw)) goto Error; if (!WebPReportProgress(picture, 99, &percent)) goto UserAbort; diff --git a/3rdparty/libwebp/src/enc/vp8li_enc.h b/3rdparty/libwebp/src/enc/vp8li_enc.h index 3d35e1612d..c5b60dcb39 100644 --- a/3rdparty/libwebp/src/enc/vp8li_enc.h +++ b/3rdparty/libwebp/src/enc/vp8li_enc.h @@ -88,11 +88,9 @@ int VP8LEncodeImage(const WebPConfig* const config, const WebPPicture* const picture); // Encodes the main image stream using the supplied bit writer. -// If 'use_cache' is false, disables the use of color cache. // Returns false in case of error (stored in picture->error_code). int VP8LEncodeStream(const WebPConfig* const config, - const WebPPicture* const picture, VP8LBitWriter* const bw, - int use_cache); + const WebPPicture* const picture, VP8LBitWriter* const bw); #if (WEBP_NEAR_LOSSLESS == 1) // in near_lossless.c diff --git a/3rdparty/libwebp/src/mux/anim_encode.c b/3rdparty/libwebp/src/mux/anim_encode.c index d1c61a2f1e..31bd0457bf 100644 --- a/3rdparty/libwebp/src/mux/anim_encode.c +++ b/3rdparty/libwebp/src/mux/anim_encode.c @@ -22,6 +22,7 @@ #include "src/webp/encode.h" #include "src/webp/format_constants.h" #include "src/webp/mux.h" +#include "src/webp/types.h" #if defined(_MSC_VER) && _MSC_VER < 1900 #define snprintf _snprintf @@ -1398,7 +1399,10 @@ int WebPAnimEncoderAdd(WebPAnimEncoder* enc, WebPPicture* frame, int timestamp, } config = *encoder_config; } else { - WebPConfigInit(&config); + if (!WebPConfigInit(&config)) { + MarkError(enc, "Cannot Init config"); + return 0; + } config.lossless = 1; } assert(enc->curr_canvas_ == NULL); @@ -1419,12 +1423,14 @@ int WebPAnimEncoderAdd(WebPAnimEncoder* enc, WebPPicture* frame, int timestamp, // ----------------------------------------------------------------------------- // Bitstream assembly. -static int DecodeFrameOntoCanvas(const WebPMuxFrameInfo* const frame, - WebPPicture* const canvas) { +WEBP_NODISCARD static int DecodeFrameOntoCanvas( + const WebPMuxFrameInfo* const frame, WebPPicture* const canvas) { const WebPData* const image = &frame->bitstream; WebPPicture sub_image; WebPDecoderConfig config; - WebPInitDecoderConfig(&config); + if (!WebPInitDecoderConfig(&config)) { + return 0; + } WebPUtilClearPic(canvas, NULL); if (WebPGetFeatures(image->bytes, image->size, &config.input) != VP8_STATUS_OK) { @@ -1583,4 +1589,23 @@ const char* WebPAnimEncoderGetError(WebPAnimEncoder* enc) { return enc->error_str_; } +WebPMuxError WebPAnimEncoderSetChunk( + WebPAnimEncoder* enc, const char fourcc[4], const WebPData* chunk_data, + int copy_data) { + if (enc == NULL) return WEBP_MUX_INVALID_ARGUMENT; + return WebPMuxSetChunk(enc->mux_, fourcc, chunk_data, copy_data); +} + +WebPMuxError WebPAnimEncoderGetChunk( + const WebPAnimEncoder* enc, const char fourcc[4], WebPData* chunk_data) { + if (enc == NULL) return WEBP_MUX_INVALID_ARGUMENT; + return WebPMuxGetChunk(enc->mux_, fourcc, chunk_data); +} + +WebPMuxError WebPAnimEncoderDeleteChunk( + WebPAnimEncoder* enc, const char fourcc[4]) { + if (enc == NULL) return WEBP_MUX_INVALID_ARGUMENT; + return WebPMuxDeleteChunk(enc->mux_, fourcc); +} + // ----------------------------------------------------------------------------- diff --git a/3rdparty/libwebp/src/mux/muxedit.c b/3rdparty/libwebp/src/mux/muxedit.c index aab479cc6c..48c6834a4d 100644 --- a/3rdparty/libwebp/src/mux/muxedit.c +++ b/3rdparty/libwebp/src/mux/muxedit.c @@ -66,14 +66,16 @@ void WebPMuxDelete(WebPMux* mux) { // Handy MACRO, makes MuxSet() very symmetric to MuxGet(). #define SWITCH_ID_LIST(INDEX, LIST) \ - if (idx == (INDEX)) { \ - err = ChunkAssignData(&chunk, data, copy_data, tag); \ - if (err == WEBP_MUX_OK) { \ - err = ChunkSetHead(&chunk, (LIST)); \ - if (err != WEBP_MUX_OK) ChunkRelease(&chunk); \ + do { \ + if (idx == (INDEX)) { \ + err = ChunkAssignData(&chunk, data, copy_data, tag); \ + if (err == WEBP_MUX_OK) { \ + err = ChunkSetHead(&chunk, (LIST)); \ + if (err != WEBP_MUX_OK) ChunkRelease(&chunk); \ + } \ + return err; \ } \ - return err; \ - } + } while (0) static WebPMuxError MuxSet(WebPMux* const mux, uint32_t tag, const WebPData* const data, int copy_data) { diff --git a/3rdparty/libwebp/src/mux/muxi.h b/3rdparty/libwebp/src/mux/muxi.h index fc44d6f2fe..74ae3fac12 100644 --- a/3rdparty/libwebp/src/mux/muxi.h +++ b/3rdparty/libwebp/src/mux/muxi.h @@ -28,8 +28,8 @@ extern "C" { // Defines and constants. #define MUX_MAJ_VERSION 1 -#define MUX_MIN_VERSION 3 -#define MUX_REV_VERSION 1 +#define MUX_MIN_VERSION 4 +#define MUX_REV_VERSION 0 // Chunk object. typedef struct WebPChunk WebPChunk; diff --git a/3rdparty/libwebp/src/mux/muxread.c b/3rdparty/libwebp/src/mux/muxread.c index 9862ec68ee..afd3542e12 100644 --- a/3rdparty/libwebp/src/mux/muxread.c +++ b/3rdparty/libwebp/src/mux/muxread.c @@ -21,20 +21,23 @@ // Handy MACRO. #define SWITCH_ID_LIST(INDEX, LIST) \ - if (idx == (INDEX)) { \ - const WebPChunk* const chunk = ChunkSearchList((LIST), nth, \ - kChunks[(INDEX)].tag); \ - if (chunk) { \ - *data = chunk->data_; \ - return WEBP_MUX_OK; \ - } else { \ - return WEBP_MUX_NOT_FOUND; \ + do { \ + if (idx == (INDEX)) { \ + const WebPChunk* const chunk = ChunkSearchList((LIST), nth, \ + kChunks[(INDEX)].tag); \ + if (chunk) { \ + *data = chunk->data_; \ + return WEBP_MUX_OK; \ + } else { \ + return WEBP_MUX_NOT_FOUND; \ + } \ } \ - } + } while (0) static WebPMuxError MuxGet(const WebPMux* const mux, CHUNK_INDEX idx, uint32_t nth, WebPData* const data) { assert(mux != NULL); + assert(idx != IDX_LAST_CHUNK); assert(!IsWPI(kChunks[idx].id)); WebPDataInit(data); @@ -429,6 +432,7 @@ WebPMuxError WebPMuxGetChunk(const WebPMux* mux, const char fourcc[4], return WEBP_MUX_INVALID_ARGUMENT; } idx = ChunkGetIndexFromFourCC(fourcc); + assert(idx != IDX_LAST_CHUNK); if (IsWPI(kChunks[idx].id)) { // An image chunk. return WEBP_MUX_INVALID_ARGUMENT; } else if (idx != IDX_UNKNOWN) { // A known chunk type. diff --git a/3rdparty/libwebp/src/utils/huffman_utils.c b/3rdparty/libwebp/src/utils/huffman_utils.c index cf73abd437..16f9faaa9a 100644 --- a/3rdparty/libwebp/src/utils/huffman_utils.c +++ b/3rdparty/libwebp/src/utils/huffman_utils.c @@ -122,6 +122,9 @@ static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits, const int symbol_code_length = code_lengths[symbol]; if (code_lengths[symbol] > 0) { if (sorted != NULL) { + if(offset[symbol_code_length] >= code_lengths_size) { + return 0; + } sorted[offset[symbol_code_length]++] = symbol; } else { offset[symbol_code_length]++; @@ -267,11 +270,11 @@ int VP8LHuffmanTablesAllocate(int size, HuffmanTables* huffman_tables) { // Have 'segment' point to the first segment for now, 'root'. HuffmanTablesSegment* const root = &huffman_tables->root; huffman_tables->curr_segment = root; + root->next = NULL; // Allocate root. root->start = (HuffmanCode*)WebPSafeMalloc(size, sizeof(*root->start)); if (root->start == NULL) return 0; root->curr_table = root->start; - root->next = NULL; root->size = size; return 1; } diff --git a/3rdparty/libwebp/src/utils/huffman_utils.h b/3rdparty/libwebp/src/utils/huffman_utils.h index 98415c5328..d511dc052c 100644 --- a/3rdparty/libwebp/src/utils/huffman_utils.h +++ b/3rdparty/libwebp/src/utils/huffman_utils.h @@ -63,7 +63,8 @@ typedef struct HuffmanTables { // Allocates a HuffmanTables with 'size' contiguous HuffmanCodes. Returns 0 on // memory allocation error, 1 otherwise. -int VP8LHuffmanTablesAllocate(int size, HuffmanTables* huffman_tables); +WEBP_NODISCARD int VP8LHuffmanTablesAllocate(int size, + HuffmanTables* huffman_tables); void VP8LHuffmanTablesDeallocate(HuffmanTables* const huffman_tables); #define HUFFMAN_PACKED_BITS 6 @@ -91,7 +92,7 @@ struct HTreeGroup { }; // Creates the instance of HTreeGroup with specified number of tree-groups. -HTreeGroup* VP8LHtreeGroupsNew(int num_htree_groups); +WEBP_NODISCARD HTreeGroup* VP8LHtreeGroupsNew(int num_htree_groups); // Releases the memory allocated for HTreeGroup. void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups); @@ -101,8 +102,10 @@ void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups); // the huffman table. // Returns built table size or 0 in case of error (invalid tree or // memory error). -int VP8LBuildHuffmanTable(HuffmanTables* const root_table, int root_bits, - const int code_lengths[], int code_lengths_size); +WEBP_NODISCARD int VP8LBuildHuffmanTable(HuffmanTables* const root_table, + int root_bits, + const int code_lengths[], + int code_lengths_size); #ifdef __cplusplus } // extern "C" diff --git a/3rdparty/libwebp/src/webp/decode.h b/3rdparty/libwebp/src/webp/decode.h index 9d968061d1..d6895f5c55 100644 --- a/3rdparty/libwebp/src/webp/decode.h +++ b/3rdparty/libwebp/src/webp/decode.h @@ -48,34 +48,33 @@ WEBP_EXTERN int WebPGetDecoderVersion(void); // RIFF + VP8X + (optional chunks) + VP8(L) // ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose. // VP8(L) <-- Not a valid WebP format: only allowed for internal purpose. -WEBP_EXTERN int WebPGetInfo(const uint8_t* data, size_t data_size, - int* width, int* height); +WEBP_NODISCARD WEBP_EXTERN int WebPGetInfo( + const uint8_t* data, size_t data_size, int* width, int* height); // Decodes WebP images pointed to by 'data' and returns RGBA samples, along // with the dimensions in *width and *height. The ordering of samples in // memory is R, G, B, A, R, G, B, A... in scan order (endian-independent). // The returned pointer should be deleted calling WebPFree(). // Returns NULL in case of error. -WEBP_EXTERN uint8_t* WebPDecodeRGBA(const uint8_t* data, size_t data_size, - int* width, int* height); +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeRGBA( + const uint8_t* data, size_t data_size, int* width, int* height); // Same as WebPDecodeRGBA, but returning A, R, G, B, A, R, G, B... ordered data. -WEBP_EXTERN uint8_t* WebPDecodeARGB(const uint8_t* data, size_t data_size, - int* width, int* height); +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeARGB( + const uint8_t* data, size_t data_size, int* width, int* height); // Same as WebPDecodeRGBA, but returning B, G, R, A, B, G, R, A... ordered data. -WEBP_EXTERN uint8_t* WebPDecodeBGRA(const uint8_t* data, size_t data_size, - int* width, int* height); +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeBGRA( + const uint8_t* data, size_t data_size, int* width, int* height); // Same as WebPDecodeRGBA, but returning R, G, B, R, G, B... ordered data. // If the bitstream contains transparency, it is ignored. -WEBP_EXTERN uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size, - int* width, int* height); +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeRGB( + const uint8_t* data, size_t data_size, int* width, int* height); // Same as WebPDecodeRGB, but returning B, G, R, B, G, R... ordered data. -WEBP_EXTERN uint8_t* WebPDecodeBGR(const uint8_t* data, size_t data_size, - int* width, int* height); - +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeBGR( + const uint8_t* data, size_t data_size, int* width, int* height); // Decode WebP images pointed to by 'data' to Y'UV format(*). The pointer // returned is the Y samples buffer. Upon return, *u and *v will point to @@ -87,10 +86,9 @@ WEBP_EXTERN uint8_t* WebPDecodeBGR(const uint8_t* data, size_t data_size, // 'width' and 'height' may be NULL, the other pointers must not be. // Returns NULL in case of error. // (*) Also named Y'CbCr. See: https://en.wikipedia.org/wiki/YCbCr -WEBP_EXTERN uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size, - int* width, int* height, - uint8_t** u, uint8_t** v, - int* stride, int* uv_stride); +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeYUV( + const uint8_t* data, size_t data_size, int* width, int* height, + uint8_t** u, uint8_t** v, int* stride, int* uv_stride); // These five functions are variants of the above ones, that decode the image // directly into a pre-allocated buffer 'output_buffer'. The maximum storage @@ -100,22 +98,22 @@ WEBP_EXTERN uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size, // The parameter 'output_stride' specifies the distance (in bytes) // between scanlines. Hence, output_buffer_size is expected to be at least // output_stride x picture-height. -WEBP_EXTERN uint8_t* WebPDecodeRGBAInto( +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeRGBAInto( const uint8_t* data, size_t data_size, uint8_t* output_buffer, size_t output_buffer_size, int output_stride); -WEBP_EXTERN uint8_t* WebPDecodeARGBInto( +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeARGBInto( const uint8_t* data, size_t data_size, uint8_t* output_buffer, size_t output_buffer_size, int output_stride); -WEBP_EXTERN uint8_t* WebPDecodeBGRAInto( +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeBGRAInto( const uint8_t* data, size_t data_size, uint8_t* output_buffer, size_t output_buffer_size, int output_stride); // RGB and BGR variants. Here too the transparency information, if present, // will be dropped and ignored. -WEBP_EXTERN uint8_t* WebPDecodeRGBInto( +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeRGBInto( const uint8_t* data, size_t data_size, uint8_t* output_buffer, size_t output_buffer_size, int output_stride); -WEBP_EXTERN uint8_t* WebPDecodeBGRInto( +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeBGRInto( const uint8_t* data, size_t data_size, uint8_t* output_buffer, size_t output_buffer_size, int output_stride); @@ -126,7 +124,7 @@ WEBP_EXTERN uint8_t* WebPDecodeBGRInto( // 'u_size' and 'v_size' respectively. // Pointer to the luma plane ('*luma') is returned or NULL if an error occurred // during decoding (or because some buffers were found to be too small). -WEBP_EXTERN uint8_t* WebPDecodeYUVInto( +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPDecodeYUVInto( const uint8_t* data, size_t data_size, uint8_t* luma, size_t luma_size, int luma_stride, uint8_t* u, size_t u_size, int u_stride, @@ -217,11 +215,11 @@ struct WebPDecBuffer { }; // Internal, version-checked, entry point -WEBP_EXTERN int WebPInitDecBufferInternal(WebPDecBuffer*, int); +WEBP_NODISCARD WEBP_EXTERN int WebPInitDecBufferInternal(WebPDecBuffer*, int); // Initialize the structure as empty. Must be called before any other use. // Returns false in case of version mismatch -static WEBP_INLINE int WebPInitDecBuffer(WebPDecBuffer* buffer) { +WEBP_NODISCARD static WEBP_INLINE int WebPInitDecBuffer(WebPDecBuffer* buffer) { return WebPInitDecBufferInternal(buffer, WEBP_DECODER_ABI_VERSION); } @@ -232,7 +230,7 @@ WEBP_EXTERN void WebPFreeDecBuffer(WebPDecBuffer* buffer); //------------------------------------------------------------------------------ // Enumeration of the status codes -typedef enum VP8StatusCode { +typedef enum WEBP_NODISCARD VP8StatusCode { VP8_STATUS_OK = 0, VP8_STATUS_OUT_OF_MEMORY, VP8_STATUS_INVALID_PARAM, @@ -282,7 +280,8 @@ typedef enum VP8StatusCode { // within valid bounds. // All other fields of WebPDecBuffer MUST remain constant between calls. // Returns NULL if the allocation failed. -WEBP_EXTERN WebPIDecoder* WebPINewDecoder(WebPDecBuffer* output_buffer); +WEBP_NODISCARD WEBP_EXTERN WebPIDecoder* WebPINewDecoder( + WebPDecBuffer* output_buffer); // This function allocates and initializes an incremental-decoder object, which // will output the RGB/A samples specified by 'csp' into a preallocated @@ -294,7 +293,7 @@ WEBP_EXTERN WebPIDecoder* WebPINewDecoder(WebPDecBuffer* output_buffer); // colorspace 'csp' is taken into account for allocating this buffer. All other // parameters are ignored. // Returns NULL if the allocation failed, or if some parameters are invalid. -WEBP_EXTERN WebPIDecoder* WebPINewRGB( +WEBP_NODISCARD WEBP_EXTERN WebPIDecoder* WebPINewRGB( WEBP_CSP_MODE csp, uint8_t* output_buffer, size_t output_buffer_size, int output_stride); @@ -309,7 +308,7 @@ WEBP_EXTERN WebPIDecoder* WebPINewRGB( // In this case, the output buffer will be automatically allocated (using // MODE_YUVA) when decoding starts. All parameters are then ignored. // Returns NULL if the allocation failed or if a parameter is invalid. -WEBP_EXTERN WebPIDecoder* WebPINewYUVA( +WEBP_NODISCARD WEBP_EXTERN WebPIDecoder* WebPINewYUVA( uint8_t* luma, size_t luma_size, int luma_stride, uint8_t* u, size_t u_size, int u_stride, uint8_t* v, size_t v_size, int v_stride, @@ -317,7 +316,7 @@ WEBP_EXTERN WebPIDecoder* WebPINewYUVA( // Deprecated version of the above, without the alpha plane. // Kept for backward compatibility. -WEBP_EXTERN WebPIDecoder* WebPINewYUV( +WEBP_NODISCARD WEBP_EXTERN WebPIDecoder* WebPINewYUV( uint8_t* luma, size_t luma_size, int luma_stride, uint8_t* u, size_t u_size, int u_stride, uint8_t* v, size_t v_size, int v_stride); @@ -347,21 +346,21 @@ WEBP_EXTERN VP8StatusCode WebPIUpdate( // (*last_y, *width etc.) can be NULL if corresponding information is not // needed. The values in these pointers are only valid on successful (non-NULL) // return. -WEBP_EXTERN uint8_t* WebPIDecGetRGB( +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPIDecGetRGB( const WebPIDecoder* idec, int* last_y, int* width, int* height, int* stride); // Same as above function to get a YUVA image. Returns pointer to the luma // plane or NULL in case of error. If there is no alpha information // the alpha pointer '*a' will be returned NULL. -WEBP_EXTERN uint8_t* WebPIDecGetYUVA( +WEBP_NODISCARD WEBP_EXTERN uint8_t* WebPIDecGetYUVA( const WebPIDecoder* idec, int* last_y, uint8_t** u, uint8_t** v, uint8_t** a, int* width, int* height, int* stride, int* uv_stride, int* a_stride); // Deprecated alpha-less version of WebPIDecGetYUVA(): it will ignore the // alpha information (if present). Kept for backward compatibility. -static WEBP_INLINE uint8_t* WebPIDecGetYUV( +WEBP_NODISCARD static WEBP_INLINE uint8_t* WebPIDecGetYUV( const WebPIDecoder* idec, int* last_y, uint8_t** u, uint8_t** v, int* width, int* height, int* stride, int* uv_stride) { return WebPIDecGetYUVA(idec, last_y, u, v, NULL, width, height, @@ -374,7 +373,7 @@ static WEBP_INLINE uint8_t* WebPIDecGetYUV( // Returns NULL in case the incremental decoder object is in an invalid state. // Otherwise returns the pointer to the internal representation. This structure // is read-only, tied to WebPIDecoder's lifespan and should not be modified. -WEBP_EXTERN const WebPDecBuffer* WebPIDecodedArea( +WEBP_NODISCARD WEBP_EXTERN const WebPDecBuffer* WebPIDecodedArea( const WebPIDecoder* idec, int* left, int* top, int* width, int* height); //------------------------------------------------------------------------------ @@ -469,12 +468,14 @@ struct WebPDecoderConfig { }; // Internal, version-checked, entry point -WEBP_EXTERN int WebPInitDecoderConfigInternal(WebPDecoderConfig*, int); +WEBP_NODISCARD WEBP_EXTERN int WebPInitDecoderConfigInternal(WebPDecoderConfig*, + int); // Initialize the configuration as empty. This function must always be // called first, unless WebPGetFeatures() is to be called. // Returns false in case of mismatched version. -static WEBP_INLINE int WebPInitDecoderConfig(WebPDecoderConfig* config) { +WEBP_NODISCARD static WEBP_INLINE int WebPInitDecoderConfig( + WebPDecoderConfig* config) { return WebPInitDecoderConfigInternal(config, WEBP_DECODER_ABI_VERSION); } @@ -489,8 +490,8 @@ static WEBP_INLINE int WebPInitDecoderConfig(WebPDecoderConfig* config) { // The return WebPIDecoder object must always be deleted calling WebPIDelete(). // Returns NULL in case of error (and config->status will then reflect // the error condition, if available). -WEBP_EXTERN WebPIDecoder* WebPIDecode(const uint8_t* data, size_t data_size, - WebPDecoderConfig* config); +WEBP_NODISCARD WEBP_EXTERN WebPIDecoder* WebPIDecode( + const uint8_t* data, size_t data_size, WebPDecoderConfig* config); // Non-incremental version. This version decodes the full data at once, taking // 'config' into account. Returns decoding status (which should be VP8_STATUS_OK diff --git a/3rdparty/libwebp/src/webp/demux.h b/3rdparty/libwebp/src/webp/demux.h index 846eeb15a9..8d246550ca 100644 --- a/3rdparty/libwebp/src/webp/demux.h +++ b/3rdparty/libwebp/src/webp/demux.h @@ -50,6 +50,7 @@ #include "./decode.h" // for WEBP_CSP_MODE #include "./mux_types.h" +#include "./types.h" #ifdef __cplusplus extern "C" { @@ -85,13 +86,13 @@ typedef enum WebPDemuxState { } WebPDemuxState; // Internal, version-checked, entry point -WEBP_EXTERN WebPDemuxer* WebPDemuxInternal( +WEBP_NODISCARD WEBP_EXTERN WebPDemuxer* WebPDemuxInternal( const WebPData*, int, WebPDemuxState*, int); // Parses the full WebP file given by 'data'. For single images the WebP file // header alone or the file header and the chunk header may be absent. // Returns a WebPDemuxer object on successful parse, NULL otherwise. -static WEBP_INLINE WebPDemuxer* WebPDemux(const WebPData* data) { +WEBP_NODISCARD static WEBP_INLINE WebPDemuxer* WebPDemux(const WebPData* data) { return WebPDemuxInternal(data, 0, NULL, WEBP_DEMUX_ABI_VERSION); } @@ -103,7 +104,7 @@ static WEBP_INLINE WebPDemuxer* WebPDemux(const WebPData* data) { // If this data is volatile, the demuxer object should be deleted (by calling // WebPDemuxDelete()) and WebPDemuxPartial() called again on the new data. // This is usually an inexpensive operation. -static WEBP_INLINE WebPDemuxer* WebPDemuxPartial( +WEBP_NODISCARD static WEBP_INLINE WebPDemuxer* WebPDemuxPartial( const WebPData* data, WebPDemuxState* state) { return WebPDemuxInternal(data, 1, state, WEBP_DEMUX_ABI_VERSION); } @@ -164,14 +165,14 @@ struct WebPIterator { // Returns false if 'dmux' is NULL or frame 'frame_number' is not present. // Call WebPDemuxReleaseIterator() when use of the iterator is complete. // NOTE: 'dmux' must persist for the lifetime of 'iter'. -WEBP_EXTERN int WebPDemuxGetFrame( +WEBP_NODISCARD WEBP_EXTERN int WebPDemuxGetFrame( const WebPDemuxer* dmux, int frame_number, WebPIterator* iter); // Sets 'iter->fragment' to point to the next ('iter->frame_num' + 1) or // previous ('iter->frame_num' - 1) frame. These functions do not loop. // Returns true on success, false otherwise. -WEBP_EXTERN int WebPDemuxNextFrame(WebPIterator* iter); -WEBP_EXTERN int WebPDemuxPrevFrame(WebPIterator* iter); +WEBP_NODISCARD WEBP_EXTERN int WebPDemuxNextFrame(WebPIterator* iter); +WEBP_NODISCARD WEBP_EXTERN int WebPDemuxPrevFrame(WebPIterator* iter); // Releases any memory associated with 'iter'. // Must be called before any subsequent calls to WebPDemuxGetChunk() on the same @@ -202,15 +203,16 @@ struct WebPChunkIterator { // payloads are accessed through WebPDemuxGetFrame() and related functions. // Call WebPDemuxReleaseChunkIterator() when use of the iterator is complete. // NOTE: 'dmux' must persist for the lifetime of the iterator. -WEBP_EXTERN int WebPDemuxGetChunk(const WebPDemuxer* dmux, - const char fourcc[4], int chunk_number, - WebPChunkIterator* iter); +WEBP_NODISCARD WEBP_EXTERN int WebPDemuxGetChunk(const WebPDemuxer* dmux, + const char fourcc[4], + int chunk_number, + WebPChunkIterator* iter); // Sets 'iter->chunk' to point to the next ('iter->chunk_num' + 1) or previous // ('iter->chunk_num' - 1) chunk. These functions do not loop. // Returns true on success, false otherwise. -WEBP_EXTERN int WebPDemuxNextChunk(WebPChunkIterator* iter); -WEBP_EXTERN int WebPDemuxPrevChunk(WebPChunkIterator* iter); +WEBP_NODISCARD WEBP_EXTERN int WebPDemuxNextChunk(WebPChunkIterator* iter); +WEBP_NODISCARD WEBP_EXTERN int WebPDemuxPrevChunk(WebPChunkIterator* iter); // Releases any memory associated with 'iter'. // Must be called before destroying the associated WebPDemuxer with @@ -257,21 +259,21 @@ struct WebPAnimDecoderOptions { }; // Internal, version-checked, entry point. -WEBP_EXTERN int WebPAnimDecoderOptionsInitInternal( +WEBP_NODISCARD WEBP_EXTERN int WebPAnimDecoderOptionsInitInternal( WebPAnimDecoderOptions*, int); // Should always be called, to initialize a fresh WebPAnimDecoderOptions // structure before modification. Returns false in case of version mismatch. // WebPAnimDecoderOptionsInit() must have succeeded before using the // 'dec_options' object. -static WEBP_INLINE int WebPAnimDecoderOptionsInit( +WEBP_NODISCARD static WEBP_INLINE int WebPAnimDecoderOptionsInit( WebPAnimDecoderOptions* dec_options) { return WebPAnimDecoderOptionsInitInternal(dec_options, WEBP_DEMUX_ABI_VERSION); } // Internal, version-checked, entry point. -WEBP_EXTERN WebPAnimDecoder* WebPAnimDecoderNewInternal( +WEBP_NODISCARD WEBP_EXTERN WebPAnimDecoder* WebPAnimDecoderNewInternal( const WebPData*, const WebPAnimDecoderOptions*, int); // Creates and initializes a WebPAnimDecoder object. @@ -284,7 +286,7 @@ WEBP_EXTERN WebPAnimDecoder* WebPAnimDecoderNewInternal( // Returns: // A pointer to the newly created WebPAnimDecoder object, or NULL in case of // parsing error, invalid option or memory error. -static WEBP_INLINE WebPAnimDecoder* WebPAnimDecoderNew( +WEBP_NODISCARD static WEBP_INLINE WebPAnimDecoder* WebPAnimDecoderNew( const WebPData* webp_data, const WebPAnimDecoderOptions* dec_options) { return WebPAnimDecoderNewInternal(webp_data, dec_options, WEBP_DEMUX_ABI_VERSION); @@ -306,8 +308,8 @@ struct WebPAnimInfo { // info - (out) global information fetched from the animation. // Returns: // True on success. -WEBP_EXTERN int WebPAnimDecoderGetInfo(const WebPAnimDecoder* dec, - WebPAnimInfo* info); +WEBP_NODISCARD WEBP_EXTERN int WebPAnimDecoderGetInfo( + const WebPAnimDecoder* dec, WebPAnimInfo* info); // Fetch the next frame from 'dec' based on options supplied to // WebPAnimDecoderNew(). This will be a fully reconstructed canvas of size @@ -321,8 +323,9 @@ WEBP_EXTERN int WebPAnimDecoderGetInfo(const WebPAnimDecoder* dec, // Returns: // False if any of the arguments are NULL, or if there is a parsing or // decoding error, or if there are no more frames. Otherwise, returns true. -WEBP_EXTERN int WebPAnimDecoderGetNext(WebPAnimDecoder* dec, - uint8_t** buf, int* timestamp); +WEBP_NODISCARD WEBP_EXTERN int WebPAnimDecoderGetNext(WebPAnimDecoder* dec, + uint8_t** buf, + int* timestamp); // Check if there are more frames left to decode. // Parameters: @@ -330,7 +333,8 @@ WEBP_EXTERN int WebPAnimDecoderGetNext(WebPAnimDecoder* dec, // Returns: // True if 'dec' is not NULL and some frames are yet to be decoded. // Otherwise, returns false. -WEBP_EXTERN int WebPAnimDecoderHasMoreFrames(const WebPAnimDecoder* dec); +WEBP_NODISCARD WEBP_EXTERN int WebPAnimDecoderHasMoreFrames( + const WebPAnimDecoder* dec); // Resets the WebPAnimDecoder object, so that next call to // WebPAnimDecoderGetNext() will restart decoding from 1st frame. This would be @@ -348,7 +352,7 @@ WEBP_EXTERN void WebPAnimDecoderReset(WebPAnimDecoder* dec); // // Parameters: // dec - (in) decoder instance from which the demuxer object is to be fetched. -WEBP_EXTERN const WebPDemuxer* WebPAnimDecoderGetDemuxer( +WEBP_NODISCARD WEBP_EXTERN const WebPDemuxer* WebPAnimDecoderGetDemuxer( const WebPAnimDecoder* dec); // Deletes the WebPAnimDecoder object. diff --git a/3rdparty/libwebp/src/webp/encode.h b/3rdparty/libwebp/src/webp/encode.h index 56b68e2f10..f3d59297c8 100644 --- a/3rdparty/libwebp/src/webp/encode.h +++ b/3rdparty/libwebp/src/webp/encode.h @@ -164,13 +164,14 @@ typedef enum WebPPreset { } WebPPreset; // Internal, version-checked, entry point -WEBP_EXTERN int WebPConfigInitInternal(WebPConfig*, WebPPreset, float, int); +WEBP_NODISCARD WEBP_EXTERN int WebPConfigInitInternal(WebPConfig*, WebPPreset, + float, int); // Should always be called, to initialize a fresh WebPConfig structure before // modification. Returns false in case of version mismatch. WebPConfigInit() // must have succeeded before using the 'config' object. // Note that the default values are lossless=0 and quality=75. -static WEBP_INLINE int WebPConfigInit(WebPConfig* config) { +WEBP_NODISCARD static WEBP_INLINE int WebPConfigInit(WebPConfig* config) { return WebPConfigInitInternal(config, WEBP_PRESET_DEFAULT, 75.f, WEBP_ENCODER_ABI_VERSION); } @@ -179,8 +180,9 @@ static WEBP_INLINE int WebPConfigInit(WebPConfig* config) { // set of parameters (referred to by 'preset') and a given quality factor. // This function can be called as a replacement to WebPConfigInit(). Will // return false in case of error. -static WEBP_INLINE int WebPConfigPreset(WebPConfig* config, - WebPPreset preset, float quality) { +WEBP_NODISCARD static WEBP_INLINE int WebPConfigPreset(WebPConfig* config, + WebPPreset preset, + float quality) { return WebPConfigInitInternal(config, preset, quality, WEBP_ENCODER_ABI_VERSION); } @@ -191,11 +193,12 @@ static WEBP_INLINE int WebPConfigPreset(WebPConfig* config, // speed and final compressed size. // This function will overwrite several fields from config: 'method', 'quality' // and 'lossless'. Returns false in case of parameter error. -WEBP_EXTERN int WebPConfigLosslessPreset(WebPConfig* config, int level); +WEBP_NODISCARD WEBP_EXTERN int WebPConfigLosslessPreset(WebPConfig* config, + int level); // Returns true if 'config' is non-NULL and all configuration parameters are // within their valid ranges. -WEBP_EXTERN int WebPValidateConfig(const WebPConfig* config); +WEBP_NODISCARD WEBP_EXTERN int WebPValidateConfig(const WebPConfig* config); //------------------------------------------------------------------------------ // Input / Output @@ -255,8 +258,8 @@ WEBP_EXTERN void WebPMemoryWriterClear(WebPMemoryWriter* writer); // The custom writer to be used with WebPMemoryWriter as custom_ptr. Upon // completion, writer.mem and writer.size will hold the coded data. // writer.mem must be freed by calling WebPMemoryWriterClear. -WEBP_EXTERN int WebPMemoryWrite(const uint8_t* data, size_t data_size, - const WebPPicture* picture); +WEBP_NODISCARD WEBP_EXTERN int WebPMemoryWrite( + const uint8_t* data, size_t data_size, const WebPPicture* picture); // Progress hook, called from time to time to report progress. It can return // false to request an abort of the encoding process, or true otherwise if @@ -364,13 +367,13 @@ struct WebPPicture { }; // Internal, version-checked, entry point -WEBP_EXTERN int WebPPictureInitInternal(WebPPicture*, int); +WEBP_NODISCARD WEBP_EXTERN int WebPPictureInitInternal(WebPPicture*, int); // Should always be called, to initialize the structure. Returns false in case // of version mismatch. WebPPictureInit() must have succeeded before using the // 'picture' object. // Note that, by default, use_argb is false and colorspace is WEBP_YUV420. -static WEBP_INLINE int WebPPictureInit(WebPPicture* picture) { +WEBP_NODISCARD static WEBP_INLINE int WebPPictureInit(WebPPicture* picture) { return WebPPictureInitInternal(picture, WEBP_ENCODER_ABI_VERSION); } @@ -381,7 +384,7 @@ static WEBP_INLINE int WebPPictureInit(WebPPicture* picture) { // Allocate y/u/v buffers as per colorspace/width/height specification. // Note! This function will free the previous buffer if needed. // Returns false in case of memory error. -WEBP_EXTERN int WebPPictureAlloc(WebPPicture* picture); +WEBP_NODISCARD WEBP_EXTERN int WebPPictureAlloc(WebPPicture* picture); // Release the memory allocated by WebPPictureAlloc() or WebPPictureImport*(). // Note that this function does _not_ free the memory used by the 'picture' @@ -394,7 +397,8 @@ WEBP_EXTERN void WebPPictureFree(WebPPicture* picture); // will fully own the copied pixels (this is not a view). The 'dst' picture need // not be initialized as its content is overwritten. // Returns false in case of memory allocation error. -WEBP_EXTERN int WebPPictureCopy(const WebPPicture* src, WebPPicture* dst); +WEBP_NODISCARD WEBP_EXTERN int WebPPictureCopy(const WebPPicture* src, + WebPPicture* dst); // Compute the single distortion for packed planes of samples. // 'src' will be compared to 'ref', and the raw distortion stored into @@ -403,19 +407,18 @@ WEBP_EXTERN int WebPPictureCopy(const WebPPicture* src, WebPPicture* dst); // 'x_step' is the horizontal stride (in bytes) between samples. // 'src/ref_stride' is the byte distance between rows. // Returns false in case of error (bad parameter, memory allocation error, ...). -WEBP_EXTERN int WebPPlaneDistortion(const uint8_t* src, size_t src_stride, - const uint8_t* ref, size_t ref_stride, - int width, int height, - size_t x_step, - int type, // 0 = PSNR, 1 = SSIM, 2 = LSIM - float* distortion, float* result); +WEBP_NODISCARD WEBP_EXTERN int WebPPlaneDistortion( + const uint8_t* src, size_t src_stride, + const uint8_t* ref, size_t ref_stride, int width, int height, size_t x_step, + int type, // 0 = PSNR, 1 = SSIM, 2 = LSIM + float* distortion, float* result); // Compute PSNR, SSIM or LSIM distortion metric between two pictures. Results // are in dB, stored in result[] in the B/G/R/A/All order. The distortion is // always performed using ARGB samples. Hence if the input is YUV(A), the // picture will be internally converted to ARGB (just for the measurement). // Warning: this function is rather CPU-intensive. -WEBP_EXTERN int WebPPictureDistortion( +WEBP_NODISCARD WEBP_EXTERN int WebPPictureDistortion( const WebPPicture* src, const WebPPicture* ref, int metric_type, // 0 = PSNR, 1 = SSIM, 2 = LSIM float result[5]); @@ -428,8 +431,8 @@ WEBP_EXTERN int WebPPictureDistortion( // must be fully be comprised inside the 'src' source picture. If the source // picture uses the YUV420 colorspace, the top and left coordinates will be // snapped to even values. -WEBP_EXTERN int WebPPictureCrop(WebPPicture* picture, - int left, int top, int width, int height); +WEBP_NODISCARD WEBP_EXTERN int WebPPictureCrop( + WebPPicture* picture, int left, int top, int width, int height); // Extracts a view from 'src' picture into 'dst'. The rectangle for the view // is defined by the top-left corner pixel coordinates (left, top) as well @@ -442,9 +445,9 @@ WEBP_EXTERN int WebPPictureCrop(WebPPicture* picture, // with WebPPictureInit() if it is different from 'src', since its content will // be overwritten. // Returns false in case of invalid parameters. -WEBP_EXTERN int WebPPictureView(const WebPPicture* src, - int left, int top, int width, int height, - WebPPicture* dst); +WEBP_NODISCARD WEBP_EXTERN int WebPPictureView( + const WebPPicture* src, int left, int top, int width, int height, + WebPPicture* dst); // Returns true if the 'picture' is actually a view and therefore does // not own the memory for pixels. @@ -455,29 +458,30 @@ WEBP_EXTERN int WebPPictureIsView(const WebPPicture* picture); // dimension will be calculated preserving the aspect ratio. // No gamma correction is applied. // Returns false in case of error (invalid parameter or insufficient memory). -WEBP_EXTERN int WebPPictureRescale(WebPPicture* picture, int width, int height); +WEBP_NODISCARD WEBP_EXTERN int WebPPictureRescale(WebPPicture* picture, + int width, int height); // Colorspace conversion function to import RGB samples. // Previous buffer will be free'd, if any. // *rgb buffer should have a size of at least height * rgb_stride. // Returns false in case of memory error. -WEBP_EXTERN int WebPPictureImportRGB( +WEBP_NODISCARD WEBP_EXTERN int WebPPictureImportRGB( WebPPicture* picture, const uint8_t* rgb, int rgb_stride); // Same, but for RGBA buffer. -WEBP_EXTERN int WebPPictureImportRGBA( +WEBP_NODISCARD WEBP_EXTERN int WebPPictureImportRGBA( WebPPicture* picture, const uint8_t* rgba, int rgba_stride); // Same, but for RGBA buffer. Imports the RGB direct from the 32-bit format // input buffer ignoring the alpha channel. Avoids needing to copy the data // to a temporary 24-bit RGB buffer to import the RGB only. -WEBP_EXTERN int WebPPictureImportRGBX( +WEBP_NODISCARD WEBP_EXTERN int WebPPictureImportRGBX( WebPPicture* picture, const uint8_t* rgbx, int rgbx_stride); // Variants of the above, but taking BGR(A|X) input. -WEBP_EXTERN int WebPPictureImportBGR( +WEBP_NODISCARD WEBP_EXTERN int WebPPictureImportBGR( WebPPicture* picture, const uint8_t* bgr, int bgr_stride); -WEBP_EXTERN int WebPPictureImportBGRA( +WEBP_NODISCARD WEBP_EXTERN int WebPPictureImportBGRA( WebPPicture* picture, const uint8_t* bgra, int bgra_stride); -WEBP_EXTERN int WebPPictureImportBGRX( +WEBP_NODISCARD WEBP_EXTERN int WebPPictureImportBGRX( WebPPicture* picture, const uint8_t* bgrx, int bgrx_stride); // Converts picture->argb data to the YUV420A format. The 'colorspace' @@ -486,24 +490,24 @@ WEBP_EXTERN int WebPPictureImportBGRX( // non-opaque transparent values is detected, and 'colorspace' will be // adjusted accordingly. Note that this method is lossy. // Returns false in case of error. -WEBP_EXTERN int WebPPictureARGBToYUVA(WebPPicture* picture, - WebPEncCSP /*colorspace = WEBP_YUV420*/); +WEBP_NODISCARD WEBP_EXTERN int WebPPictureARGBToYUVA( + WebPPicture* picture, WebPEncCSP /*colorspace = WEBP_YUV420*/); // Same as WebPPictureARGBToYUVA(), but the conversion is done using // pseudo-random dithering with a strength 'dithering' between // 0.0 (no dithering) and 1.0 (maximum dithering). This is useful // for photographic picture. -WEBP_EXTERN int WebPPictureARGBToYUVADithered( +WEBP_NODISCARD WEBP_EXTERN int WebPPictureARGBToYUVADithered( WebPPicture* picture, WebPEncCSP colorspace, float dithering); -// Performs 'sharp' RGBA->YUVA420 downsampling and colorspace conversion. +// Performs 'sharp' RGBA->YUVA420 downsampling and colorspace conversion // Downsampling is handled with extra care in case of color clipping. This // method is roughly 2x slower than WebPPictureARGBToYUVA() but produces better // and sharper YUV representation. // Returns false in case of error. -WEBP_EXTERN int WebPPictureSharpARGBToYUVA(WebPPicture* picture); +WEBP_NODISCARD WEBP_EXTERN int WebPPictureSharpARGBToYUVA(WebPPicture* picture); // kept for backward compatibility: -WEBP_EXTERN int WebPPictureSmartARGBToYUVA(WebPPicture* picture); +WEBP_NODISCARD WEBP_EXTERN int WebPPictureSmartARGBToYUVA(WebPPicture* picture); // Converts picture->yuv to picture->argb and sets picture->use_argb to true. // The input format must be YUV_420 or YUV_420A. The conversion from YUV420 to @@ -511,7 +515,7 @@ WEBP_EXTERN int WebPPictureSmartARGBToYUVA(WebPPicture* picture); // Note that the use of this colorspace is discouraged if one has access to the // raw ARGB samples, since using YUV420 is comparatively lossy. // Returns false in case of error. -WEBP_EXTERN int WebPPictureYUVAToARGB(WebPPicture* picture); +WEBP_NODISCARD WEBP_EXTERN int WebPPictureYUVAToARGB(WebPPicture* picture); // Helper function: given a width x height plane of RGBA or YUV(A) samples // clean-up or smoothen the YUV or RGB samples under fully transparent area, @@ -541,7 +545,8 @@ WEBP_EXTERN void WebPBlendAlpha(WebPPicture* picture, uint32_t background_rgb); // the former for lossy encoding, and the latter for lossless encoding // (when config.lossless is true). Automatic conversion from one format to // another is provided but they both incur some loss. -WEBP_EXTERN int WebPEncode(const WebPConfig* config, WebPPicture* picture); +WEBP_NODISCARD WEBP_EXTERN int WebPEncode(const WebPConfig* config, + WebPPicture* picture); //------------------------------------------------------------------------------ diff --git a/3rdparty/libwebp/src/webp/mux.h b/3rdparty/libwebp/src/webp/mux.h index 7d27489a40..8fb067e435 100644 --- a/3rdparty/libwebp/src/webp/mux.h +++ b/3rdparty/libwebp/src/webp/mux.h @@ -16,12 +16,13 @@ #define WEBP_WEBP_MUX_H_ #include "./mux_types.h" +#include "./types.h" #ifdef __cplusplus extern "C" { #endif -#define WEBP_MUX_ABI_VERSION 0x0108 // MAJOR(8b) + MINOR(8b) +#define WEBP_MUX_ABI_VERSION 0x0109 // MAJOR(8b) + MINOR(8b) //------------------------------------------------------------------------------ // Mux API @@ -70,7 +71,7 @@ typedef struct WebPMuxAnimParams WebPMuxAnimParams; typedef struct WebPAnimEncoderOptions WebPAnimEncoderOptions; // Error codes -typedef enum WebPMuxError { +typedef enum WEBP_NODISCARD WebPMuxError { WEBP_MUX_OK = 1, WEBP_MUX_NOT_FOUND = 0, WEBP_MUX_INVALID_ARGUMENT = -1, @@ -104,13 +105,13 @@ WEBP_EXTERN int WebPGetMuxVersion(void); // Life of a Mux object // Internal, version-checked, entry point -WEBP_EXTERN WebPMux* WebPNewInternal(int); +WEBP_NODISCARD WEBP_EXTERN WebPMux* WebPNewInternal(int); // Creates an empty mux object. // Returns: // A pointer to the newly created empty mux object. // Or NULL in case of memory error. -static WEBP_INLINE WebPMux* WebPMuxNew(void) { +WEBP_NODISCARD static WEBP_INLINE WebPMux* WebPMuxNew(void) { return WebPNewInternal(WEBP_MUX_ABI_VERSION); } @@ -123,18 +124,21 @@ WEBP_EXTERN void WebPMuxDelete(WebPMux* mux); // Mux creation. // Internal, version-checked, entry point -WEBP_EXTERN WebPMux* WebPMuxCreateInternal(const WebPData*, int, int); +WEBP_NODISCARD WEBP_EXTERN WebPMux* WebPMuxCreateInternal(const WebPData*, int, + int); // Creates a mux object from raw data given in WebP RIFF format. // Parameters: // bitstream - (in) the bitstream data in WebP RIFF format // copy_data - (in) value 1 indicates given data WILL be copied to the mux -// object and value 0 indicates data will NOT be copied. +// object and value 0 indicates data will NOT be copied. If the +// data is not copied, it must exist for the lifetime of the +// mux object. // Returns: // A pointer to the mux object created from given data - on success. // NULL - In case of invalid data or memory error. -static WEBP_INLINE WebPMux* WebPMuxCreate(const WebPData* bitstream, - int copy_data) { +WEBP_NODISCARD static WEBP_INLINE WebPMux* WebPMuxCreate( + const WebPData* bitstream, int copy_data) { return WebPMuxCreateInternal(bitstream, copy_data, WEBP_MUX_ABI_VERSION); } @@ -154,7 +158,9 @@ static WEBP_INLINE WebPMux* WebPMuxCreate(const WebPData* bitstream, // e.g., "ICCP", "XMP ", "EXIF" etc. // chunk_data - (in) the chunk data to be added // copy_data - (in) value 1 indicates given data WILL be copied to the mux -// object and value 0 indicates data will NOT be copied. +// object and value 0 indicates data will NOT be copied. If the +// data is not copied, it must exist until a call to +// WebPMuxAssemble() is made. // Returns: // WEBP_MUX_INVALID_ARGUMENT - if mux, fourcc or chunk_data is NULL // or if fourcc corresponds to an image chunk. @@ -217,7 +223,9 @@ struct WebPMuxFrameInfo { // bitstream - (in) can be a raw VP8/VP8L bitstream or a single-image // WebP file (non-animated) // copy_data - (in) value 1 indicates given data WILL be copied to the mux -// object and value 0 indicates data will NOT be copied. +// object and value 0 indicates data will NOT be copied. If the +// data is not copied, it must exist until a call to +// WebPMuxAssemble() is made. // Returns: // WEBP_MUX_INVALID_ARGUMENT - if mux is NULL or bitstream is NULL. // WEBP_MUX_MEMORY_ERROR - on memory allocation error. @@ -235,7 +243,9 @@ WEBP_EXTERN WebPMuxError WebPMuxSetImage( // mux - (in/out) object to which the frame is to be added // frame - (in) frame data. // copy_data - (in) value 1 indicates given data WILL be copied to the mux -// object and value 0 indicates data will NOT be copied. +// object and value 0 indicates data will NOT be copied. If the +// data is not copied, it must exist until a call to +// WebPMuxAssemble() is made. // Returns: // WEBP_MUX_INVALID_ARGUMENT - if mux or frame is NULL // or if content of 'frame' is invalid. @@ -449,7 +459,7 @@ WEBP_EXTERN int WebPAnimEncoderOptionsInitInternal( // structure before modification. Returns false in case of version mismatch. // WebPAnimEncoderOptionsInit() must have succeeded before using the // 'enc_options' object. -static WEBP_INLINE int WebPAnimEncoderOptionsInit( +WEBP_NODISCARD static WEBP_INLINE int WebPAnimEncoderOptionsInit( WebPAnimEncoderOptions* enc_options) { return WebPAnimEncoderOptionsInitInternal(enc_options, WEBP_MUX_ABI_VERSION); } @@ -490,7 +500,7 @@ static WEBP_INLINE WebPAnimEncoder* WebPAnimEncoderNew( // Returns: // On error, returns false and frame->error_code is set appropriately. // Otherwise, returns true. -WEBP_EXTERN int WebPAnimEncoderAdd( +WEBP_NODISCARD WEBP_EXTERN int WebPAnimEncoderAdd( WebPAnimEncoder* enc, struct WebPPicture* frame, int timestamp_ms, const struct WebPConfig* config); @@ -503,8 +513,8 @@ WEBP_EXTERN int WebPAnimEncoderAdd( // webp_data - (out) generated WebP bitstream. // Returns: // True on success. -WEBP_EXTERN int WebPAnimEncoderAssemble(WebPAnimEncoder* enc, - WebPData* webp_data); +WEBP_NODISCARD WEBP_EXTERN int WebPAnimEncoderAssemble(WebPAnimEncoder* enc, + WebPData* webp_data); // Get error string corresponding to the most recent call using 'enc'. The // returned string is owned by 'enc' and is valid only until the next call to @@ -521,6 +531,57 @@ WEBP_EXTERN const char* WebPAnimEncoderGetError(WebPAnimEncoder* enc); // enc - (in/out) object to be deleted WEBP_EXTERN void WebPAnimEncoderDelete(WebPAnimEncoder* enc); +//------------------------------------------------------------------------------ +// Non-image chunks. + +// Note: Only non-image related chunks should be managed through chunk APIs. +// (Image related chunks are: "ANMF", "VP8 ", "VP8L" and "ALPH"). + +// Adds a chunk with id 'fourcc' and data 'chunk_data' in the enc object. +// Any existing chunk(s) with the same id will be removed. +// Parameters: +// enc - (in/out) object to which the chunk is to be added +// fourcc - (in) a character array containing the fourcc of the given chunk; +// e.g., "ICCP", "XMP ", "EXIF", etc. +// chunk_data - (in) the chunk data to be added +// copy_data - (in) value 1 indicates given data WILL be copied to the enc +// object and value 0 indicates data will NOT be copied. If the +// data is not copied, it must exist until a call to +// WebPAnimEncoderAssemble() is made. +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if enc, fourcc or chunk_data is NULL. +// WEBP_MUX_MEMORY_ERROR - on memory allocation error. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPAnimEncoderSetChunk( + WebPAnimEncoder* enc, const char fourcc[4], const WebPData* chunk_data, + int copy_data); + +// Gets a reference to the data of the chunk with id 'fourcc' in the enc object. +// The caller should NOT free the returned data. +// Parameters: +// enc - (in) object from which the chunk data is to be fetched +// fourcc - (in) a character array containing the fourcc of the chunk; +// e.g., "ICCP", "XMP ", "EXIF", etc. +// chunk_data - (out) returned chunk data +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if enc, fourcc or chunk_data is NULL. +// WEBP_MUX_NOT_FOUND - If enc does not contain a chunk with the given id. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPAnimEncoderGetChunk( + const WebPAnimEncoder* enc, const char fourcc[4], WebPData* chunk_data); + +// Deletes the chunk with the given 'fourcc' from the enc object. +// Parameters: +// enc - (in/out) object from which the chunk is to be deleted +// fourcc - (in) a character array containing the fourcc of the chunk; +// e.g., "ICCP", "XMP ", "EXIF", etc. +// Returns: +// WEBP_MUX_INVALID_ARGUMENT - if enc or fourcc is NULL. +// WEBP_MUX_NOT_FOUND - If enc does not contain a chunk with the given fourcc. +// WEBP_MUX_OK - on success. +WEBP_EXTERN WebPMuxError WebPAnimEncoderDeleteChunk( + WebPAnimEncoder* enc, const char fourcc[4]); + //------------------------------------------------------------------------------ #ifdef __cplusplus diff --git a/3rdparty/libwebp/src/webp/mux_types.h b/3rdparty/libwebp/src/webp/mux_types.h index 2fe8195839..c585d2082f 100644 --- a/3rdparty/libwebp/src/webp/mux_types.h +++ b/3rdparty/libwebp/src/webp/mux_types.h @@ -79,7 +79,8 @@ static WEBP_INLINE void WebPDataClear(WebPData* webp_data) { // Allocates necessary storage for 'dst' and copies the contents of 'src'. // Returns true on success. -static WEBP_INLINE int WebPDataCopy(const WebPData* src, WebPData* dst) { +WEBP_NODISCARD static WEBP_INLINE int WebPDataCopy(const WebPData* src, + WebPData* dst) { if (src == NULL || dst == NULL) return 0; WebPDataInit(dst); if (src->bytes != NULL && src->size != 0) { diff --git a/3rdparty/libwebp/src/webp/types.h b/3rdparty/libwebp/src/webp/types.h index f255432e41..9c17edec45 100644 --- a/3rdparty/libwebp/src/webp/types.h +++ b/3rdparty/libwebp/src/webp/types.h @@ -36,18 +36,39 @@ typedef long long int int64_t; #define WEBP_INLINE __forceinline #endif /* _MSC_VER */ +#ifndef WEBP_NODISCARD +#if defined(WEBP_ENABLE_NODISCARD) && WEBP_ENABLE_NODISCARD +#if (defined(__cplusplus) && __cplusplus >= 201700L) || \ + (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) +#define WEBP_NODISCARD [[nodiscard]] +#else +// gcc's __has_attribute does not work for enums. +#if defined(__clang__) && defined(__has_attribute) +#if __has_attribute(warn_unused_result) +#define WEBP_NODISCARD __attribute__((warn_unused_result)) +#else +#define WEBP_NODISCARD +#endif /* __has_attribute(warn_unused_result) */ +#else +#define WEBP_NODISCARD +#endif /* defined(__clang__) && defined(__has_attribute) */ +#endif /* (defined(__cplusplus) && __cplusplus >= 201700L) || + (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) */ +#else +#define WEBP_NODISCARD +#endif /* defined(WEBP_ENABLE_NODISCARD) && WEBP_ENABLE_NODISCARD */ +#endif /* WEBP_NODISCARD */ + #ifndef WEBP_EXTERN // This explicitly marks library functions and allows for changing the // signature for e.g., Windows DLL builds. -# if defined(__GNUC__) && __GNUC__ >= 4 +# if defined(_WIN32) && defined(WEBP_DLL) +# define WEBP_EXTERN __declspec(dllexport) +# elif defined(__GNUC__) && __GNUC__ >= 4 # define WEBP_EXTERN extern __attribute__ ((visibility ("default"))) # else -# if defined(_MSC_VER) && defined(WEBP_DLL) -# define WEBP_EXTERN __declspec(dllexport) -# else -# define WEBP_EXTERN extern -# endif -# endif /* __GNUC__ >= 4 */ +# define WEBP_EXTERN extern +# endif /* defined(_WIN32) && defined(WEBP_DLL) */ #endif /* WEBP_EXTERN */ // Macro to check ABI compatibility (same major revision number) @@ -60,7 +81,7 @@ extern "C" { // Allocates 'size' bytes of memory. Returns NULL upon error. Memory // must be deallocated by calling WebPFree(). This function is made available // by the core 'libwebp' library. -WEBP_EXTERN void* WebPMalloc(size_t size); +WEBP_NODISCARD WEBP_EXTERN void* WebPMalloc(size_t size); // Releases memory returned by the WebPDecode*() functions (from decode.h). WEBP_EXTERN void WebPFree(void* ptr); From c317a3ee89e79b6c26ad5c4406e56998723f2f92 Mon Sep 17 00:00:00 2001 From: Vincent Rabaud Date: Wed, 17 Apr 2024 15:58:10 +0200 Subject: [PATCH 08/14] Merge pull request #25419 from vrabaud:ffmpeg Fix race condition in InternalFFMpegRegister initialization. #25419 initLogger_ does not check if the logger has been initizalized before and it might initialize it several times from different threads, racing with other threads that are logging. ### 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 --- modules/videoio/src/cap_ffmpeg_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/videoio/src/cap_ffmpeg_impl.hpp b/modules/videoio/src/cap_ffmpeg_impl.hpp index 9be4b08279..0546fbdfbe 100644 --- a/modules/videoio/src/cap_ffmpeg_impl.hpp +++ b/modules/videoio/src/cap_ffmpeg_impl.hpp @@ -927,7 +927,6 @@ public: if(!threadSafe) lock.lock(); static InternalFFMpegRegister instance; - initLogger_(); // update logger setup unconditionally (GStreamer's libav plugin may override these settings) } static void initLogger_() { @@ -965,6 +964,7 @@ public: /* register a callback function for synchronization */ av_lockmgr_register(&LockCallBack); #endif + initLogger_(); } ~InternalFFMpegRegister() { From d77dbbe7a0c791deaf7f9c612cbfaa36a5e55b0c Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Wed, 17 Apr 2024 14:49:28 +0300 Subject: [PATCH 09/14] imgproc: sync boundingRect function with 5.x --- modules/imgproc/src/geometry.cpp | 331 ++++++++++++++++++++++++++++ modules/imgproc/src/shapedescr.cpp | 334 ----------------------------- 2 files changed, 331 insertions(+), 334 deletions(-) diff --git a/modules/imgproc/src/geometry.cpp b/modules/imgproc/src/geometry.cpp index ae14590f22..8cf2474787 100644 --- a/modules/imgproc/src/geometry.cpp +++ b/modules/imgproc/src/geometry.cpp @@ -39,7 +39,9 @@ // //M*/ #include "precomp.hpp" +#include "opencv2/core/hal/intrin.hpp" +using namespace cv; CV_IMPL CvRect cvMaxRect( const CvRect* rect1, const CvRect* rect2 ) @@ -592,3 +594,332 @@ float cv::intersectConvexConvex( InputArray _p1, InputArray _p2, OutputArray _p1 } return (float)fabs(area); } + +static Rect maskBoundingRect( const Mat& img ) +{ + CV_Assert( img.depth() <= CV_8S && img.channels() == 1 ); + + Size size = img.size(); + int xmin = size.width, ymin = -1, xmax = -1, ymax = -1, i, j, k; + + for( i = 0; i < size.height; i++ ) + { + const uchar* _ptr = img.ptr(i); + const uchar* ptr = (const uchar*)alignPtr(_ptr, 4); + int have_nz = 0, k_min, offset = (int)(ptr - _ptr); + j = 0; + offset = MIN(offset, size.width); + for( ; j < offset; j++ ) + if( _ptr[j] ) + { + if( j < xmin ) + xmin = j; + if( j > xmax ) + xmax = j; + have_nz = 1; + } + if( offset < size.width ) + { + xmin -= offset; + xmax -= offset; + size.width -= offset; + j = 0; + for( ; j <= xmin - 4; j += 4 ) + if( *((int*)(ptr+j)) ) + break; + for( ; j < xmin; j++ ) + if( ptr[j] ) + { + xmin = j; + if( j > xmax ) + xmax = j; + have_nz = 1; + break; + } + k_min = MAX(j-1, xmax); + k = size.width - 1; + for( ; k > k_min && (k&3) != 3; k-- ) + if( ptr[k] ) + break; + if( k > k_min && (k&3) == 3 ) + { + for( ; k > k_min+3; k -= 4 ) + if( *((int*)(ptr+k-3)) ) + break; + } + for( ; k > k_min; k-- ) + if( ptr[k] ) + { + xmax = k; + have_nz = 1; + break; + } + if( !have_nz ) + { + j &= ~3; + for( ; j <= k - 3; j += 4 ) + if( *((int*)(ptr+j)) ) + break; + for( ; j <= k; j++ ) + if( ptr[j] ) + { + have_nz = 1; + break; + } + } + xmin += offset; + xmax += offset; + size.width += offset; + } + if( have_nz ) + { + if( ymin < 0 ) + ymin = i; + ymax = i; + } + } + + if( xmin >= size.width ) + xmin = ymin = 0; + return Rect(xmin, ymin, xmax - xmin + 1, ymax - ymin + 1); +} + +// Calculates bounding rectangle of a point set or retrieves already calculated +static Rect pointSetBoundingRect( const Mat& points ) +{ + int npoints = points.checkVector(2); + int depth = points.depth(); + CV_Assert(npoints >= 0 && (depth == CV_32F || depth == CV_32S)); + + int xmin = 0, ymin = 0, xmax = -1, ymax = -1, i; + bool is_float = depth == CV_32F; + + if( npoints == 0 ) + return Rect(); + +#if CV_SIMD // TODO: enable for CV_SIMD_SCALABLE, loop tail related. + const int64_t* pts = points.ptr(); + + if( !is_float ) + { + v_int32 minval, maxval; + minval = maxval = v_reinterpret_as_s32(vx_setall_s64(*pts)); //min[0]=pt.x, min[1]=pt.y, min[2]=pt.x, min[3]=pt.y + for( i = 1; i <= npoints - VTraits::vlanes()/2; i+= VTraits::vlanes()/2 ) + { + v_int32 ptXY2 = v_reinterpret_as_s32(vx_load(pts + i)); + minval = v_min(ptXY2, minval); + maxval = v_max(ptXY2, maxval); + } + minval = v_min(v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(minval))), v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(minval)))); + maxval = v_max(v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(maxval))), v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(maxval)))); + if( i <= npoints - VTraits::vlanes()/4 ) + { + v_int32 ptXY = v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(vx_load_low(pts + i)))); + minval = v_min(ptXY, minval); + maxval = v_max(ptXY, maxval); + i += VTraits::vlanes()/2; + } + for(int j = 16; j < VTraits::vlanes(); j*=2) + { + minval = v_min(v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(minval))), v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(minval)))); + maxval = v_max(v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(maxval))), v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(maxval)))); + } + xmin = v_get0(minval); + xmax = v_get0(maxval); + ymin = v_get0(v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(minval)))); + ymax = v_get0(v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(maxval)))); +#if CV_SIMD_WIDTH > 16 + if( i < npoints ) + { + v_int32x4 minval2, maxval2; + minval2 = maxval2 = v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(v_load_low(pts + i)))); + for( i++; i < npoints; i++ ) + { + v_int32x4 ptXY = v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(v_load_low(pts + i)))); + minval2 = v_min(ptXY, minval2); + maxval2 = v_max(ptXY, maxval2); + } + xmin = min(xmin, v_get0(minval2)); + xmax = max(xmax, v_get0(maxval2)); + ymin = min(ymin, v_get0(v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(minval2))))); + ymax = max(ymax, v_get0(v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(maxval2))))); + } +#endif // CV_SIMD + } + else + { + v_float32 minval, maxval; + minval = maxval = v_reinterpret_as_f32(vx_setall_s64(*pts)); //min[0]=pt.x, min[1]=pt.y, min[2]=pt.x, min[3]=pt.y + for( i = 1; i <= npoints - VTraits::vlanes()/2; i+= VTraits::vlanes()/2 ) + { + v_float32 ptXY2 = v_reinterpret_as_f32(vx_load(pts + i)); + minval = v_min(ptXY2, minval); + maxval = v_max(ptXY2, maxval); + } + minval = v_min(v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(minval))), v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(minval)))); + maxval = v_max(v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(maxval))), v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(maxval)))); + if( i <= npoints - VTraits::vlanes()/4 ) + { + v_float32 ptXY = v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(vx_load_low(pts + i)))); + minval = v_min(ptXY, minval); + maxval = v_max(ptXY, maxval); + i += VTraits::vlanes()/4; + } + for(int j = 16; j < VTraits::vlanes(); j*=2) + { + minval = v_min(v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(minval))), v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(minval)))); + maxval = v_max(v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(maxval))), v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(maxval)))); + } + xmin = cvFloor(v_get0(minval)); + xmax = cvFloor(v_get0(maxval)); + ymin = cvFloor(v_get0(v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(minval))))); + ymax = cvFloor(v_get0(v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(maxval))))); +#if CV_SIMD_WIDTH > 16 + if( i < npoints ) + { + v_float32x4 minval2, maxval2; + minval2 = maxval2 = v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(v_load_low(pts + i)))); + for( i++; i < npoints; i++ ) + { + v_float32x4 ptXY = v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(v_load_low(pts + i)))); + minval2 = v_min(ptXY, minval2); + maxval2 = v_max(ptXY, maxval2); + } + xmin = min(xmin, cvFloor(v_get0(minval2))); + xmax = max(xmax, cvFloor(v_get0(maxval2))); + ymin = min(ymin, cvFloor(v_get0(v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(minval2)))))); + ymax = max(ymax, cvFloor(v_get0(v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(maxval2)))))); + } +#endif + } +#else + const Point* pts = points.ptr(); + Point pt = pts[0]; + + if( !is_float ) + { + xmin = xmax = pt.x; + ymin = ymax = pt.y; + + for( i = 1; i < npoints; i++ ) + { + pt = pts[i]; + + if( xmin > pt.x ) + xmin = pt.x; + + if( xmax < pt.x ) + xmax = pt.x; + + if( ymin > pt.y ) + ymin = pt.y; + + if( ymax < pt.y ) + ymax = pt.y; + } + } + else + { + Cv32suf v; + // init values + xmin = xmax = CV_TOGGLE_FLT(pt.x); + ymin = ymax = CV_TOGGLE_FLT(pt.y); + + for( i = 1; i < npoints; i++ ) + { + pt = pts[i]; + pt.x = CV_TOGGLE_FLT(pt.x); + pt.y = CV_TOGGLE_FLT(pt.y); + + if( xmin > pt.x ) + xmin = pt.x; + + if( xmax < pt.x ) + xmax = pt.x; + + if( ymin > pt.y ) + ymin = pt.y; + + if( ymax < pt.y ) + ymax = pt.y; + } + + v.i = CV_TOGGLE_FLT(xmin); xmin = cvFloor(v.f); + v.i = CV_TOGGLE_FLT(ymin); ymin = cvFloor(v.f); + // because right and bottom sides of the bounding rectangle are not inclusive + // (note +1 in width and height calculation below), cvFloor is used here instead of cvCeil + v.i = CV_TOGGLE_FLT(xmax); xmax = cvFloor(v.f); + v.i = CV_TOGGLE_FLT(ymax); ymax = cvFloor(v.f); + } +#endif + + return Rect(xmin, ymin, xmax - xmin + 1, ymax - ymin + 1); +} + + +cv::Rect cv::boundingRect(InputArray array) +{ + CV_INSTRUMENT_REGION(); + + Mat m = array.getMat(); + return m.depth() <= CV_8U ? maskBoundingRect(m) : pointSetBoundingRect(m); +} + + +/* Calculates bounding rectangle of a point set or retrieves already calculated */ +CV_IMPL CvRect +cvBoundingRect( CvArr* array, int update ) +{ + cv::Rect rect; + CvContour contour_header; + CvSeq* ptseq = 0; + CvSeqBlock block; + + CvMat stub, *mat = 0; + int calculate = update; + + if( CV_IS_SEQ( array )) + { + ptseq = (CvSeq*)array; + if( !CV_IS_SEQ_POINT_SET( ptseq )) + CV_Error( cv::Error::StsBadArg, "Unsupported sequence type" ); + + if( ptseq->header_size < (int)sizeof(CvContour)) + { + update = 0; + calculate = 1; + } + } + else + { + mat = cvGetMat( array, &stub ); + if( CV_MAT_TYPE(mat->type) == CV_32SC2 || + CV_MAT_TYPE(mat->type) == CV_32FC2 ) + { + ptseq = cvPointSeqFromMat(CV_SEQ_KIND_GENERIC, mat, &contour_header, &block); + mat = 0; + } + else if( CV_MAT_TYPE(mat->type) != CV_8UC1 && + CV_MAT_TYPE(mat->type) != CV_8SC1 ) + CV_Error( cv::Error::StsUnsupportedFormat, + "The image/matrix format is not supported by the function" ); + update = 0; + calculate = 1; + } + + if( !calculate ) + return ((CvContour*)ptseq)->rect; + + if( mat ) + { + rect = cvRect(maskBoundingRect(cv::cvarrToMat(mat))); + } + else if( ptseq->total ) + { + cv::AutoBuffer abuf; + rect = cvRect(pointSetBoundingRect(cv::cvarrToMat(ptseq, false, false, 0, &abuf))); + } + if( update ) + ((CvContour*)ptseq)->rect = cvRect(rect); + return cvRect(rect); +} diff --git a/modules/imgproc/src/shapedescr.cpp b/modules/imgproc/src/shapedescr.cpp index 9be6038d9d..007bf9ac62 100644 --- a/modules/imgproc/src/shapedescr.cpp +++ b/modules/imgproc/src/shapedescr.cpp @@ -862,282 +862,6 @@ cv::RotatedRect cv::fitEllipseDirect( InputArray _points ) return box; } - -namespace cv -{ - -// Calculates bounding rectangle of a point set or retrieves already calculated -static Rect pointSetBoundingRect( const Mat& points ) -{ - int npoints = points.checkVector(2); - int depth = points.depth(); - CV_Assert(npoints >= 0 && (depth == CV_32F || depth == CV_32S)); - - int xmin = 0, ymin = 0, xmax = -1, ymax = -1, i; - bool is_float = depth == CV_32F; - - if( npoints == 0 ) - return Rect(); - -#if CV_SIMD // TODO: enable for CV_SIMD_SCALABLE, loop tail related. - const int64_t* pts = points.ptr(); - - if( !is_float ) - { - v_int32 minval, maxval; - minval = maxval = v_reinterpret_as_s32(vx_setall_s64(*pts)); //min[0]=pt.x, min[1]=pt.y, min[2]=pt.x, min[3]=pt.y - for( i = 1; i <= npoints - VTraits::vlanes()/2; i+= VTraits::vlanes()/2 ) - { - v_int32 ptXY2 = v_reinterpret_as_s32(vx_load(pts + i)); - minval = v_min(ptXY2, minval); - maxval = v_max(ptXY2, maxval); - } - minval = v_min(v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(minval))), v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(minval)))); - maxval = v_max(v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(maxval))), v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(maxval)))); - if( i <= npoints - VTraits::vlanes()/4 ) - { - v_int32 ptXY = v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(vx_load_low(pts + i)))); - minval = v_min(ptXY, minval); - maxval = v_max(ptXY, maxval); - i += VTraits::vlanes()/2; - } - for(int j = 16; j < VTraits::vlanes(); j*=2) - { - minval = v_min(v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(minval))), v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(minval)))); - maxval = v_max(v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(maxval))), v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(maxval)))); - } - xmin = v_get0(minval); - xmax = v_get0(maxval); - ymin = v_get0(v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(minval)))); - ymax = v_get0(v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(maxval)))); -#if CV_SIMD_WIDTH > 16 - if( i < npoints ) - { - v_int32x4 minval2, maxval2; - minval2 = maxval2 = v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(v_load_low(pts + i)))); - for( i++; i < npoints; i++ ) - { - v_int32x4 ptXY = v_reinterpret_as_s32(v_expand_low(v_reinterpret_as_u32(v_load_low(pts + i)))); - minval2 = v_min(ptXY, minval2); - maxval2 = v_max(ptXY, maxval2); - } - xmin = min(xmin, v_get0(minval2)); - xmax = max(xmax, v_get0(maxval2)); - ymin = min(ymin, v_get0(v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(minval2))))); - ymax = max(ymax, v_get0(v_reinterpret_as_s32(v_expand_high(v_reinterpret_as_u32(maxval2))))); - } -#endif // CV_SIMD - } - else - { - v_float32 minval, maxval; - minval = maxval = v_reinterpret_as_f32(vx_setall_s64(*pts)); //min[0]=pt.x, min[1]=pt.y, min[2]=pt.x, min[3]=pt.y - for( i = 1; i <= npoints - VTraits::vlanes()/2; i+= VTraits::vlanes()/2 ) - { - v_float32 ptXY2 = v_reinterpret_as_f32(vx_load(pts + i)); - minval = v_min(ptXY2, minval); - maxval = v_max(ptXY2, maxval); - } - minval = v_min(v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(minval))), v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(minval)))); - maxval = v_max(v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(maxval))), v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(maxval)))); - if( i <= npoints - VTraits::vlanes()/4 ) - { - v_float32 ptXY = v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(vx_load_low(pts + i)))); - minval = v_min(ptXY, minval); - maxval = v_max(ptXY, maxval); - i += VTraits::vlanes()/4; - } - for(int j = 16; j < VTraits::vlanes(); j*=2) - { - minval = v_min(v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(minval))), v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(minval)))); - maxval = v_max(v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(maxval))), v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(maxval)))); - } - xmin = cvFloor(v_get0(minval)); - xmax = cvFloor(v_get0(maxval)); - ymin = cvFloor(v_get0(v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(minval))))); - ymax = cvFloor(v_get0(v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(maxval))))); -#if CV_SIMD_WIDTH > 16 - if( i < npoints ) - { - v_float32x4 minval2, maxval2; - minval2 = maxval2 = v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(v_load_low(pts + i)))); - for( i++; i < npoints; i++ ) - { - v_float32x4 ptXY = v_reinterpret_as_f32(v_expand_low(v_reinterpret_as_u32(v_load_low(pts + i)))); - minval2 = v_min(ptXY, minval2); - maxval2 = v_max(ptXY, maxval2); - } - xmin = min(xmin, cvFloor(v_get0(minval2))); - xmax = max(xmax, cvFloor(v_get0(maxval2))); - ymin = min(ymin, cvFloor(v_get0(v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(minval2)))))); - ymax = max(ymax, cvFloor(v_get0(v_reinterpret_as_f32(v_expand_high(v_reinterpret_as_u32(maxval2)))))); - } -#endif - } -#else - const Point* pts = points.ptr(); - Point pt = pts[0]; - - if( !is_float ) - { - xmin = xmax = pt.x; - ymin = ymax = pt.y; - - for( i = 1; i < npoints; i++ ) - { - pt = pts[i]; - - if( xmin > pt.x ) - xmin = pt.x; - - if( xmax < pt.x ) - xmax = pt.x; - - if( ymin > pt.y ) - ymin = pt.y; - - if( ymax < pt.y ) - ymax = pt.y; - } - } - else - { - Cv32suf v; - // init values - xmin = xmax = CV_TOGGLE_FLT(pt.x); - ymin = ymax = CV_TOGGLE_FLT(pt.y); - - for( i = 1; i < npoints; i++ ) - { - pt = pts[i]; - pt.x = CV_TOGGLE_FLT(pt.x); - pt.y = CV_TOGGLE_FLT(pt.y); - - if( xmin > pt.x ) - xmin = pt.x; - - if( xmax < pt.x ) - xmax = pt.x; - - if( ymin > pt.y ) - ymin = pt.y; - - if( ymax < pt.y ) - ymax = pt.y; - } - - v.i = CV_TOGGLE_FLT(xmin); xmin = cvFloor(v.f); - v.i = CV_TOGGLE_FLT(ymin); ymin = cvFloor(v.f); - // because right and bottom sides of the bounding rectangle are not inclusive - // (note +1 in width and height calculation below), cvFloor is used here instead of cvCeil - v.i = CV_TOGGLE_FLT(xmax); xmax = cvFloor(v.f); - v.i = CV_TOGGLE_FLT(ymax); ymax = cvFloor(v.f); - } -#endif - - return Rect(xmin, ymin, xmax - xmin + 1, ymax - ymin + 1); -} - - -static Rect maskBoundingRect( const Mat& img ) -{ - CV_Assert( img.depth() <= CV_8S && img.channels() == 1 ); - - Size size = img.size(); - int xmin = size.width, ymin = -1, xmax = -1, ymax = -1, i, j, k; - - for( i = 0; i < size.height; i++ ) - { - const uchar* _ptr = img.ptr(i); - const uchar* ptr = (const uchar*)alignPtr(_ptr, 4); - int have_nz = 0, k_min, offset = (int)(ptr - _ptr); - j = 0; - offset = MIN(offset, size.width); - for( ; j < offset; j++ ) - if( _ptr[j] ) - { - if( j < xmin ) - xmin = j; - if( j > xmax ) - xmax = j; - have_nz = 1; - } - if( offset < size.width ) - { - xmin -= offset; - xmax -= offset; - size.width -= offset; - j = 0; - for( ; j <= xmin - 4; j += 4 ) - if( *((int*)(ptr+j)) ) - break; - for( ; j < xmin; j++ ) - if( ptr[j] ) - { - xmin = j; - if( j > xmax ) - xmax = j; - have_nz = 1; - break; - } - k_min = MAX(j-1, xmax); - k = size.width - 1; - for( ; k > k_min && (k&3) != 3; k-- ) - if( ptr[k] ) - break; - if( k > k_min && (k&3) == 3 ) - { - for( ; k > k_min+3; k -= 4 ) - if( *((int*)(ptr+k-3)) ) - break; - } - for( ; k > k_min; k-- ) - if( ptr[k] ) - { - xmax = k; - have_nz = 1; - break; - } - if( !have_nz ) - { - j &= ~3; - for( ; j <= k - 3; j += 4 ) - if( *((int*)(ptr+j)) ) - break; - for( ; j <= k; j++ ) - if( ptr[j] ) - { - have_nz = 1; - break; - } - } - xmin += offset; - xmax += offset; - size.width += offset; - } - if( have_nz ) - { - if( ymin < 0 ) - ymin = i; - ymax = i; - } - } - - if( xmin >= size.width ) - xmin = ymin = 0; - return Rect(xmin, ymin, xmax - xmin + 1, ymax - ymin + 1); -} - -} - -cv::Rect cv::boundingRect(InputArray array) -{ - CV_INSTRUMENT_REGION(); - - Mat m = array.getMat(); - return m.depth() <= CV_8U ? maskBoundingRect(m) : pointSetBoundingRect(m); -} - ////////////////////////////////////////////// C API /////////////////////////////////////////// CV_IMPL int @@ -1478,62 +1202,4 @@ cvFitEllipse2( const CvArr* array ) return cvBox2D(cv::fitEllipse(points)); } -/* Calculates bounding rectangle of a point set or retrieves already calculated */ -CV_IMPL CvRect -cvBoundingRect( CvArr* array, int update ) -{ - cv::Rect rect; - CvContour contour_header; - CvSeq* ptseq = 0; - CvSeqBlock block; - - CvMat stub, *mat = 0; - int calculate = update; - - if( CV_IS_SEQ( array )) - { - ptseq = (CvSeq*)array; - if( !CV_IS_SEQ_POINT_SET( ptseq )) - CV_Error( cv::Error::StsBadArg, "Unsupported sequence type" ); - - if( ptseq->header_size < (int)sizeof(CvContour)) - { - update = 0; - calculate = 1; - } - } - else - { - mat = cvGetMat( array, &stub ); - if( CV_MAT_TYPE(mat->type) == CV_32SC2 || - CV_MAT_TYPE(mat->type) == CV_32FC2 ) - { - ptseq = cvPointSeqFromMat(CV_SEQ_KIND_GENERIC, mat, &contour_header, &block); - mat = 0; - } - else if( CV_MAT_TYPE(mat->type) != CV_8UC1 && - CV_MAT_TYPE(mat->type) != CV_8SC1 ) - CV_Error( cv::Error::StsUnsupportedFormat, - "The image/matrix format is not supported by the function" ); - update = 0; - calculate = 1; - } - - if( !calculate ) - return ((CvContour*)ptseq)->rect; - - if( mat ) - { - rect = cvRect(cv::maskBoundingRect(cv::cvarrToMat(mat))); - } - else if( ptseq->total ) - { - cv::AutoBuffer abuf; - rect = cvRect(cv::pointSetBoundingRect(cv::cvarrToMat(ptseq, false, false, 0, &abuf))); - } - if( update ) - ((CvContour*)ptseq)->rect = cvRect(rect); - return cvRect(rect); -} - /* End of file. */ From c577b2440643bf98942cfd8c49478c545c3fa56b Mon Sep 17 00:00:00 2001 From: Kumataro Date: Fri, 19 Apr 2024 00:11:07 +0900 Subject: [PATCH 10/14] Merge pull request #25445 from Kumataro:fix25403 apps: createsamples: fix comment to remove last backslash #25445 Close #25403 ### 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 - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- apps/createsamples/utility.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/createsamples/utility.cpp b/apps/createsamples/utility.cpp index 198f4c2eb7..b57d3fcb81 100644 --- a/apps/createsamples/utility.cpp +++ b/apps/createsamples/utility.cpp @@ -1168,7 +1168,7 @@ void cvCreateTestSamples( const char* infoname, } else { - filename++; // character after last / or \ + filename++; // get basename after last path delimiter } count = MIN( count, cvbgdata->count ); From 4ef5986d4de9657ca6e86703d474d20789d739ca Mon Sep 17 00:00:00 2001 From: fengyuentau Date: Fri, 19 Apr 2024 14:24:26 +0800 Subject: [PATCH 11/14] remove manual unrolling that causes problem --- modules/core/src/matmul.simd.hpp | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/modules/core/src/matmul.simd.hpp b/modules/core/src/matmul.simd.hpp index 058666485a..fb0c6ddefe 100644 --- a/modules/core/src/matmul.simd.hpp +++ b/modules/core/src/matmul.simd.hpp @@ -394,19 +394,6 @@ GEMMSingleMul( const T* a_data, size_t a_step, { WT al(a_data[k]); j=0; - #if CV_ENABLE_UNROLLED - for(; j <= m - 4; j += 4 ) - { - WT t0 = d_buf[j] + WT(b_data[j])*al; - WT t1 = d_buf[j+1] + WT(b_data[j+1])*al; - d_buf[j] = t0; - d_buf[j+1] = t1; - t0 = d_buf[j+2] + WT(b_data[j+2])*al; - t1 = d_buf[j+3] + WT(b_data[j+3])*al; - d_buf[j+2] = t0; - d_buf[j+3] = t1; - } - #endif for( ; j < m; j++ ) d_buf[j] += WT(b_data[j])*al; } From 882f46e1d30c30db1b53d0eca4f188a7f8cc30a9 Mon Sep 17 00:00:00 2001 From: JunX Date: Fri, 19 Apr 2024 16:55:17 +0800 Subject: [PATCH 12/14] Merge pull request #25317 from junxnone:ipp_202110 Fix for IPP 2021.10 with OneAPI 2024 #25317 fixes #25270 ### 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 - [ ] 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 --- cmake/OpenCVFindIPP.cmake | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cmake/OpenCVFindIPP.cmake b/cmake/OpenCVFindIPP.cmake index 6bcd81d8b4..2328ef8b43 100644 --- a/cmake/OpenCVFindIPP.cmake +++ b/cmake/OpenCVFindIPP.cmake @@ -84,7 +84,7 @@ endmacro() # This macro uses IPP_ROOT_DIR variable # TODO Cleanup code after ICV package stabilization macro(ipp_detect_version) - set(IPP_INCLUDE_DIRS ${IPP_ROOT_DIR}/include) + get_filename_component(IPP_INCLUDE_DIRS ${IPP_VERSION_FILE} PATH) set(__msg) if(EXISTS ${IPP_ROOT_DIR}/include/ippicv_redefs.h) @@ -271,7 +271,9 @@ if(NOT DEFINED IPPROOT) endif() file(TO_CMAKE_PATH "${IPPROOT}" __IPPROOT) -if(EXISTS "${__IPPROOT}/include/ippversion.h") +file(GLOB_RECURSE IPP_VERSION_FILE "${__IPPROOT}/include/*ippversion.h") + +if(EXISTS ${IPP_VERSION_FILE}) set(IPP_ROOT_DIR ${__IPPROOT}) ipp_detect_version() endif() From fc5eb101bfcb16fa21e1f648f0b47f8a68fb4895 Mon Sep 17 00:00:00 2001 From: Vincent Rabaud Date: Fri, 19 Apr 2024 12:00:27 +0200 Subject: [PATCH 13/14] Merge pull request #25447 from vrabaud:tiff Remove unnecessary FIXIT section in grfmt_tiff.cpp #25447 No int64/uint64 is used in the code anymore. grfmt_tiff.hpp includes the tiff.h header inside of the tiff_dummy_namespace declaration. One implication of this is that all namespaced declarations made in tiff.h become qualified with tiff_dummy_namespace::. Because tiff.h includes standard library headers, the std namespace declarations are converted to tiff_dummy_namespace::std declarations. Subsequently, grfmt_tiff.hpp declares using namespace tiff_dummy_namespace;. This can lead to an ambiguity error during the resolution of the std namespace. ### 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 --- modules/imgcodecs/src/grfmt_tiff.cpp | 54 +++++++++++----------------- 1 file changed, 20 insertions(+), 34 deletions(-) diff --git a/modules/imgcodecs/src/grfmt_tiff.cpp b/modules/imgcodecs/src/grfmt_tiff.cpp index 3094bcc25c..3890df96bd 100644 --- a/modules/imgcodecs/src/grfmt_tiff.cpp +++ b/modules/imgcodecs/src/grfmt_tiff.cpp @@ -53,22 +53,8 @@ #include "grfmt_tiff.hpp" #include -// TODO FIXIT Conflict declarations for common types like int64/uint64 -namespace tiff_dummy_namespace { #include "tiff.h" #include "tiffio.h" -} -using namespace tiff_dummy_namespace; - -#ifndef _MSC_VER -namespace numeric_types = tiff_dummy_namespace; -#else -#include -namespace numeric_types { - using uint16 = std::uint16_t; - using uint32 = std::uint32_t; -} -#endif namespace cv { @@ -274,8 +260,8 @@ bool TiffDecoder::readHeader() if (tif) { - numeric_types::uint32 wdth = 0, hght = 0; - numeric_types::uint16 photometric = 0; + uint32_t wdth = 0, hght = 0; + uint16_t photometric = 0; CV_TIFF_CHECK_CALL(TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &wdth)); CV_TIFF_CHECK_CALL(TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &hght)); @@ -283,7 +269,7 @@ bool TiffDecoder::readHeader() { bool isGrayScale = photometric == PHOTOMETRIC_MINISWHITE || photometric == PHOTOMETRIC_MINISBLACK; - numeric_types::uint16 bpp = 8, ncn = isGrayScale ? 1 : 3; + uint16_t bpp = 8, ncn = isGrayScale ? 1 : 3; if (0 == TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bpp)) { // TIFF bi-level images don't require TIFFTAG_BITSPERSAMPLE tag @@ -306,7 +292,7 @@ bool TiffDecoder::readHeader() (ncn != 1 && ncn != 3 && ncn != 4))) bpp = 8; - numeric_types::uint16 sample_format = SAMPLEFORMAT_UINT; + uint16_t sample_format = SAMPLEFORMAT_UINT; TIFFGetField(tif, TIFFTAG_SAMPLEFORMAT, &sample_format); int wanted_channels = normalizeChannelsNumber(ncn); switch (bpp) @@ -388,7 +374,7 @@ bool TiffDecoder::nextPage() readHeader(); } -static void fixOrientationPartial(Mat &img, numeric_types::uint16 orientation) +static void fixOrientationPartial(Mat &img, uint16_t orientation) { switch(orientation) { case ORIENTATION_RIGHTTOP: @@ -444,7 +430,7 @@ static void fixOrientationFull(Mat &img, int orientation) * For 8 bit some corrections are done by TIFFReadRGBAStrip/Tile already. * Not so for 16/32/64 bit. */ -static void fixOrientation(Mat &img, numeric_types::uint16 orientation, bool isOrientationFull) +static void fixOrientation(Mat &img, uint16_t orientation, bool isOrientationFull) { if( isOrientationFull ) { @@ -605,7 +591,7 @@ bool TiffDecoder::readData( Mat& img ) CV_Assert(!m_tif.empty()); TIFF* tif = (TIFF*)m_tif.get(); - numeric_types::uint16 photometric = (numeric_types::uint16)-1; + uint16_t photometric = (uint16_t)-1; CV_TIFF_CHECK_CALL(TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric)); if (m_hdr && depth >= CV_32F) @@ -621,14 +607,14 @@ bool TiffDecoder::readData( Mat& img ) { int is_tiled = TIFFIsTiled(tif) != 0; bool isGrayScale = photometric == PHOTOMETRIC_MINISWHITE || photometric == PHOTOMETRIC_MINISBLACK; - numeric_types::uint16 bpp = 8, ncn = isGrayScale ? 1 : 3; + uint16_t bpp = 8, ncn = isGrayScale ? 1 : 3; if (0 == TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bpp)) { // TIFF bi-level images don't require TIFFTAG_BITSPERSAMPLE tag bpp = 1; } CV_TIFF_CHECK_CALL_DEBUG(TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &ncn)); - numeric_types::uint16 img_orientation = ORIENTATION_TOPLEFT; + uint16_t img_orientation = ORIENTATION_TOPLEFT; CV_TIFF_CHECK_CALL_DEBUG(TIFFGetField(tif, TIFFTAG_ORIENTATION, &img_orientation)); constexpr const int bitsPerByte = 8; int dst_bpp = (int)(img.elemSize1() * bitsPerByte); @@ -638,7 +624,7 @@ bool TiffDecoder::readData( Mat& img ) int wanted_channels = normalizeChannelsNumber(img.channels()); bool doReadScanline = false; - numeric_types::uint32 tile_width0 = m_width, tile_height0 = 0; + uint32_t tile_width0 = m_width, tile_height0 = 0; if (is_tiled) { @@ -656,7 +642,7 @@ bool TiffDecoder::readData( Mat& img ) tile_width0 = m_width; if (tile_height0 == 0 || - (!is_tiled && tile_height0 == std::numeric_limits::max()) ) + (!is_tiled && tile_height0 == std::numeric_limits::max()) ) tile_height0 = m_height; const int TILE_MAX_WIDTH = (1 << 24); @@ -681,7 +667,7 @@ bool TiffDecoder::readData( Mat& img ) ( (uint64_t) MAX_TILE_SIZE * 95 / 100) ) { - uint16_t planerConfig = (numeric_types::uint16)-1; + uint16_t planerConfig = (uint16_t)-1; CV_TIFF_CHECK_CALL(TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &planerConfig)); doReadScanline = (!is_tiled) // no tile @@ -737,7 +723,7 @@ bool TiffDecoder::readData( Mat& img ) MAX_TILE_SIZE * 95 / 100 ) { - uint16_t planerConfig = (numeric_types::uint16)-1; + uint16_t planerConfig = (uint16_t)-1; CV_TIFF_CHECK_CALL(TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &planerConfig)); doReadScanline = (!is_tiled) // no tile @@ -821,7 +807,7 @@ bool TiffDecoder::readData( Mat& img ) uchar* bstart = src_buffer; if (doReadScanline) { - CV_TIFF_CHECK_CALL((int)TIFFReadScanline(tif, (numeric_types::uint32*)src_buffer, y) >= 0); + CV_TIFF_CHECK_CALL((int)TIFFReadScanline(tif, (uint32_t*)src_buffer, y) >= 0); if ( isNeedConvert16to8 ) { @@ -843,11 +829,11 @@ bool TiffDecoder::readData( Mat& img ) } else if (!is_tiled) { - CV_TIFF_CHECK_CALL(TIFFReadRGBAStrip(tif, y, (numeric_types::uint32*)src_buffer)); + CV_TIFF_CHECK_CALL(TIFFReadRGBAStrip(tif, y, (uint32_t*)src_buffer)); } else { - CV_TIFF_CHECK_CALL(TIFFReadRGBATile(tif, x, y, (numeric_types::uint32*)src_buffer)); + CV_TIFF_CHECK_CALL(TIFFReadRGBATile(tif, x, y, (uint32_t*)src_buffer)); // Tiles fill the buffer from the bottom up bstart += (tile_height0 - tile_height) * tile_width0 * 4; } @@ -941,15 +927,15 @@ bool TiffDecoder::readData( Mat& img ) { if (doReadScanline) { - CV_TIFF_CHECK_CALL((int)TIFFReadScanline(tif, (numeric_types::uint32*)src_buffer, y) >= 0); + CV_TIFF_CHECK_CALL((int)TIFFReadScanline(tif, (uint32_t*)src_buffer, y) >= 0); } else if (!is_tiled) { - CV_TIFF_CHECK_CALL((int)TIFFReadEncodedStrip(tif, tileidx, (numeric_types::uint32*)src_buffer, src_buffer_size) >= 0); + CV_TIFF_CHECK_CALL((int)TIFFReadEncodedStrip(tif, tileidx, (uint32_t*)src_buffer, src_buffer_size) >= 0); } else { - CV_TIFF_CHECK_CALL((int)TIFFReadEncodedTile(tif, tileidx, (numeric_types::uint32*)src_buffer, src_buffer_size) >= 0); + CV_TIFF_CHECK_CALL((int)TIFFReadEncodedTile(tif, tileidx, (uint32_t*)src_buffer, src_buffer_size) >= 0); } for (int i = 0; i < tile_height; i++) @@ -1266,7 +1252,7 @@ bool TiffEncoder::writeLibTiff( const std::vector& img_vec, const std::vect int page_compression = compression; int bitsPerChannel = -1; - numeric_types::uint16 sample_format = SAMPLEFORMAT_INT; + uint16_t sample_format = SAMPLEFORMAT_INT; switch (depth) { case CV_8U: From fb2af90daacc0dc3123741fd6371f5aa943ee935 Mon Sep 17 00:00:00 2001 From: Laurent Berger Date: Fri, 19 Apr 2024 12:38:17 +0200 Subject: [PATCH 14/14] Merge pull request #25354 from LaurentBerger:uiname Add cv::currentUIFramework #25354 issue https://github.com/opencv/opencv/issues/25329 ### 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 - [ ] The PR is proposed to the proper branch - [x] 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 --- modules/highgui/include/opencv2/highgui.hpp | 9 +++++++ modules/highgui/src/backend.hpp | 1 + modules/highgui/src/window.cpp | 27 +++++++++++++++++++++ modules/highgui/src/window_gtk.cpp | 13 ++++++++++ modules/highgui/src/window_w32.cpp | 5 ++++ modules/highgui/test/test_gui.cpp | 19 +++++++++++++++ 6 files changed, 74 insertions(+) diff --git a/modules/highgui/include/opencv2/highgui.hpp b/modules/highgui/include/opencv2/highgui.hpp index 41ce7b6186..8175bd0871 100644 --- a/modules/highgui/include/opencv2/highgui.hpp +++ b/modules/highgui/include/opencv2/highgui.hpp @@ -285,6 +285,15 @@ The function destroyAllWindows destroys all of the opened HighGUI windows. */ CV_EXPORTS_W void destroyAllWindows(); + +/** @brief HighGUI backend used. + +The function returns HighGUI backend name used: could be COCOA, GTK2/3, QT, WAYLAND or WIN32. +Returns empty string if there is no available UI backend. + */ +CV_EXPORTS_W const std::string currentUIFramework(); + + CV_EXPORTS_W int startWindowThread(); /** @brief Similar to #waitKey, but returns full key code. diff --git a/modules/highgui/src/backend.hpp b/modules/highgui/src/backend.hpp index 7c32846ce4..93d51da119 100644 --- a/modules/highgui/src/backend.hpp +++ b/modules/highgui/src/backend.hpp @@ -106,6 +106,7 @@ public: virtual int waitKeyEx(int delay /*= 0*/) = 0; virtual int pollKey() = 0; + virtual const std::string getName() const = 0; }; std::shared_ptr& getCurrentUIBackend(); diff --git a/modules/highgui/src/window.cpp b/modules/highgui/src/window.cpp index 4bb6e9d880..a41e2313c8 100644 --- a/modules/highgui/src/window.cpp +++ b/modules/highgui/src/window.cpp @@ -1091,6 +1091,33 @@ void cv::imshow(const String& winname, const ogl::Texture2D& _tex) #endif } +const std::string cv::currentUIFramework() +{ + CV_TRACE_FUNCTION(); + + // plugin and backend-compatible implementations + auto backend = getCurrentUIBackend(); + if (backend) + { + return backend->getName(); + } + + // builtin backends +#if defined(HAVE_WIN32UI) + CV_Assert(false); // backend-compatible +#elif defined (HAVE_GTK) + CV_Assert(false); // backend-compatible +#elif defined (HAVE_QT) + return std::string("QT"); +#elif defined (HAVE_COCOA) + return std::string("COCOA"); +#elif defined (HAVE_WAYLAND) + return std::string("WAYLAND"); +#else + return std::string(); +#endif +} + // Without OpenGL #ifndef HAVE_OPENGL diff --git a/modules/highgui/src/window_gtk.cpp b/modules/highgui/src/window_gtk.cpp index c3fb853305..88421be8b8 100644 --- a/modules/highgui/src/window_gtk.cpp +++ b/modules/highgui/src/window_gtk.cpp @@ -2286,6 +2286,19 @@ public: { return cvWaitKey(1); // TODO } + + const std::string getName() const CV_OVERRIDE + { +#if GTK_MAJOR_VERSION == 2 + return "GTK2"; +#elif GTK_MAJOR_VERSION == 3 + return "GTK3"; +#elif GTK_MAJOR_VERSION == 4 + return "GTK4"; +#else +#error "Unsupported GTK version" +#endif + } }; // GTKBackendUI static diff --git a/modules/highgui/src/window_w32.cpp b/modules/highgui/src/window_w32.cpp index a693b1de90..98f876a34f 100644 --- a/modules/highgui/src/window_w32.cpp +++ b/modules/highgui/src/window_w32.cpp @@ -3004,6 +3004,11 @@ public: { return pollKey_W32(); } + + const std::string getName() const CV_OVERRIDE + { + return "WIN32"; + } }; // Win32BackendUI static diff --git a/modules/highgui/test/test_gui.cpp b/modules/highgui/test/test_gui.cpp index de40e80ede..8991e8072b 100644 --- a/modules/highgui/test/test_gui.cpp +++ b/modules/highgui/test/test_gui.cpp @@ -205,4 +205,23 @@ TEST(Highgui_GUI, trackbar) EXPECT_NO_THROW(destroyAllWindows()); } + +TEST(Highgui_GUI, currentUIFramework) +{ + auto framework = currentUIFramework(); + std::cout << "UI framework: \"" << framework << "\"" << std::endl; +#if (!defined(ENABLE_PLUGINS) \ + && !defined HAVE_GTK \ + && !defined HAVE_QT \ + && !defined HAVE_WIN32UI \ + && !defined HAVE_COCOA \ + && !defined HAVE_WAYLAND \ + ) + EXPECT_TRUE(framework.empty()); +#elif !defined(ENABLE_PLUGINS) + EXPECT_GT(framework.size(), 0); // builtin backends +#endif +} + + }} // namespace