From 056e761bbc8f334a1486e68ff380ae6161556691 Mon Sep 17 00:00:00 2001 From: kallaballa Date: Fri, 15 Aug 2025 01:17:54 +0200 Subject: [PATCH 01/21] added source comments to mark TSAN false positives. see: #27638 --- modules/core/src/ocl.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index 8479667fd7..7d3a13a855 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -3500,8 +3500,10 @@ struct Kernel::Impl void addUMat(const UMat& m, bool dst) { + // TSAN false positive: see #27638 CV_Assert(nu < MAX_ARRS && m.u && m.u->urefcount > 0); u[nu] = m.u; + // TSAN false positive: see #27638 CV_XADD(&m.u->urefcount, 1); nu++; if(dst && m.u->tempUMat()) @@ -5670,6 +5672,7 @@ public: if(!u) return; + // Next two lines: TSAN false positive: see #27638 CV_Assert(u->urefcount == 0); CV_Assert(u->refcount == 0 && "UMat deallocation error: some derived Mat is still alive"); @@ -6602,11 +6605,13 @@ public: void flushCleanupQueue() const { + // TSAN false positive: see #27638 if (!cleanupQueue.empty()) { std::deque q; { cv::AutoLock lock(cleanupQueueMutex); + // TSAN false positive: see #27638 q.swap(cleanupQueue); } for (std::deque::const_iterator i = q.begin(); i != q.end(); ++i) From f81240f57bf5be7817b4a47af8183e24d4eb5f26 Mon Sep 17 00:00:00 2001 From: kallaballa Date: Sat, 23 Aug 2025 19:48:04 +0200 Subject: [PATCH 02/21] stay on fast-path by using INTER_LINEAR resize when ALGO_HINT_APPROX is used --- modules/objdetect/src/hog.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/modules/objdetect/src/hog.cpp b/modules/objdetect/src/hog.cpp index b83263304f..1c7c8f73cb 100644 --- a/modules/objdetect/src/hog.cpp +++ b/modules/objdetect/src/hog.cpp @@ -1668,9 +1668,16 @@ public: Size sz(cvRound(img.cols/scale), cvRound(img.rows/scale)); Mat smallerImg(sz, img.type(), smallerImgBuf.ptr()); if( sz == img.size() ) + { smallerImg = Mat(sz, img.type(), img.data, img.step); + } else - resize(img, smallerImg, sz, 0, 0, INTER_LINEAR_EXACT); + { + if(getDefaultAlgorithmHint() == ALGO_HINT_APPROX) + resize(img, smallerImg, sz, 0, 0, INTER_LINEAR); + else + resize(img, smallerImg, sz, 0, 0, INTER_LINEAR_EXACT); + } hog->detect(smallerImg, locations, hitsWeights, hitThreshold, winStride, padding); Size scaledWinSize = Size(cvRound(hog->winSize.width*scale), cvRound(hog->winSize.height*scale)); From 6d889ee74c94124f6492eb8f0d50946d9c31d8e9 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Fri, 29 Aug 2025 13:16:22 +0300 Subject: [PATCH 03/21] Merge pull request #27717 from MaximSmolskiy:improve_fitellipsedirect_tests Improve fitEllipseDirect tests #27717 ### Pull Request Readiness Checklist Previous `fit_and_check_ellipse` implementation was very weak - it only checks that points center lies inside ellipse. Current implementation `fit_and_check_ellipse` checks that points RMS (Root Mean Square) algebraic distance is quite small. It means that on average points are near boundary of ellipse. Because for points on ellipse algebraic distance is equal to `0` and for points that are close to boundary of ellipse is quite small See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- modules/imgproc/test/test_fitellipse.cpp | 35 ++++++++++-------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/modules/imgproc/test/test_fitellipse.cpp b/modules/imgproc/test/test_fitellipse.cpp index cb3afea3d7..fff88212c5 100644 --- a/modules/imgproc/test/test_fitellipse.cpp +++ b/modules/imgproc/test/test_fitellipse.cpp @@ -8,31 +8,22 @@ namespace opencv_test { namespace { -// return true if point lies inside ellipse -static bool check_pt_in_ellipse(const Point2f& pt, const RotatedRect& el) { - Point2f to_pt = pt - el.center; - double el_angle = el.angle * CV_PI / 180; +static double algebraic_dist(const Point2f& pt, const RotatedRect& el) { + const Point2d to_pt = pt - el.center; + const double el_angle = el.angle * CV_PI / 180; const Point2d to_pt_el( to_pt.x * cos(-el_angle) - to_pt.y * sin(-el_angle), to_pt.x * sin(-el_angle) + to_pt.y * cos(-el_angle)); - const double pt_angle = atan2(to_pt_el.y / el.size.height, to_pt_el.x / el.size.width); - const double x_dist = 0.5 * el.size.width * cos(pt_angle); - const double y_dist = 0.5 * el.size.height * sin(pt_angle); - double el_dist = sqrt(x_dist * x_dist + y_dist * y_dist); - return cv::norm(to_pt) < el_dist; + return normL2Sqr(Point2d(2 * to_pt_el.x / el.size.width, 2 * to_pt_el.y / el.size.height)) - 1; } -// Return true if mass center of fitted points lies inside ellipse -static bool fit_and_check_ellipse(const vector& pts) { - RotatedRect ellipse = fitEllipseDirect(pts); // fitEllipseAMS() also works fine - - Point2f mass_center; - for (size_t i = 0; i < pts.size(); i++) { - mass_center += pts[i]; +static double rms_algebraic_dist(const vector& pts, const RotatedRect& el) { + double sum_algebraic_dists_sqr = 0; + for (const auto& pt : pts) { + const auto pt_algebraic_dist = algebraic_dist(pt, el); + sum_algebraic_dists_sqr += pt_algebraic_dist * pt_algebraic_dist; } - mass_center /= (float)pts.size(); - - return check_pt_in_ellipse(mass_center, ellipse); + return sqrt(sum_algebraic_dists_sqr / pts.size()); } TEST(Imgproc_FitEllipse_Issue_4515, accuracy) { @@ -50,7 +41,8 @@ TEST(Imgproc_FitEllipse_Issue_4515, accuracy) { pts.push_back(Point2f(333, 319)); pts.push_back(Point2f(333, 320)); - EXPECT_TRUE(fit_and_check_ellipse(pts)); + const RotatedRect ellipse = fitEllipseDirect(pts); // fitEllipseAMS() also works fine + EXPECT_LT(rms_algebraic_dist(pts, ellipse), 1e-1); } TEST(Imgproc_FitEllipse_Issue_6544, accuracy) { @@ -66,7 +58,8 @@ TEST(Imgproc_FitEllipse_Issue_6544, accuracy) { pts.push_back(Point2f(929.145f, 744.976f)); pts.push_back(Point2f(917.474f, 791.823f)); - EXPECT_TRUE(fit_and_check_ellipse(pts)); + const RotatedRect ellipse = fitEllipseDirect(pts); // fitEllipseAMS() also works fine + EXPECT_LT(rms_algebraic_dist(pts, ellipse), 5e-2); } TEST(Imgproc_FitEllipse_Issue_10270, accuracy) { From 518735b50921e4aa30eb2ed989632ca466bf6a7c Mon Sep 17 00:00:00 2001 From: MaximSmolskiy Date: Sat, 30 Aug 2025 00:42:33 +0300 Subject: [PATCH 04/21] Remove useless variables from fitEllipse tests --- modules/imgproc/test/test_fitellipse.cpp | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/modules/imgproc/test/test_fitellipse.cpp b/modules/imgproc/test/test_fitellipse.cpp index fff88212c5..215b318e26 100644 --- a/modules/imgproc/test/test_fitellipse.cpp +++ b/modules/imgproc/test/test_fitellipse.cpp @@ -64,13 +64,11 @@ TEST(Imgproc_FitEllipse_Issue_6544, accuracy) { TEST(Imgproc_FitEllipse_Issue_10270, accuracy) { vector pts; - float scale = 1; - Point2f shift(0, 0); - pts.push_back(Point2f(0, 1)*scale+shift); - pts.push_back(Point2f(0, 2)*scale+shift); - pts.push_back(Point2f(0, 3)*scale+shift); - pts.push_back(Point2f(2, 3)*scale+shift); - pts.push_back(Point2f(0, 4)*scale+shift); + pts.push_back(Point2f(0, 1)); + pts.push_back(Point2f(0, 2)); + pts.push_back(Point2f(0, 3)); + pts.push_back(Point2f(2, 3)); + pts.push_back(Point2f(0, 4)); // check that we get almost vertical ellipse centered around (1, 3) RotatedRect e = fitEllipse(pts); @@ -82,13 +80,11 @@ TEST(Imgproc_FitEllipse_Issue_10270, accuracy) { TEST(Imgproc_FitEllipse_JavaCase, accuracy) { vector pts; - float scale = 1; - Point2f shift(0, 0); - pts.push_back(Point2f(0, 0)*scale+shift); - pts.push_back(Point2f(1, 1)*scale+shift); - pts.push_back(Point2f(-1, 1)*scale+shift); - pts.push_back(Point2f(-1, -1)*scale+shift); - pts.push_back(Point2f(1, -1)*scale+shift); + pts.push_back(Point2f(0, 0)); + pts.push_back(Point2f(1, 1)); + pts.push_back(Point2f(-1, 1)); + pts.push_back(Point2f(-1, -1)); + pts.push_back(Point2f(1, -1)); // check that we get almost circle centered around (0, 0) RotatedRect e = fitEllipse(pts); From ca35ed2f1c4d7956f2a84d4543f1a9cb5188fb61 Mon Sep 17 00:00:00 2001 From: cudawarped <12133430+cudawarped@users.noreply.github.com> Date: Sat, 23 Aug 2025 09:24:05 +0300 Subject: [PATCH 05/21] cuda: add compatibility layer for depreciated vector types --- .../include/opencv2/core/cuda/cuda_compat.hpp | 38 +++++++++++++++++++ .../include/opencv2/core/cuda/vec_math.hpp | 3 ++ .../include/opencv2/core/cuda/vec_traits.hpp | 4 ++ modules/core/src/cuda/gpu_mat.cu | 8 ++-- modules/dnn/src/cuda/vector_traits.hpp | 5 ++- 5 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 modules/core/include/opencv2/core/cuda/cuda_compat.hpp diff --git a/modules/core/include/opencv2/core/cuda/cuda_compat.hpp b/modules/core/include/opencv2/core/cuda/cuda_compat.hpp new file mode 100644 index 0000000000..b40b2ea4f9 --- /dev/null +++ b/modules/core/include/opencv2/core/cuda/cuda_compat.hpp @@ -0,0 +1,38 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + +#ifndef OPENCV_CUDA_CUDA_COMPAT_HPP +#define OPENCV_CUDA_CUDA_COMPAT_HPP + +#include + +namespace cv { namespace cuda { namespace device { namespace compat +{ +#if CUDA_VERSION >= 13000 + using ulonglong4 = ::ulonglong4_16a; + using double4 = ::double4_16a; + __host__ __device__ __forceinline__ + double4 make_double4(double x, double y, double z, double w) + { + return ::make_double4_16a(x, y, z, w); + } +#else + using ulonglong4 = ::ulonglong4; + using double4 = ::double4; + __host__ __device__ __forceinline__ + double4 make_double4(double x, double y, double z, double w) + { + return ::make_double4(x, y, z, w); + } +#endif + using ulonglong4Compat = ulonglong4; + using double4Compat = double4; + __host__ __device__ __forceinline__ + double4Compat make_double4_compat(double x, double y, double z, double w) + { + return make_double4(x, y, z, w); + } +}}}} + +#endif // OPENCV_CUDA_CUDA_COMPAT_HPP \ No newline at end of file diff --git a/modules/core/include/opencv2/core/cuda/vec_math.hpp b/modules/core/include/opencv2/core/cuda/vec_math.hpp index 80b1303681..afb8cc0c4c 100644 --- a/modules/core/include/opencv2/core/cuda/vec_math.hpp +++ b/modules/core/include/opencv2/core/cuda/vec_math.hpp @@ -45,6 +45,7 @@ #include "vec_traits.hpp" #include "saturate_cast.hpp" +#include "cuda_compat.hpp" /** @file * @deprecated Use @ref cudev instead. @@ -54,6 +55,8 @@ namespace cv { namespace cuda { namespace device { + using cv::cuda::device::compat::double4; + using cv::cuda::device::compat::make_double4; // saturate_cast diff --git a/modules/core/include/opencv2/core/cuda/vec_traits.hpp b/modules/core/include/opencv2/core/cuda/vec_traits.hpp index b5ff281a0b..786a9314a7 100644 --- a/modules/core/include/opencv2/core/cuda/vec_traits.hpp +++ b/modules/core/include/opencv2/core/cuda/vec_traits.hpp @@ -44,6 +44,7 @@ #define OPENCV_CUDA_VEC_TRAITS_HPP #include "common.hpp" +#include "cuda_compat.hpp" /** @file * @deprecated Use @ref cudev instead. @@ -53,6 +54,9 @@ namespace cv { namespace cuda { namespace device { + using cv::cuda::device::compat::double4; + using cv::cuda::device::compat::make_double4; + template struct TypeVec; struct __align__(8) uchar8 diff --git a/modules/core/src/cuda/gpu_mat.cu b/modules/core/src/cuda/gpu_mat.cu index b6f95445db..c70b9fc96f 100644 --- a/modules/core/src/cuda/gpu_mat.cu +++ b/modules/core/src/cuda/gpu_mat.cu @@ -51,10 +51,12 @@ #include "opencv2/core/cuda.hpp" #include "opencv2/cudev.hpp" #include "opencv2/core/cuda/utility.hpp" +#include "opencv2/core/cuda/cuda_compat.hpp" using namespace cv; using namespace cv::cuda; using namespace cv::cudev; +using cv::cuda::device::compat::double4Compat; device::ThrustAllocator::~ThrustAllocator() { @@ -341,7 +343,7 @@ void cv::cuda::GpuMat::copyTo(OutputArray _dst, InputArray _mask, Stream& stream {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, - {copyWithMask, copyWithMask, copyWithMask, copyWithMask} + {copyWithMask, copyWithMask, copyWithMask, copyWithMask} }; if (mask.channels() == channels()) @@ -424,7 +426,7 @@ GpuMat& cv::cuda::GpuMat::setTo(Scalar value, Stream& stream) {setToWithOutMask,setToWithOutMask,setToWithOutMask,setToWithOutMask}, {setToWithOutMask,setToWithOutMask,setToWithOutMask,setToWithOutMask}, {setToWithOutMask,setToWithOutMask,setToWithOutMask,setToWithOutMask}, - {setToWithOutMask,setToWithOutMask,setToWithOutMask,setToWithOutMask} + {setToWithOutMask,setToWithOutMask,setToWithOutMask,setToWithOutMask} }; funcs[depth()][channels() - 1](*this, value, stream); @@ -455,7 +457,7 @@ GpuMat& cv::cuda::GpuMat::setTo(Scalar value, InputArray _mask, Stream& stream) {setToWithMask,setToWithMask,setToWithMask,setToWithMask}, {setToWithMask,setToWithMask,setToWithMask,setToWithMask}, {setToWithMask,setToWithMask,setToWithMask,setToWithMask}, - {setToWithMask,setToWithMask,setToWithMask,setToWithMask} + {setToWithMask,setToWithMask,setToWithMask,setToWithMask} }; funcs[depth()][channels() - 1](*this, mask, value, stream); diff --git a/modules/dnn/src/cuda/vector_traits.hpp b/modules/dnn/src/cuda/vector_traits.hpp index 1b9b76980c..d7d2214035 100644 --- a/modules/dnn/src/cuda/vector_traits.hpp +++ b/modules/dnn/src/cuda/vector_traits.hpp @@ -11,6 +11,7 @@ #include "memory.hpp" #include "../cuda4dnn/csl/pointer.hpp" +#include "opencv2/core/cuda/cuda_compat.hpp" #include @@ -34,9 +35,11 @@ namespace cv { namespace dnn { namespace cuda4dnn { namespace csl { namespace de * v_store(output_vPtr, vec); */ + using cv::cuda::device::compat::ulonglong4Compat; + namespace detail { template struct raw_type_ { }; - template <> struct raw_type_<256> { typedef ulonglong4 type; }; + template <> struct raw_type_<256> { typedef ulonglong4Compat type; }; template <> struct raw_type_<128> { typedef uint4 type; }; template <> struct raw_type_<64> { typedef uint2 type; }; template <> struct raw_type_<32> { typedef uint1 type; }; From a56877a016a69f752b3e711b476f524872f3ece7 Mon Sep 17 00:00:00 2001 From: cudawarped <12133430+cudawarped@users.noreply.github.com> Date: Mon, 1 Sep 2025 16:43:04 +0300 Subject: [PATCH 06/21] Silence unreferenced function with internal linkage has been removed warnings on windows e.g. contrib\modules\cudev\include\opencv2\cudev/ptr2d/warping.hpp(86): warning C4505: 'cv::cudev::affineMap': unreferenced function with internal linkage has been removed contrib\modules\cudev\include\opencv2\cudev/ptr2d/warping.hpp(134): warning C4505: 'cv::cudev::perspectiveMap': unreferenced function with internal linkage has been removed --- cmake/OpenCVDetectCUDAUtils.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/OpenCVDetectCUDAUtils.cmake b/cmake/OpenCVDetectCUDAUtils.cmake index b993be8894..fdd65ef6c3 100644 --- a/cmake/OpenCVDetectCUDAUtils.cmake +++ b/cmake/OpenCVDetectCUDAUtils.cmake @@ -390,6 +390,7 @@ macro(ocv_nvcc_flags) endif() if(WIN32) + set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} -Xcompiler=/wd4505) if (NOT (CUDA_VERSION VERSION_LESS "11.2")) set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} -Xcudafe --display_error_number --diag-suppress 1394,1388) endif() From e41ce4dbf46a8dbee54069b46ee7bf58851721b6 Mon Sep 17 00:00:00 2001 From: Arsenii Rzhevskii Date: Tue, 2 Sep 2025 17:22:52 +0200 Subject: [PATCH 07/21] Fix memory leaks in pybindings --- modules/python/src2/cv2_convert.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/modules/python/src2/cv2_convert.cpp b/modules/python/src2/cv2_convert.cpp index 0626e42e53..577c079dcd 100644 --- a/modules/python/src2/cv2_convert.cpp +++ b/modules/python/src2/cv2_convert.cpp @@ -267,10 +267,12 @@ bool pyopencv_to(PyObject* o, Mat& m, const ArgInfo& info) const int sz2 = 4; // Scalar has 4 elements. m = Mat::zeros(sz2, 1, CV_64F); + // Fill the Mat with array elements + bool filled = true; const char *base_ptr = PyArray_BYTES(oarr); - for(int i = 0; i < sz; i++ ) + for(int i = 0; i < sz && filled; i++ ) { - PyObject* oi = PyArray_GETITEM(oarr, base_ptr + step[0] * i); + PyObject* oi = PyArray_GETITEM(oarr, base_ptr + step[0] * i); // new object if( PyInt_Check(oi) ) m.at(i) = (double)PyInt_AsLong(oi); else if( PyFloat_Check(oi) ) @@ -279,10 +281,16 @@ bool pyopencv_to(PyObject* o, Mat& m, const ArgInfo& info) { failmsg("%s has some non-numerical elements", info.name); m.release(); - return false; + filled = false; } + + Py_DECREF(oi); } - return true; + + if(needcopy) + Py_DECREF(o); + + return filled; } // handle degenerate case From f51f2f67974643d0adf4d13a8c01a39e5b37debd Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Wed, 3 Sep 2025 16:43:18 +0300 Subject: [PATCH 08/21] Build fix for Clang 21. --- modules/dnn/src/layers/pooling_layer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/dnn/src/layers/pooling_layer.cpp b/modules/dnn/src/layers/pooling_layer.cpp index fbf075f7d3..1b892bee6e 100644 --- a/modules/dnn/src/layers/pooling_layer.cpp +++ b/modules/dnn/src/layers/pooling_layer.cpp @@ -1185,7 +1185,7 @@ public: PoolingInvoker::run(src, rois, dst, mask, kernel_size, strides, pads_begin, pads_end, avePoolPaddedArea, type, spatialScale, computeMaxIdx, nstripes); } - virtual Ptr initMaxPoolingHalide(const std::vector > &inputs) + Ptr initMaxPoolingHalide(const std::vector > &inputs) { #ifdef HAVE_HALIDE Halide::Buffer inputBuffer = halideBuffer(inputs[0]); @@ -1242,7 +1242,7 @@ public: return Ptr(); } - virtual Ptr initAvePoolingHalide(const std::vector > &inputs) + Ptr initAvePoolingHalide(const std::vector > &inputs) { #ifdef HAVE_HALIDE Halide::Buffer inputBuffer = halideBuffer(inputs[0]); From 92e2c67896d9a4124f7a00be023b007a922cf206 Mon Sep 17 00:00:00 2001 From: nina16448 Date: Fri, 5 Sep 2025 01:00:28 +0800 Subject: [PATCH 09/21] fix typos --- modules/videoio/doc/videoio_overview.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/videoio/doc/videoio_overview.markdown b/modules/videoio/doc/videoio_overview.markdown index 8dcc923efb..73adbff7c8 100644 --- a/modules/videoio/doc/videoio_overview.markdown +++ b/modules/videoio/doc/videoio_overview.markdown @@ -81,7 +81,7 @@ Use 3rd party drivers or cameras Many industrial cameras or some video I/O devices don't provide standard driver interfaces for the operating system. Thus you can't use VideoCapture or VideoWriter with these devices. -To get access to their devices, manufactures provide their own C++ API and library that you have to +To get access to their devices, manufacturers provide their own C++ API and library that you have to include and link with your OpenCV application. It is a common case that these libraries read/write images from/to a memory buffer. If so, it is possible to make a `Mat` header for memory buffer (user-allocated data) and process it From 443d0ae63fad6dfd8c485d609203db16c8bd0ec3 Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Mon, 8 Sep 2025 08:52:56 +0300 Subject: [PATCH 10/21] Merge pull request #27746 from dkurt:d.kurtaev/av_packet_side_data_get fix: FFmpeg 8.0 support #27746 ### Pull Request Readiness Checklist related comment: https://github.com/opencv/opencv/pull/27691#discussion_r2322695640 See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake --- modules/videoio/src/cap_ffmpeg_impl.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/videoio/src/cap_ffmpeg_impl.hpp b/modules/videoio/src/cap_ffmpeg_impl.hpp index 5780b4c113..d971ca75b3 100644 --- a/modules/videoio/src/cap_ffmpeg_impl.hpp +++ b/modules/videoio/src/cap_ffmpeg_impl.hpp @@ -2017,7 +2017,10 @@ void CvCapture_FFMPEG::get_rotation_angle() if (sd && nb_sd > 0) { const AVPacketSideData* mtx = av_packet_side_data_get(sd, nb_sd, AV_PKT_DATA_DISPLAYMATRIX); - data = mtx->data; + if (mtx) + { + data = mtx->data; + } } # endif if (data) From 65cb3fd86c751594866e9d7a9003e39a17f1bdaf Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Mon, 8 Sep 2025 09:49:26 +0300 Subject: [PATCH 11/21] Merge pull request #27741 from dkurt:libpng_1.6.45 libpng upgrade to 1.6.45 and cICP metadata support for PNG imwrite #27741 ### Pull Request Readiness Checklist resolves #24185 libpng docs: https://www.w3.org/TR/png-3/#cICP-chunk similar code from ffmpeg: https://github.com/FFmpeg/FFmpeg/blob/a700f0f72d1f073e5adcfbb16f4633850b0ef51c/libavcodec/pngenc.c#L452-L456 So issue #24185 can be solved by replacing `cv.imwrite` in user's code to `cv.imwriteWithMetadata`: ```python cv.imwriteWithMetadata("frame.png", frame, [cv.IMAGE_METADATA_CICP], np.array([[9, 18, 0, 1]], np.uint8)) ``` ``` $ exiftool /home/d.kurtaev/opencv_build/frames_pr/image_38.png ExifTool Version Number : 12.76 File Name : image_38.png Directory : /home/d.kurtaev/opencv_build/frames_pr File Size : 3.8 MB File Modification Date/Time : 2025:09:02 20:48:22+03:00 File Access Date/Time : 2025:09:02 20:48:22+03:00 File Inode Change Date/Time : 2025:09:02 20:48:22+03:00 File Permissions : -rw-r--r-- File Type : PNG File Type Extension : png MIME Type : image/png Image Width : 1080 Image Height : 1920 Bit Depth : 8 Color Type : RGB Compression : Deflate/Inflate Filter : Adaptive Interlace : Noninterlaced Color Primaries : BT.2020, BT.2100 Transfer Characteristics : BT.2100 HLG, ARIB STD-B67 Matrix Coefficients : Identity matrix Video Full Range Flag : 1 Image Size : 1080x1920 Megapixels : 2.1 ``` 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 --- 3rdparty/libpng/CHANGES | 33 +++ 3rdparty/libpng/LICENSE | 4 +- 3rdparty/libpng/README | 4 +- 3rdparty/libpng/arm/arm_init.c | 1 - 3rdparty/libpng/arm/filter_neon.S | 267 +++-------------- 3rdparty/libpng/arm/filter_neon_intrinsics.c | 1 - 3rdparty/libpng/arm/palette_neon_intrinsics.c | 3 +- .../libpng/intel/filter_sse2_intrinsics.c | 1 - 3rdparty/libpng/intel/intel_init.c | 1 - 3rdparty/libpng/mips/filter_msa_intrinsics.c | 45 ++- 3rdparty/libpng/mips/mips_init.c | 1 - 3rdparty/libpng/png.c | 268 ++++++++++++------ 3rdparty/libpng/png.h | 47 +-- 3rdparty/libpng/pngconf.h | 11 +- 3rdparty/libpng/pngdebug.h | 1 - 3rdparty/libpng/pngerror.c | 10 +- 3rdparty/libpng/pngget.c | 26 +- 3rdparty/libpng/pnginfo.h | 9 +- 3rdparty/libpng/pnglibconf.h | 12 +- 3rdparty/libpng/pngmem.c | 1 - 3rdparty/libpng/pngpread.c | 45 +-- 3rdparty/libpng/pngpriv.h | 54 +--- 3rdparty/libpng/pngread.c | 13 +- 3rdparty/libpng/pngrio.c | 1 - 3rdparty/libpng/pngrtran.c | 1 - 3rdparty/libpng/pngrutil.c | 89 +++--- 3rdparty/libpng/pngset.c | 30 +- 3rdparty/libpng/pngstruct.h | 1 - 3rdparty/libpng/pngtrans.c | 1 - 3rdparty/libpng/pngwio.c | 1 - 3rdparty/libpng/pngwrite.c | 85 ++++-- 3rdparty/libpng/pngwtran.c | 1 - 3rdparty/libpng/pngwutil.c | 82 +++--- 3rdparty/libpng/powerpc/powerpc_init.c | 1 - .../imgcodecs/include/opencv2/imgcodecs.hpp | 3 +- modules/imgcodecs/src/grfmt_png.cpp | 11 + modules/videoio/src/cap_ffmpeg_impl.hpp | 15 +- 37 files changed, 615 insertions(+), 565 deletions(-) diff --git a/3rdparty/libpng/CHANGES b/3rdparty/libpng/CHANGES index 441b57ecf1..3f37f3f393 100644 --- a/3rdparty/libpng/CHANGES +++ b/3rdparty/libpng/CHANGES @@ -6196,6 +6196,39 @@ Version 1.6.43 [February 23, 2024] consistency verification and text linting. Added version consistency verification to pngtest.c also. +Version 1.6.44 [September 12, 2024] + Hardened calculations in chroma handling to prevent overflows, and + relaxed a constraint in cHRM validation to accomodate the standard + ACES AP1 set of color primaries. + (Contributed by John Bowler) + Removed the ASM implementation of ARM Neon optimizations and updated + the build accordingly. Only the remaining C implementation shall be + used from now on, thus ensuring the support of the PAC/BTI security + features on ARM64. + (Contributed by Ross Burton and John Bowler) + Fixed the pickup of the PNG_HARDWARE_OPTIMIZATIONS option in the + CMake build on FreeBSD/amd64. This is an important performance fix + on this platform. + Applied various fixes and improvements to the CMake build. + (Contributed by Eric Riff, Benjamin Buch and Erik Scholz) + Added fuzzing targets for the simplified read API. + (Contributed by Mikhail Khachayants) + Fixed a build error involving pngtest.c under a custom config. + This was a regression introduced in a code cleanup in libpng-1.6.43. + (Contributed by Ben Wagner) + Fixed and improved the config files for AppVeyor CI and Travis CI. + +Version 1.6.45 [January 7, 2025] + Added support for the cICP chunk. + (Contributed by Lucas Chollet and John Bowler) + Adjusted and improved various checks in colorspace calculations. + (Contributed by John Bowler) + Rearranged the write order of colorspace chunks for better conformance + with the PNG v3 draft specification. + (Contributed by John Bowler) + Raised the minimum required CMake version from 3.6 to 3.14. + Forked off a development branch for libpng version 1.8. + Send comments/corrections/commendations to png-mng-implement at lists.sf.net. Subscription is required; visit https://lists.sourceforge.net/lists/listinfo/png-mng-implement diff --git a/3rdparty/libpng/LICENSE b/3rdparty/libpng/LICENSE index 25f298f0fc..ea6df986cb 100644 --- a/3rdparty/libpng/LICENSE +++ b/3rdparty/libpng/LICENSE @@ -4,8 +4,8 @@ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE PNG Reference Library License version 2 --------------------------------------- - * Copyright (c) 1995-2024 The PNG Reference Library Authors. - * Copyright (c) 2018-2024 Cosmin Truta. + * Copyright (c) 1995-2025 The PNG Reference Library Authors. + * Copyright (c) 2018-2025 Cosmin Truta. * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson. * Copyright (c) 1996-1997 Andreas Dilger. * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. diff --git a/3rdparty/libpng/README b/3rdparty/libpng/README index a6ca3ae9f9..1f73eb58cf 100644 --- a/3rdparty/libpng/README +++ b/3rdparty/libpng/README @@ -1,4 +1,4 @@ -README for libpng version 1.6.43 +README for libpng version 1.6.45 ================================ See the note about version numbers near the top of `png.h`. @@ -157,8 +157,6 @@ Files included in this distribution "PNG: The Definitive Guide" by Greg Roelofs, O'Reilly, 1999 libtests/ => Test programs - oss-fuzz/ => Files used by the OSS-Fuzz project for fuzz-testing - libpng pngexif/ => Program to inspect the EXIF information in PNG files pngminim/ => Minimal decoder, encoder, and progressive decoder programs demonstrating the use of pngusr.dfa diff --git a/3rdparty/libpng/arm/arm_init.c b/3rdparty/libpng/arm/arm_init.c index 84d05556f8..50376081a3 100644 --- a/3rdparty/libpng/arm/arm_init.c +++ b/3rdparty/libpng/arm/arm_init.c @@ -1,4 +1,3 @@ - /* arm_init.c - NEON optimised filter functions * * Copyright (c) 2018-2022 Cosmin Truta diff --git a/3rdparty/libpng/arm/filter_neon.S b/3rdparty/libpng/arm/filter_neon.S index 2308aad13e..0cbd372cb1 100644 --- a/3rdparty/libpng/arm/filter_neon.S +++ b/3rdparty/libpng/arm/filter_neon.S @@ -1,253 +1,60 @@ - -/* filter_neon.S - NEON optimised filter functions +/* filter_neon.S - placeholder file * - * Copyright (c) 2018 Cosmin Truta - * Copyright (c) 2014,2017 Glenn Randers-Pehrson - * Written by Mans Rullgard, 2011. + * Copyright (c) 2024 Cosmin Truta * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer * and license in png.h */ +/* IMPORTANT NOTE: + * + * Historically, the hand-coded assembler implementation of Neon optimizations + * in this module had not been in sync with the intrinsics-based implementation + * in filter_neon_intrinsics.c and palette_neon_intrinsics.c, at least since + * the introduction of riffled palette optimizations. Moreover, the assembler + * code used to work on 32-bit ARM only, and it caused problems, even if empty, + * on 64-bit ARM. + * + * All references to this module from our internal build scripts and projects + * have been removed. + * + * For the external projects that might still expect this module to be present, + * we leave this stub in place, for the remaining lifetime of libpng-1.6.x. + * Everything should continue to function normally, as long as there are no + * deliberate attempts to use the old hand-made assembler code. A build error + * will be raised otherwise. + */ + /* This is required to get the symbol renames, which are #defines, and the * definitions (or not) of PNG_ARM_NEON_OPT and PNG_ARM_NEON_IMPLEMENTATION. */ #define PNG_VERSION_INFO_ONLY #include "../pngpriv.h" -#if (defined(__linux__) || defined(__FreeBSD__)) && defined(__ELF__) -.section .note.GNU-stack,"",%progbits /* mark stack as non-executable */ -#endif - #ifdef PNG_READ_SUPPORTED - -/* Assembler NEON support - only works for 32-bit ARM (i.e. it does not work for - * ARM64). The code in arm/filter_neon_intrinsics.c supports ARM64, however it - * only works if -mfpu=neon is specified on the GCC command line. See pngpriv.h - * for the logic which sets PNG_USE_ARM_NEON_ASM: - */ #if PNG_ARM_NEON_IMPLEMENTATION == 2 /* hand-coded assembler */ - #if PNG_ARM_NEON_OPT > 0 -#ifdef __ELF__ -# define ELF +#if defined(__clang__) +#define GNUC_VERSION 0 /* not gcc, although it might pretend to be */ +#elif defined(__GNUC__) +#define GNUC_MAJOR (__GNUC__ + 0) +#define GNUC_MINOR (__GNUC_MINOR__ + 0) +#define GNUC_PATCHLEVEL (__GNUC_PATCHLEVEL__ + 0) +#define GNUC_VERSION (GNUC_MAJOR * 10000 + GNUC_MINOR * 100 + GNUC_PATCHLEVEL) #else -# define ELF @ +#define GNUC_VERSION 0 /* not gcc */ #endif - .arch armv7-a - .fpu neon +#if (GNUC_VERSION > 0) && (GNUC_VERSION < 40300) +#error "PNG_ARM_NEON is not supported with gcc versions earlier than 4.3.0" +#elif GNUC_VERSION == 40504 +#error "PNG_ARM_NEON is not supported with gcc version 4.5.4" +#else +#error "Please use 'arm/*_neon_intrinsics.c' for PNG_ARM_NEON support" +#endif -.macro func name, export=0 - .macro endfunc -ELF .size \name, . - \name - .endfunc - .purgem endfunc - .endm - .text - - /* Explicitly specifying alignment here because some versions of - * GAS don't align code correctly. This is harmless in correctly - * written versions of GAS. - */ - .align 2 - - .if \export - .global \name - .endif -ELF .type \name, STT_FUNC - .func \name -\name: -.endm - -func png_read_filter_row_sub4_neon, export=1 - ldr r3, [r0, #4] @ rowbytes - vmov.i8 d3, #0 -1: - vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128] - vadd.u8 d0, d3, d4 - vadd.u8 d1, d0, d5 - vadd.u8 d2, d1, d6 - vadd.u8 d3, d2, d7 - vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]! - subs r3, r3, #16 - bgt 1b - - bx lr -endfunc - -func png_read_filter_row_sub3_neon, export=1 - ldr r3, [r0, #4] @ rowbytes - vmov.i8 d3, #0 - mov r0, r1 - mov r2, #3 - mov r12, #12 - vld1.8 {q11}, [r0], r12 -1: - vext.8 d5, d22, d23, #3 - vadd.u8 d0, d3, d22 - vext.8 d6, d22, d23, #6 - vadd.u8 d1, d0, d5 - vext.8 d7, d23, d23, #1 - vld1.8 {q11}, [r0], r12 - vst1.32 {d0[0]}, [r1,:32], r2 - vadd.u8 d2, d1, d6 - vst1.32 {d1[0]}, [r1], r2 - vadd.u8 d3, d2, d7 - vst1.32 {d2[0]}, [r1], r2 - vst1.32 {d3[0]}, [r1], r2 - subs r3, r3, #12 - bgt 1b - - bx lr -endfunc - -func png_read_filter_row_up_neon, export=1 - ldr r3, [r0, #4] @ rowbytes -1: - vld1.8 {q0}, [r1,:128] - vld1.8 {q1}, [r2,:128]! - vadd.u8 q0, q0, q1 - vst1.8 {q0}, [r1,:128]! - subs r3, r3, #16 - bgt 1b - - bx lr -endfunc - -func png_read_filter_row_avg4_neon, export=1 - ldr r12, [r0, #4] @ rowbytes - vmov.i8 d3, #0 -1: - vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128] - vld4.32 {d16[],d17[],d18[],d19[]},[r2,:128]! - vhadd.u8 d0, d3, d16 - vadd.u8 d0, d0, d4 - vhadd.u8 d1, d0, d17 - vadd.u8 d1, d1, d5 - vhadd.u8 d2, d1, d18 - vadd.u8 d2, d2, d6 - vhadd.u8 d3, d2, d19 - vadd.u8 d3, d3, d7 - vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]! - subs r12, r12, #16 - bgt 1b - - bx lr -endfunc - -func png_read_filter_row_avg3_neon, export=1 - push {r4,lr} - ldr r12, [r0, #4] @ rowbytes - vmov.i8 d3, #0 - mov r0, r1 - mov r4, #3 - mov lr, #12 - vld1.8 {q11}, [r0], lr -1: - vld1.8 {q10}, [r2], lr - vext.8 d5, d22, d23, #3 - vhadd.u8 d0, d3, d20 - vext.8 d17, d20, d21, #3 - vadd.u8 d0, d0, d22 - vext.8 d6, d22, d23, #6 - vhadd.u8 d1, d0, d17 - vext.8 d18, d20, d21, #6 - vadd.u8 d1, d1, d5 - vext.8 d7, d23, d23, #1 - vld1.8 {q11}, [r0], lr - vst1.32 {d0[0]}, [r1,:32], r4 - vhadd.u8 d2, d1, d18 - vst1.32 {d1[0]}, [r1], r4 - vext.8 d19, d21, d21, #1 - vadd.u8 d2, d2, d6 - vhadd.u8 d3, d2, d19 - vst1.32 {d2[0]}, [r1], r4 - vadd.u8 d3, d3, d7 - vst1.32 {d3[0]}, [r1], r4 - subs r12, r12, #12 - bgt 1b - - pop {r4,pc} -endfunc - -.macro paeth rx, ra, rb, rc - vaddl.u8 q12, \ra, \rb @ a + b - vaddl.u8 q15, \rc, \rc @ 2*c - vabdl.u8 q13, \rb, \rc @ pa - vabdl.u8 q14, \ra, \rc @ pb - vabd.u16 q15, q12, q15 @ pc - vcle.u16 q12, q13, q14 @ pa <= pb - vcle.u16 q13, q13, q15 @ pa <= pc - vcle.u16 q14, q14, q15 @ pb <= pc - vand q12, q12, q13 @ pa <= pb && pa <= pc - vmovn.u16 d28, q14 - vmovn.u16 \rx, q12 - vbsl d28, \rb, \rc - vbsl \rx, \ra, d28 -.endm - -func png_read_filter_row_paeth4_neon, export=1 - ldr r12, [r0, #4] @ rowbytes - vmov.i8 d3, #0 - vmov.i8 d20, #0 -1: - vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128] - vld4.32 {d16[],d17[],d18[],d19[]},[r2,:128]! - paeth d0, d3, d16, d20 - vadd.u8 d0, d0, d4 - paeth d1, d0, d17, d16 - vadd.u8 d1, d1, d5 - paeth d2, d1, d18, d17 - vadd.u8 d2, d2, d6 - paeth d3, d2, d19, d18 - vmov d20, d19 - vadd.u8 d3, d3, d7 - vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]! - subs r12, r12, #16 - bgt 1b - - bx lr -endfunc - -func png_read_filter_row_paeth3_neon, export=1 - push {r4,lr} - ldr r12, [r0, #4] @ rowbytes - vmov.i8 d3, #0 - vmov.i8 d4, #0 - mov r0, r1 - mov r4, #3 - mov lr, #12 - vld1.8 {q11}, [r0], lr -1: - vld1.8 {q10}, [r2], lr - paeth d0, d3, d20, d4 - vext.8 d5, d22, d23, #3 - vadd.u8 d0, d0, d22 - vext.8 d17, d20, d21, #3 - paeth d1, d0, d17, d20 - vst1.32 {d0[0]}, [r1,:32], r4 - vext.8 d6, d22, d23, #6 - vadd.u8 d1, d1, d5 - vext.8 d18, d20, d21, #6 - paeth d2, d1, d18, d17 - vext.8 d7, d23, d23, #1 - vld1.8 {q11}, [r0], lr - vst1.32 {d1[0]}, [r1], r4 - vadd.u8 d2, d2, d6 - vext.8 d19, d21, d21, #1 - paeth d3, d2, d19, d18 - vst1.32 {d2[0]}, [r1], r4 - vmov d4, d19 - vadd.u8 d3, d3, d7 - vst1.32 {d3[0]}, [r1], r4 - subs r12, r12, #12 - bgt 1b - - pop {r4,pc} -endfunc #endif /* PNG_ARM_NEON_OPT > 0 */ -#endif /* PNG_ARM_NEON_IMPLEMENTATION == 2 (assembler) */ +#endif /* PNG_ARM_NEON_IMPLEMENTATION == 2 */ #endif /* READ */ diff --git a/3rdparty/libpng/arm/filter_neon_intrinsics.c b/3rdparty/libpng/arm/filter_neon_intrinsics.c index 4466d48b20..7c3e0da4d8 100644 --- a/3rdparty/libpng/arm/filter_neon_intrinsics.c +++ b/3rdparty/libpng/arm/filter_neon_intrinsics.c @@ -1,4 +1,3 @@ - /* filter_neon_intrinsics.c - NEON optimised filter functions * * Copyright (c) 2018 Cosmin Truta diff --git a/3rdparty/libpng/arm/palette_neon_intrinsics.c b/3rdparty/libpng/arm/palette_neon_intrinsics.c index 92c7d6f9f6..3068e9b6e6 100644 --- a/3rdparty/libpng/arm/palette_neon_intrinsics.c +++ b/3rdparty/libpng/arm/palette_neon_intrinsics.c @@ -1,4 +1,3 @@ - /* palette_neon_intrinsics.c - NEON optimised palette expansion functions * * Copyright (c) 2018-2019 Cosmin Truta @@ -64,7 +63,7 @@ png_do_expand_palette_rgba8_neon(png_structrp png_ptr, png_row_infop row_info, { png_uint_32 row_width = row_info->width; const png_uint_32 *riffled_palette = - (const png_uint_32 *)png_ptr->riffled_palette; + png_aligncastconst(png_const_uint_32p, png_ptr->riffled_palette); const png_uint_32 pixels_per_chunk = 4; png_uint_32 i; diff --git a/3rdparty/libpng/intel/filter_sse2_intrinsics.c b/3rdparty/libpng/intel/filter_sse2_intrinsics.c index d3c0fe9e2d..2993f650b7 100644 --- a/3rdparty/libpng/intel/filter_sse2_intrinsics.c +++ b/3rdparty/libpng/intel/filter_sse2_intrinsics.c @@ -1,4 +1,3 @@ - /* filter_sse2_intrinsics.c - SSE2 optimized filter functions * * Copyright (c) 2018 Cosmin Truta diff --git a/3rdparty/libpng/intel/intel_init.c b/3rdparty/libpng/intel/intel_init.c index 2f8168b7c4..9e4610d25b 100644 --- a/3rdparty/libpng/intel/intel_init.c +++ b/3rdparty/libpng/intel/intel_init.c @@ -1,4 +1,3 @@ - /* intel_init.c - SSE2 optimized filter functions * * Copyright (c) 2018 Cosmin Truta diff --git a/3rdparty/libpng/mips/filter_msa_intrinsics.c b/3rdparty/libpng/mips/filter_msa_intrinsics.c index 1b734f4d9a..a294f55130 100644 --- a/3rdparty/libpng/mips/filter_msa_intrinsics.c +++ b/3rdparty/libpng/mips/filter_msa_intrinsics.c @@ -1,4 +1,3 @@ - /* filter_msa_intrinsics.c - MSA optimised filter functions * * Copyright (c) 2018-2024 Cosmin Truta @@ -47,7 +46,7 @@ uint8_t *psrc_lw_m = (uint8_t *) (psrc); \ uint32_t val_m; \ \ - asm volatile ( \ + __asm__ volatile ( \ "lw %[val_m], %[psrc_lw_m] \n\t" \ \ : [val_m] "=r" (val_m) \ @@ -62,7 +61,7 @@ uint8_t *pdst_sh_m = (uint8_t *) (pdst); \ uint16_t val_m = (val); \ \ - asm volatile ( \ + __asm__ volatile ( \ "sh %[val_m], %[pdst_sh_m] \n\t" \ \ : [pdst_sh_m] "=m" (*pdst_sh_m) \ @@ -75,7 +74,7 @@ uint8_t *pdst_sw_m = (uint8_t *) (pdst); \ uint32_t val_m = (val); \ \ - asm volatile ( \ + __asm__ volatile ( \ "sw %[val_m], %[pdst_sw_m] \n\t" \ \ : [pdst_sw_m] "=m" (*pdst_sw_m) \ @@ -83,20 +82,20 @@ ); \ } - #if (__mips == 64) + #if __mips == 64 #define SD(val, pdst) \ { \ uint8_t *pdst_sd_m = (uint8_t *) (pdst); \ uint64_t val_m = (val); \ \ - asm volatile ( \ + __asm__ volatile ( \ "sd %[val_m], %[pdst_sd_m] \n\t" \ \ : [pdst_sd_m] "=m" (*pdst_sd_m) \ : [val_m] "r" (val_m) \ ); \ } - #else + #else #define SD(val, pdst) \ { \ uint8_t *pdst_sd_m = (uint8_t *) (pdst); \ @@ -108,17 +107,17 @@ SW(val0_m, pdst_sd_m); \ SW(val1_m, pdst_sd_m + 4); \ } - #endif + #endif /* __mips == 64 */ #else #define MSA_SRLI_B(a, b) (a >> b) -#if (__mips_isa_rev >= 6) +#if __mips_isa_rev >= 6 #define LW(psrc) \ ( { \ uint8_t *psrc_lw_m = (uint8_t *) (psrc); \ uint32_t val_m; \ \ - asm volatile ( \ + __asm__ volatile ( \ "lw %[val_m], %[psrc_lw_m] \n\t" \ \ : [val_m] "=r" (val_m) \ @@ -133,7 +132,7 @@ uint8_t *pdst_sh_m = (uint8_t *) (pdst); \ uint16_t val_m = (val); \ \ - asm volatile ( \ + __asm__ volatile ( \ "sh %[val_m], %[pdst_sh_m] \n\t" \ \ : [pdst_sh_m] "=m" (*pdst_sh_m) \ @@ -146,7 +145,7 @@ uint8_t *pdst_sw_m = (uint8_t *) (pdst); \ uint32_t val_m = (val); \ \ - asm volatile ( \ + __asm__ volatile ( \ "sw %[val_m], %[pdst_sw_m] \n\t" \ \ : [pdst_sw_m] "=m" (*pdst_sw_m) \ @@ -154,20 +153,20 @@ ); \ } - #if (__mips == 64) + #if __mips == 64 #define SD(val, pdst) \ { \ uint8_t *pdst_sd_m = (uint8_t *) (pdst); \ uint64_t val_m = (val); \ \ - asm volatile ( \ + __asm__ volatile ( \ "sd %[val_m], %[pdst_sd_m] \n\t" \ \ : [pdst_sd_m] "=m" (*pdst_sd_m) \ : [val_m] "r" (val_m) \ ); \ } - #else + #else #define SD(val, pdst) \ { \ uint8_t *pdst_sd_m = (uint8_t *) (pdst); \ @@ -179,14 +178,14 @@ SW(val0_m, pdst_sd_m); \ SW(val1_m, pdst_sd_m + 4); \ } - #endif -#else // !(__mips_isa_rev >= 6) + #endif /* __mips == 64 */ +#else #define LW(psrc) \ ( { \ uint8_t *psrc_lw_m = (uint8_t *) (psrc); \ uint32_t val_m; \ \ - asm volatile ( \ + __asm__ volatile ( \ "ulw %[val_m], %[psrc_lw_m] \n\t" \ \ : [val_m] "=r" (val_m) \ @@ -201,7 +200,7 @@ uint8_t *pdst_sh_m = (uint8_t *) (pdst); \ uint16_t val_m = (val); \ \ - asm volatile ( \ + __asm__ volatile ( \ "ush %[val_m], %[pdst_sh_m] \n\t" \ \ : [pdst_sh_m] "=m" (*pdst_sh_m) \ @@ -214,7 +213,7 @@ uint8_t *pdst_sw_m = (uint8_t *) (pdst); \ uint32_t val_m = (val); \ \ - asm volatile ( \ + __asm__ volatile ( \ "usw %[val_m], %[pdst_sw_m] \n\t" \ \ : [pdst_sw_m] "=m" (*pdst_sw_m) \ @@ -222,7 +221,7 @@ ); \ } - #define SD(val, pdst) \ + #define SD(val, pdst) \ { \ uint8_t *pdst_sd_m = (uint8_t *) (pdst); \ uint32_t val0_m, val1_m; \ @@ -238,14 +237,14 @@ { \ uint8_t *pdst_m = (uint8_t *) (pdst); \ \ - asm volatile ( \ + __asm__ volatile ( \ "usw $0, %[pdst_m] \n\t" \ \ : [pdst_m] "=m" (*pdst_m) \ : \ ); \ } -#endif // (__mips_isa_rev >= 6) +#endif /* __mips_isa_rev >= 6 */ #endif #define LD_B(RTYPE, psrc) *((RTYPE *) (psrc)) diff --git a/3rdparty/libpng/mips/mips_init.c b/3rdparty/libpng/mips/mips_init.c index 5c6fa1dbf1..143f0a3714 100644 --- a/3rdparty/libpng/mips/mips_init.c +++ b/3rdparty/libpng/mips/mips_init.c @@ -1,4 +1,3 @@ - /* mips_init.c - MSA optimised filter functions * * Copyright (c) 2018-2024 Cosmin Truta diff --git a/3rdparty/libpng/png.c b/3rdparty/libpng/png.c index 9ed3157009..466af7d992 100644 --- a/3rdparty/libpng/png.c +++ b/3rdparty/libpng/png.c @@ -1,7 +1,6 @@ - /* png.c - location for general purpose libpng functions * - * Copyright (c) 2018-2024 Cosmin Truta + * Copyright (c) 2018-2025 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -14,7 +13,7 @@ #include "pngpriv.h" /* Generate a compiler error if there is an old png.h in the search path. */ -typedef png_libpng_version_1_6_43 Your_png_h_is_not_version_1_6_43; +typedef png_libpng_version_1_6_45 Your_png_h_is_not_version_1_6_45; /* Tells libpng that we have already handled the first "num_bytes" bytes * of the PNG file signature. If the PNG data is embedded into another @@ -794,8 +793,8 @@ png_get_copyright(png_const_structrp png_ptr) return PNG_STRING_COPYRIGHT #else return PNG_STRING_NEWLINE \ - "libpng version 1.6.43" PNG_STRING_NEWLINE \ - "Copyright (c) 2018-2024 Cosmin Truta" PNG_STRING_NEWLINE \ + "libpng version 1.6.45" PNG_STRING_NEWLINE \ + "Copyright (c) 2018-2025 Cosmin Truta" PNG_STRING_NEWLINE \ "Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \ PNG_STRING_NEWLINE \ "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ @@ -1203,6 +1202,68 @@ png_colorspace_sync(png_const_structrp png_ptr, png_inforp info_ptr) #endif /* GAMMA */ #ifdef PNG_COLORSPACE_SUPPORTED +static png_int_32 +png_fp_add(png_int_32 addend0, png_int_32 addend1, int *error) +{ + /* Safely add two fixed point values setting an error flag and returning 0.5 + * on overflow. + * IMPLEMENTATION NOTE: ANSI requires signed overflow not to occur, therefore + * relying on addition of two positive values producing a negative one is not + * safe. + */ + if (addend0 > 0) + { + if (0x7fffffff - addend0 >= addend1) + return addend0+addend1; + } + else if (addend0 < 0) + { + if (-0x7fffffff - addend0 <= addend1) + return addend0+addend1; + } + else + return addend1; + + *error = 1; + return PNG_FP_1/2; +} + +static png_int_32 +png_fp_sub(png_int_32 addend0, png_int_32 addend1, int *error) +{ + /* As above but calculate addend0-addend1. */ + if (addend1 > 0) + { + if (-0x7fffffff + addend1 <= addend0) + return addend0-addend1; + } + else if (addend1 < 0) + { + if (0x7fffffff + addend1 >= addend0) + return addend0-addend1; + } + else + return addend0; + + *error = 1; + return PNG_FP_1/2; +} + +static int +png_safe_add(png_int_32 *addend0_and_result, png_int_32 addend1, + png_int_32 addend2) +{ + /* Safely add three integers. Returns 0 on success, 1 on overflow. Does not + * set the result on overflow. + */ + int error = 0; + int result = png_fp_add(*addend0_and_result, + png_fp_add(addend1, addend2, &error), + &error); + if (!error) *addend0_and_result = result; + return error; +} + /* Added at libpng-1.5.5 to support read and write of true CIEXYZ values for * cHRM, as opposed to using chromaticities. These internal APIs return * non-zero on a parameter error. The X, Y and Z values are required to be @@ -1211,38 +1272,60 @@ png_colorspace_sync(png_const_structrp png_ptr, png_inforp info_ptr) static int png_xy_from_XYZ(png_xy *xy, const png_XYZ *XYZ) { - png_int_32 d, dwhite, whiteX, whiteY; + png_int_32 d, dred, dgreen, dblue, dwhite, whiteX, whiteY; - d = XYZ->red_X + XYZ->red_Y + XYZ->red_Z; - if (png_muldiv(&xy->redx, XYZ->red_X, PNG_FP_1, d) == 0) + /* 'd' in each of the blocks below is just X+Y+Z for each component, + * x, y and z are X,Y,Z/(X+Y+Z). + */ + d = XYZ->red_X; + if (png_safe_add(&d, XYZ->red_Y, XYZ->red_Z)) return 1; - if (png_muldiv(&xy->redy, XYZ->red_Y, PNG_FP_1, d) == 0) + dred = d; + if (png_muldiv(&xy->redx, XYZ->red_X, PNG_FP_1, dred) == 0) + return 1; + if (png_muldiv(&xy->redy, XYZ->red_Y, PNG_FP_1, dred) == 0) + return 1; + + d = XYZ->green_X; + if (png_safe_add(&d, XYZ->green_Y, XYZ->green_Z)) + return 1; + dgreen = d; + if (png_muldiv(&xy->greenx, XYZ->green_X, PNG_FP_1, dgreen) == 0) + return 1; + if (png_muldiv(&xy->greeny, XYZ->green_Y, PNG_FP_1, dgreen) == 0) + return 1; + + d = XYZ->blue_X; + if (png_safe_add(&d, XYZ->blue_Y, XYZ->blue_Z)) + return 1; + dblue = d; + if (png_muldiv(&xy->bluex, XYZ->blue_X, PNG_FP_1, dblue) == 0) + return 1; + if (png_muldiv(&xy->bluey, XYZ->blue_Y, PNG_FP_1, dblue) == 0) + return 1; + + /* The reference white is simply the sum of the end-point (X,Y,Z) vectors so + * the fillowing calculates (X+Y+Z) of the reference white (media white, + * encoding white) itself: + */ + d = dblue; + if (png_safe_add(&d, dred, dgreen)) return 1; dwhite = d; - whiteX = XYZ->red_X; - whiteY = XYZ->red_Y; - d = XYZ->green_X + XYZ->green_Y + XYZ->green_Z; - if (png_muldiv(&xy->greenx, XYZ->green_X, PNG_FP_1, d) == 0) - return 1; - if (png_muldiv(&xy->greeny, XYZ->green_Y, PNG_FP_1, d) == 0) - return 1; - dwhite += d; - whiteX += XYZ->green_X; - whiteY += XYZ->green_Y; - - d = XYZ->blue_X + XYZ->blue_Y + XYZ->blue_Z; - if (png_muldiv(&xy->bluex, XYZ->blue_X, PNG_FP_1, d) == 0) - return 1; - if (png_muldiv(&xy->bluey, XYZ->blue_Y, PNG_FP_1, d) == 0) - return 1; - dwhite += d; - whiteX += XYZ->blue_X; - whiteY += XYZ->blue_Y; - - /* The reference white is simply the sum of the end-point (X,Y,Z) vectors, - * thus: + /* Find the white X,Y values from the sum of the red, green and blue X,Y + * values. */ + d = XYZ->red_X; + if (png_safe_add(&d, XYZ->green_X, XYZ->blue_X)) + return 1; + whiteX = d; + + d = XYZ->red_Y; + if (png_safe_add(&d, XYZ->green_Y, XYZ->blue_Y)) + return 1; + whiteY = d; + if (png_muldiv(&xy->whitex, whiteX, PNG_FP_1, dwhite) == 0) return 1; if (png_muldiv(&xy->whitey, whiteY, PNG_FP_1, dwhite) == 0) @@ -1261,15 +1344,24 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy) * have end points with 0 tristimulus values (these are impossible end * points, but they are used to cover the possible colors). We check * xy->whitey against 5, not 0, to avoid a possible integer overflow. + * + * The limits here will *not* accept ACES AP0, where bluey is -7700 + * (-0.0770) because the PNG spec itself requires the xy values to be + * unsigned. whitey is also required to be 5 or more to avoid overflow. + * + * Instead the upper limits have been relaxed to accomodate ACES AP1 where + * redz ends up as -600 (-0.006). ProPhotoRGB was already "in range." + * The new limit accomodates the AP0 and AP1 ranges for z but not AP0 redy. */ - if (xy->redx < 0 || xy->redx > PNG_FP_1) return 1; - if (xy->redy < 0 || xy->redy > PNG_FP_1-xy->redx) return 1; - if (xy->greenx < 0 || xy->greenx > PNG_FP_1) return 1; - if (xy->greeny < 0 || xy->greeny > PNG_FP_1-xy->greenx) return 1; - if (xy->bluex < 0 || xy->bluex > PNG_FP_1) return 1; - if (xy->bluey < 0 || xy->bluey > PNG_FP_1-xy->bluex) return 1; - if (xy->whitex < 0 || xy->whitex > PNG_FP_1) return 1; - if (xy->whitey < 5 || xy->whitey > PNG_FP_1-xy->whitex) return 1; + const png_fixed_point fpLimit = PNG_FP_1+(PNG_FP_1/10); + if (xy->redx < 0 || xy->redx > fpLimit) return 1; + if (xy->redy < 0 || xy->redy > fpLimit-xy->redx) return 1; + if (xy->greenx < 0 || xy->greenx > fpLimit) return 1; + if (xy->greeny < 0 || xy->greeny > fpLimit-xy->greenx) return 1; + if (xy->bluex < 0 || xy->bluex > fpLimit) return 1; + if (xy->bluey < 0 || xy->bluey > fpLimit-xy->bluex) return 1; + if (xy->whitex < 0 || xy->whitex > fpLimit) return 1; + if (xy->whitey < 5 || xy->whitey > fpLimit-xy->whitex) return 1; /* The reverse calculation is more difficult because the original tristimulus * value had 9 independent values (red,green,blue)x(X,Y,Z) however only 8 @@ -1414,18 +1506,23 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy) * (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x) * * Accuracy: - * The input values have 5 decimal digits of accuracy. The values are all in - * the range 0 < value < 1, so simple products are in the same range but may - * need up to 10 decimal digits to preserve the original precision and avoid - * underflow. Because we are using a 32-bit signed representation we cannot - * match this; the best is a little over 9 decimal digits, less than 10. + * The input values have 5 decimal digits of accuracy. + * + * In the previous implementation the values were all in the range 0 < value + * < 1, so simple products are in the same range but may need up to 10 + * decimal digits to preserve the original precision and avoid underflow. + * Because we are using a 32-bit signed representation we cannot match this; + * the best is a little over 9 decimal digits, less than 10. + * + * This range has now been extended to allow values up to 1.1, or 110,000 in + * fixed point. * * The approach used here is to preserve the maximum precision within the * signed representation. Because the red-scale calculation above uses the - * difference between two products of values that must be in the range -1..+1 - * it is sufficient to divide the product by 7; ceil(100,000/32767*2). The - * factor is irrelevant in the calculation because it is applied to both - * numerator and denominator. + * difference between two products of values that must be in the range + * -1.1..+1.1 it is sufficient to divide the product by 8; + * ceil(121,000/32767*2). The factor is irrelevant in the calculation + * because it is applied to both numerator and denominator. * * Note that the values of the differences of the products of the * chromaticities in the above equations tend to be small, for example for @@ -1447,49 +1544,61 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy) * Adobe Wide Gamut RGB * 0.258728243040113 0.724682314948566 0.016589442011321 */ - /* By the argument, above overflow should be impossible here. The return - * value of 2 indicates an internal error to the caller. + int error = 0; + + /* By the argument above overflow should be impossible here, however the + * code now simply returns a failure code. The xy subtracts in the arguments + * to png_muldiv are *not* checked for overflow because the checks at the + * start guarantee they are in the range 0..110000 and png_fixed_point is a + * 32-bit signed number. */ - if (png_muldiv(&left, xy->greenx-xy->bluex, xy->redy - xy->bluey, 7) == 0) - return 2; - if (png_muldiv(&right, xy->greeny-xy->bluey, xy->redx - xy->bluex, 7) == 0) - return 2; - denominator = left - right; + if (png_muldiv(&left, xy->greenx-xy->bluex, xy->redy - xy->bluey, 8) == 0) + return 1; + if (png_muldiv(&right, xy->greeny-xy->bluey, xy->redx - xy->bluex, 8) == 0) + return 1; + denominator = png_fp_sub(left, right, &error); + if (error) return 1; /* Now find the red numerator. */ - if (png_muldiv(&left, xy->greenx-xy->bluex, xy->whitey-xy->bluey, 7) == 0) - return 2; - if (png_muldiv(&right, xy->greeny-xy->bluey, xy->whitex-xy->bluex, 7) == 0) - return 2; + if (png_muldiv(&left, xy->greenx-xy->bluex, xy->whitey-xy->bluey, 8) == 0) + return 1; + if (png_muldiv(&right, xy->greeny-xy->bluey, xy->whitex-xy->bluex, 8) == 0) + return 1; /* Overflow is possible here and it indicates an extreme set of PNG cHRM * chunk values. This calculation actually returns the reciprocal of the * scale value because this allows us to delay the multiplication of white-y * into the denominator, which tends to produce a small number. */ - if (png_muldiv(&red_inverse, xy->whitey, denominator, left-right) == 0 || + if (png_muldiv(&red_inverse, xy->whitey, denominator, + png_fp_sub(left, right, &error)) == 0 || error || red_inverse <= xy->whitey /* r+g+b scales = white scale */) return 1; /* Similarly for green_inverse: */ - if (png_muldiv(&left, xy->redy-xy->bluey, xy->whitex-xy->bluex, 7) == 0) - return 2; - if (png_muldiv(&right, xy->redx-xy->bluex, xy->whitey-xy->bluey, 7) == 0) - return 2; - if (png_muldiv(&green_inverse, xy->whitey, denominator, left-right) == 0 || + if (png_muldiv(&left, xy->redy-xy->bluey, xy->whitex-xy->bluex, 8) == 0) + return 1; + if (png_muldiv(&right, xy->redx-xy->bluex, xy->whitey-xy->bluey, 8) == 0) + return 1; + if (png_muldiv(&green_inverse, xy->whitey, denominator, + png_fp_sub(left, right, &error)) == 0 || error || green_inverse <= xy->whitey) return 1; /* And the blue scale, the checks above guarantee this can't overflow but it * can still produce 0 for extreme cHRM values. */ - blue_scale = png_reciprocal(xy->whitey) - png_reciprocal(red_inverse) - - png_reciprocal(green_inverse); - if (blue_scale <= 0) + blue_scale = png_fp_sub(png_fp_sub(png_reciprocal(xy->whitey), + png_reciprocal(red_inverse), &error), + png_reciprocal(green_inverse), &error); + if (error || blue_scale <= 0) return 1; - /* And fill in the png_XYZ: */ + /* And fill in the png_XYZ. Again the subtracts are safe because of the + * checks on the xy values at the start (the subtracts just calculate the + * corresponding z values.) + */ if (png_muldiv(&XYZ->red_X, xy->redx, PNG_FP_1, red_inverse) == 0) return 1; if (png_muldiv(&XYZ->red_Y, xy->redy, PNG_FP_1, red_inverse) == 0) @@ -1520,25 +1629,14 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy) static int png_XYZ_normalize(png_XYZ *XYZ) { - png_int_32 Y; + png_int_32 Y, Ytemp; - if (XYZ->red_Y < 0 || XYZ->green_Y < 0 || XYZ->blue_Y < 0 || - XYZ->red_X < 0 || XYZ->green_X < 0 || XYZ->blue_X < 0 || - XYZ->red_Z < 0 || XYZ->green_Z < 0 || XYZ->blue_Z < 0) + /* Normalize by scaling so the sum of the end-point Y values is PNG_FP_1. */ + Ytemp = XYZ->red_Y; + if (png_safe_add(&Ytemp, XYZ->green_Y, XYZ->blue_Y)) return 1; - /* Normalize by scaling so the sum of the end-point Y values is PNG_FP_1. - * IMPLEMENTATION NOTE: ANSI requires signed overflow not to occur, therefore - * relying on addition of two positive values producing a negative one is not - * safe. - */ - Y = XYZ->red_Y; - if (0x7fffffff - Y < XYZ->green_X) - return 1; - Y += XYZ->green_Y; - if (0x7fffffff - Y < XYZ->blue_X) - return 1; - Y += XYZ->blue_Y; + Y = Ytemp; if (Y != PNG_FP_1) { diff --git a/3rdparty/libpng/png.h b/3rdparty/libpng/png.h index 83d3903126..d25fbe9ed3 100644 --- a/3rdparty/libpng/png.h +++ b/3rdparty/libpng/png.h @@ -1,9 +1,8 @@ - /* png.h - header file for PNG reference library * - * libpng version 1.6.43 + * libpng version 1.6.45 * - * Copyright (c) 2018-2024 Cosmin Truta + * Copyright (c) 2018-2025 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -15,7 +14,7 @@ * libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger * libpng versions 0.97, January 1998, through 1.6.35, July 2018: * Glenn Randers-Pehrson - * libpng versions 1.6.36, December 2018, through 1.6.43, February 2024: + * libpng versions 1.6.36, December 2018, through 1.6.45, January 2025: * Cosmin Truta * See also "Contributing Authors", below. */ @@ -27,8 +26,8 @@ * PNG Reference Library License version 2 * --------------------------------------- * - * * Copyright (c) 1995-2024 The PNG Reference Library Authors. - * * Copyright (c) 2018-2024 Cosmin Truta. + * * Copyright (c) 1995-2025 The PNG Reference Library Authors. + * * Copyright (c) 2018-2025 Cosmin Truta. * * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson. * * Copyright (c) 1996-1997 Andreas Dilger. * * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -239,7 +238,7 @@ * ... * 1.5.30 15 10530 15.so.15.30[.0] * ... - * 1.6.43 16 10643 16.so.16.43[.0] + * 1.6.45 16 10645 16.so.16.45[.0] * * Henceforth the source version will match the shared-library major and * minor numbers; the shared-library major version number will be used for @@ -275,7 +274,7 @@ */ /* Version information for png.h - this should match the version in png.c */ -#define PNG_LIBPNG_VER_STRING "1.6.43" +#define PNG_LIBPNG_VER_STRING "1.6.45" #define PNG_HEADER_VERSION_STRING " libpng version " PNG_LIBPNG_VER_STRING "\n" /* The versions of shared library builds should stay in sync, going forward */ @@ -286,18 +285,18 @@ /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ #define PNG_LIBPNG_VER_MAJOR 1 #define PNG_LIBPNG_VER_MINOR 6 -#define PNG_LIBPNG_VER_RELEASE 43 +#define PNG_LIBPNG_VER_RELEASE 45 /* This should be zero for a public release, or non-zero for a * development version. */ -#define PNG_LIBPNG_VER_BUILD 0 +#define PNG_LIBPNG_VER_BUILD 0 /* Release Status */ -#define PNG_LIBPNG_BUILD_ALPHA 1 -#define PNG_LIBPNG_BUILD_BETA 2 -#define PNG_LIBPNG_BUILD_RC 3 -#define PNG_LIBPNG_BUILD_STABLE 4 +#define PNG_LIBPNG_BUILD_ALPHA 1 +#define PNG_LIBPNG_BUILD_BETA 2 +#define PNG_LIBPNG_BUILD_RC 3 +#define PNG_LIBPNG_BUILD_STABLE 4 #define PNG_LIBPNG_BUILD_RELEASE_STATUS_MASK 7 /* Release-Specific Flags */ @@ -317,7 +316,7 @@ * From version 1.0.1 it is: * XXYYZZ, where XX=major, YY=minor, ZZ=release */ -#define PNG_LIBPNG_VER 10643 /* 1.6.43 */ +#define PNG_LIBPNG_VER 10645 /* 1.6.45 */ /* Library configuration: these options cannot be changed after * the library has been built. @@ -427,7 +426,7 @@ extern "C" { /* This triggers a compiler error in png.c, if png.c and png.h * do not agree upon the version number. */ -typedef char* png_libpng_version_1_6_43; +typedef char* png_libpng_version_1_6_45; /* Basic control structions. Read libpng-manual.txt or libpng.3 for more info. * @@ -745,6 +744,7 @@ typedef png_unknown_chunk * * png_unknown_chunkpp; #define PNG_INFO_sCAL 0x4000U /* ESR, 1.0.6 */ #define PNG_INFO_IDAT 0x8000U /* ESR, 1.0.6 */ #define PNG_INFO_eXIf 0x10000U /* GR-P, 1.6.31 */ +#define PNG_INFO_cICP 0x20000U /* This is used for the transformation routines, as some of them * change these values for the row. It also should enable using @@ -824,7 +824,7 @@ typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp, * your compiler. This may be very difficult - try using a different compiler * to build the library! */ -PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef); +PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), (jmp_buf, int), typedef); #endif /* Transform masks for the high-level interface */ @@ -1974,6 +1974,17 @@ PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_const_structrp png_ptr, png_fixed_point int_blue_Z)) #endif +#ifdef PNG_cICP_SUPPORTED +PNG_EXPORT(250, png_uint_32, png_get_cICP, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep colour_primaries, + png_bytep transfer_function, png_bytep matrix_coefficients, + png_bytep video_full_range_flag)); +PNG_EXPORT(251, void, png_set_cICP, (png_const_structrp png_ptr, + png_inforp info_ptr, png_byte colour_primaries, + png_byte transfer_function, png_byte matrix_coefficients, + png_byte video_full_range_flag)); +#endif + #ifdef PNG_eXIf_SUPPORTED PNG_EXPORT(246, png_uint_32, png_get_eXIf, (png_const_structrp png_ptr, png_inforp info_ptr, png_bytep *exif)); @@ -3238,7 +3249,7 @@ PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option, * one to use is one more than this.) */ #ifdef PNG_EXPORT_LAST_ORDINAL - PNG_EXPORT_LAST_ORDINAL(249); + PNG_EXPORT_LAST_ORDINAL(251); #endif #ifdef __cplusplus diff --git a/3rdparty/libpng/pngconf.h b/3rdparty/libpng/pngconf.h index 000d7b1a8a..11a40b8d81 100644 --- a/3rdparty/libpng/pngconf.h +++ b/3rdparty/libpng/pngconf.h @@ -1,9 +1,8 @@ - /* pngconf.h - machine-configurable file for libpng * - * libpng version 1.6.43 + * libpng version 1.6.45 * - * Copyright (c) 2018-2024 Cosmin Truta + * Copyright (c) 2018-2025 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson * Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -88,7 +87,7 @@ /* The PNGARG macro was used in versions of libpng prior to 1.6.0 to protect * against legacy (pre ISOC90) compilers that did not understand function - * prototypes. It is not required for modern C compilers. + * prototypes. [Deprecated.] */ #ifndef PNGARG # define PNGARG(arglist) arglist @@ -298,7 +297,7 @@ #ifndef PNG_EXPORTA # define PNG_EXPORTA(ordinal, type, name, args, attributes) \ - PNG_FUNCTION(PNG_EXPORT_TYPE(type), (PNGAPI name), PNGARG(args), \ + PNG_FUNCTION(PNG_EXPORT_TYPE(type), (PNGAPI name), args, \ PNG_LINKAGE_API attributes) #endif @@ -316,7 +315,7 @@ #endif #ifndef PNG_CALLBACK -# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args) +# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) args #endif /* Support for compiler specific function attributes. These are used diff --git a/3rdparty/libpng/pngdebug.h b/3rdparty/libpng/pngdebug.h index 00d5a4569e..ab9ea632d9 100644 --- a/3rdparty/libpng/pngdebug.h +++ b/3rdparty/libpng/pngdebug.h @@ -1,4 +1,3 @@ - /* pngdebug.h - Debugging macros for libpng, also used in pngtest.c * * Copyright (c) 2018 Cosmin Truta diff --git a/3rdparty/libpng/pngerror.c b/3rdparty/libpng/pngerror.c index 29ebda7943..aa0ae58e15 100644 --- a/3rdparty/libpng/pngerror.c +++ b/3rdparty/libpng/pngerror.c @@ -1,4 +1,3 @@ - /* pngerror.c - stub functions for i/o and memory allocation * * Copyright (c) 2018-2024 Cosmin Truta @@ -20,13 +19,14 @@ #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) -static PNG_FUNCTION(void, png_default_error,PNGARG((png_const_structrp png_ptr, - png_const_charp error_message)),PNG_NORETURN); +static PNG_FUNCTION(void /* PRIVATE */, +png_default_error,(png_const_structrp png_ptr, png_const_charp error_message), + PNG_NORETURN); #ifdef PNG_WARNINGS_SUPPORTED static void /* PRIVATE */ -png_default_warning PNGARG((png_const_structrp png_ptr, - png_const_charp warning_message)); +png_default_warning(png_const_structrp png_ptr, + png_const_charp warning_message); #endif /* WARNINGS */ /* This function is called whenever there is a fatal error. This function diff --git a/3rdparty/libpng/pngget.c b/3rdparty/libpng/pngget.c index 1084b268ff..9be8814322 100644 --- a/3rdparty/libpng/pngget.c +++ b/3rdparty/libpng/pngget.c @@ -1,4 +1,3 @@ - /* pngget.c - retrieval of values from info struct * * Copyright (c) 2018-2024 Cosmin Truta @@ -785,6 +784,31 @@ png_get_sPLT(png_const_structrp png_ptr, png_inforp info_ptr, } #endif +#ifdef PNG_cICP_SUPPORTED +png_uint_32 PNGAPI +png_get_cICP(png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep colour_primaries, + png_bytep transfer_function, png_bytep matrix_coefficients, + png_bytep video_full_range_flag) +{ + png_debug1(1, "in %s retrieval function", "cICP"); + + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_cICP) != 0 && + colour_primaries != NULL && transfer_function != NULL && + matrix_coefficients != NULL && video_full_range_flag != NULL) + { + *colour_primaries = info_ptr->cicp_colour_primaries; + *transfer_function = info_ptr->cicp_transfer_function; + *matrix_coefficients = info_ptr->cicp_matrix_coefficients; + *video_full_range_flag = info_ptr->cicp_video_full_range_flag; + return (PNG_INFO_cICP); + } + + return (0); +} +#endif + #ifdef PNG_eXIf_SUPPORTED png_uint_32 PNGAPI png_get_eXIf(png_const_structrp png_ptr, png_inforp info_ptr, diff --git a/3rdparty/libpng/pnginfo.h b/3rdparty/libpng/pnginfo.h index 1f98dedc42..e85420c1ad 100644 --- a/3rdparty/libpng/pnginfo.h +++ b/3rdparty/libpng/pnginfo.h @@ -1,4 +1,3 @@ - /* pnginfo.h - header file for PNG reference library * * Copyright (c) 2018 Cosmin Truta @@ -101,6 +100,14 @@ struct png_info_def png_colorspace colorspace; #endif +#ifdef PNG_cICP_SUPPORTED + /* cICP chunk data */ + png_byte cicp_colour_primaries; + png_byte cicp_transfer_function; + png_byte cicp_matrix_coefficients; + png_byte cicp_video_full_range_flag; +#endif + #ifdef PNG_iCCP_SUPPORTED /* iCCP chunk data. */ png_charp iccp_name; /* profile name */ diff --git a/3rdparty/libpng/pnglibconf.h b/3rdparty/libpng/pnglibconf.h index e1e27e957e..695aae6fed 100644 --- a/3rdparty/libpng/pnglibconf.h +++ b/3rdparty/libpng/pnglibconf.h @@ -1,8 +1,8 @@ /* pnglibconf.h - library build configuration */ -/* libpng version 1.6.37 */ +/* libpng version 1.6.45 */ -/* Copyright (c) 2018-2019 Cosmin Truta */ +/* Copyright (c) 2018-2025 Cosmin Truta */ /* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */ /* This code is released under the libpng license. */ @@ -27,6 +27,7 @@ #define PNG_COLORSPACE_SUPPORTED #define PNG_CONSOLE_IO_SUPPORTED #define PNG_CONVERT_tIME_SUPPORTED +/*#undef PNG_DISABLE_ADLER32_CHECK_SUPPORTED*/ #define PNG_EASY_ACCESS_SUPPORTED /*#undef PNG_ERROR_NUMBERS_SUPPORTED*/ #define PNG_ERROR_TEXT_SUPPORTED @@ -41,6 +42,10 @@ #define PNG_INCH_CONVERSIONS_SUPPORTED #define PNG_INFO_IMAGE_SUPPORTED #define PNG_IO_STATE_SUPPORTED +/*#undef PNG_MIPS_MMI_API_SUPPORTED*/ +/*#undef PNG_MIPS_MMI_CHECK_SUPPORTED*/ +/*#undef PNG_MIPS_MSA_API_SUPPORTED*/ +/*#undef PNG_MIPS_MSA_CHECK_SUPPORTED*/ #define PNG_MNG_FEATURES_SUPPORTED #define PNG_POINTER_INDEXING_SUPPORTED /*#undef PNG_POWERPC_VSX_API_SUPPORTED*/ @@ -83,6 +88,7 @@ #define PNG_READ_USER_TRANSFORM_SUPPORTED #define PNG_READ_bKGD_SUPPORTED #define PNG_READ_cHRM_SUPPORTED +#define PNG_READ_cICP_SUPPORTED #define PNG_READ_eXIf_SUPPORTED #define PNG_READ_gAMA_SUPPORTED #define PNG_READ_hIST_SUPPORTED @@ -153,6 +159,7 @@ #define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED #define PNG_WRITE_bKGD_SUPPORTED #define PNG_WRITE_cHRM_SUPPORTED +#define PNG_WRITE_cICP_SUPPORTED #define PNG_WRITE_eXIf_SUPPORTED #define PNG_WRITE_gAMA_SUPPORTED #define PNG_WRITE_hIST_SUPPORTED @@ -171,6 +178,7 @@ #define PNG_WRITE_zTXt_SUPPORTED #define PNG_bKGD_SUPPORTED #define PNG_cHRM_SUPPORTED +#define PNG_cICP_SUPPORTED #define PNG_eXIf_SUPPORTED #define PNG_gAMA_SUPPORTED #define PNG_hIST_SUPPORTED diff --git a/3rdparty/libpng/pngmem.c b/3rdparty/libpng/pngmem.c index 09ed9c1c99..d391c13ff4 100644 --- a/3rdparty/libpng/pngmem.c +++ b/3rdparty/libpng/pngmem.c @@ -1,4 +1,3 @@ - /* pngmem.c - stub functions for memory allocation * * Copyright (c) 2018 Cosmin Truta diff --git a/3rdparty/libpng/pngpread.c b/3rdparty/libpng/pngpread.c index ffab19c08c..1bf880eabb 100644 --- a/3rdparty/libpng/pngpread.c +++ b/3rdparty/libpng/pngpread.c @@ -1,4 +1,3 @@ - /* pngpread.c - read a png file in push mode * * Copyright (c) 2018-2024 Cosmin Truta @@ -32,6 +31,21 @@ if (png_ptr->push_length + 4 > png_ptr->buffer_size) \ if (png_ptr->buffer_size < N) \ { png_push_save_buffer(png_ptr); return; } +#ifdef PNG_READ_INTERLACING_SUPPORTED +/* Arrays to facilitate interlacing - use pass (0 - 6) as index. */ + +/* Start of interlace block */ +static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; +/* Offset to next interlace block */ +static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; +/* Start of interlace block in the y direction */ +static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; +/* Offset to next interlace block in the y direction */ +static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; + +/* TODO: Move these arrays to a common utility module to avoid duplication. */ +#endif + void PNGAPI png_process_data(png_structrp png_ptr, png_inforp info_ptr, png_bytep buffer, size_t buffer_size) @@ -294,6 +308,14 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr) png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length); } +#endif +#ifdef PNG_READ_cICP_SUPPORTED + else if (png_ptr->chunk_name == png_cICP) + { + PNG_PUSH_SAVE_BUFFER_IF_FULL + png_handle_cICP(png_ptr, info_ptr, png_ptr->push_length); + } + #endif #ifdef PNG_READ_eXIf_SUPPORTED else if (png_ptr->chunk_name == png_eXIf) @@ -976,27 +998,6 @@ png_push_process_row(png_structrp png_ptr) void /* PRIVATE */ png_read_push_finish_row(png_structrp png_ptr) { -#ifdef PNG_READ_INTERLACING_SUPPORTED - /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* Start of interlace block */ - static const png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; - - /* Offset to next interlace block */ - static const png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; - - /* Start of interlace block in the y direction */ - static const png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; - - /* Offset to next interlace block in the y direction */ - static const png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; - - /* Height of interlace block. This is not currently used - if you need - * it, uncomment it here and in png.h - static const png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; - */ -#endif - png_ptr->row_number++; if (png_ptr->row_number < png_ptr->num_rows) return; diff --git a/3rdparty/libpng/pngpriv.h b/3rdparty/libpng/pngpriv.h index 9bfdb71342..84f77c3508 100644 --- a/3rdparty/libpng/pngpriv.h +++ b/3rdparty/libpng/pngpriv.h @@ -1,4 +1,3 @@ - /* pngpriv.h - private declarations for use inside libpng * * Copyright (c) 2018-2024 Cosmin Truta @@ -140,47 +139,6 @@ * callbacks to do this. */ # define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_neon - - /* By default the 'intrinsics' code in arm/filter_neon_intrinsics.c is used - * if possible - if __ARM_NEON__ is set and the compiler version is not known - * to be broken. This is controlled by PNG_ARM_NEON_IMPLEMENTATION which can - * be: - * - * 1 The intrinsics code (the default with __ARM_NEON__) - * 2 The hand coded assembler (the default without __ARM_NEON__) - * - * It is possible to set PNG_ARM_NEON_IMPLEMENTATION in CPPFLAGS, however - * this is *NOT* supported and may cease to work even after a minor revision - * to libpng. It *is* valid to do this for testing purposes, e.g. speed - * testing or a new compiler, but the results should be communicated to the - * libpng implementation list for incorporation in the next minor release. - */ -# ifndef PNG_ARM_NEON_IMPLEMENTATION -# if defined(__ARM_NEON__) || defined(__ARM_NEON) -# if defined(__clang__) - /* At present it is unknown by the libpng developers which versions - * of clang support the intrinsics, however some or perhaps all - * versions do not work with the assembler so this may be - * irrelevant, so just use the default (do nothing here.) - */ -# elif defined(__GNUC__) - /* GCC 4.5.4 NEON support is known to be broken. 4.6.3 is known to - * work, so if this *is* GCC, or G++, look for a version >4.5 - */ -# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6) -# define PNG_ARM_NEON_IMPLEMENTATION 2 -# endif /* no GNUC support */ -# endif /* __GNUC__ */ -# else /* !defined __ARM_NEON__ */ - /* The 'intrinsics' code simply won't compile without this -mfpu=neon: - */ -# if !defined(__aarch64__) && !defined(_M_ARM64) - /* The assembler code currently does not work on ARM64 */ -# define PNG_ARM_NEON_IMPLEMENTATION 2 -# endif /* __aarch64__ */ -# endif /* __ARM_NEON__ */ -# endif /* !PNG_ARM_NEON_IMPLEMENTATION */ - # ifndef PNG_ARM_NEON_IMPLEMENTATION /* Use the intrinsics code by default. */ # define PNG_ARM_NEON_IMPLEMENTATION 1 @@ -876,6 +834,7 @@ #define png_PLTE PNG_U32( 80, 76, 84, 69) #define png_bKGD PNG_U32( 98, 75, 71, 68) #define png_cHRM PNG_U32( 99, 72, 82, 77) +#define png_cICP PNG_U32( 99, 73, 67, 80) #define png_eXIf PNG_U32(101, 88, 73, 102) /* registered July 2017 */ #define png_fRAc PNG_U32(102, 82, 65, 99) /* registered, not defined */ #define png_gAMA PNG_U32(103, 65, 77, 65) @@ -1172,6 +1131,12 @@ PNG_INTERNAL_FUNCTION(void,png_write_cHRM_fixed,(png_structrp png_ptr, /* The xy value must have been previously validated */ #endif +#ifdef PNG_WRITE_cICP_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_cICP,(png_structrp png_ptr, + png_byte colour_primaries, png_byte transfer_function, + png_byte matrix_coefficients, png_byte video_full_range_flag), PNG_EMPTY); +#endif + #ifdef PNG_WRITE_sRGB_SUPPORTED PNG_INTERNAL_FUNCTION(void,png_write_sRGB,(png_structrp png_ptr, int intent),PNG_EMPTY); @@ -1515,6 +1480,11 @@ PNG_INTERNAL_FUNCTION(void,png_handle_cHRM,(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); #endif +#ifdef PNG_READ_cICP_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_cICP,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + #ifdef PNG_READ_eXIf_SUPPORTED PNG_INTERNAL_FUNCTION(void,png_handle_eXIf,(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); diff --git a/3rdparty/libpng/pngread.c b/3rdparty/libpng/pngread.c index 07a39df6e2..49e19a4960 100644 --- a/3rdparty/libpng/pngread.c +++ b/3rdparty/libpng/pngread.c @@ -1,7 +1,6 @@ - /* pngread.c - read a PNG file * - * Copyright (c) 2018-2024 Cosmin Truta + * Copyright (c) 2018-2025 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -175,6 +174,11 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr) png_handle_cHRM(png_ptr, info_ptr, length); #endif +#ifdef PNG_READ_cICP_SUPPORTED + else if (chunk_name == png_cICP) + png_handle_cICP(png_ptr, info_ptr, length); +#endif + #ifdef PNG_READ_eXIf_SUPPORTED else if (chunk_name == png_eXIf) png_handle_eXIf(png_ptr, info_ptr, length); @@ -852,6 +856,11 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr) png_handle_cHRM(png_ptr, info_ptr, length); #endif +#ifdef PNG_READ_cICP_SUPPORTED + else if (chunk_name == png_cICP) + png_handle_cICP(png_ptr, info_ptr, length); +#endif + #ifdef PNG_READ_eXIf_SUPPORTED else if (chunk_name == png_eXIf) png_handle_eXIf(png_ptr, info_ptr, length); diff --git a/3rdparty/libpng/pngrio.c b/3rdparty/libpng/pngrio.c index 7946358101..3b137f275f 100644 --- a/3rdparty/libpng/pngrio.c +++ b/3rdparty/libpng/pngrio.c @@ -1,4 +1,3 @@ - /* pngrio.c - functions for data input * * Copyright (c) 2018 Cosmin Truta diff --git a/3rdparty/libpng/pngrtran.c b/3rdparty/libpng/pngrtran.c index 1526123e02..124906635b 100644 --- a/3rdparty/libpng/pngrtran.c +++ b/3rdparty/libpng/pngrtran.c @@ -1,4 +1,3 @@ - /* pngrtran.c - transforms the data in a row for PNG readers * * Copyright (c) 2018-2024 Cosmin Truta diff --git a/3rdparty/libpng/pngrutil.c b/3rdparty/libpng/pngrutil.c index d31dc21dae..7c609b4b48 100644 --- a/3rdparty/libpng/pngrutil.c +++ b/3rdparty/libpng/pngrutil.c @@ -1,4 +1,3 @@ - /* pngrutil.c - utilities to read a PNG file * * Copyright (c) 2018-2024 Cosmin Truta @@ -18,6 +17,21 @@ #ifdef PNG_READ_SUPPORTED +#ifdef PNG_READ_INTERLACING_SUPPORTED +/* Arrays to facilitate interlacing - use pass (0 - 6) as index. */ + +/* Start of interlace block */ +static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; +/* Offset to next interlace block */ +static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; +/* Start of interlace block in the y direction */ +static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; +/* Offset to next interlace block in the y direction */ +static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; + +/* TODO: Move these arrays to a common utility module to avoid duplication. */ +#endif + png_uint_32 PNGAPI png_get_uint_31(png_const_structrp png_ptr, png_const_bytep buf) { @@ -2032,6 +2046,47 @@ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) } #endif +#ifdef PNG_READ_cICP_SUPPORTED +void /* PRIVATE */ +png_handle_cICP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_byte buf[4]; + + png_debug(1, "in png_handle_cICP"); + + if ((png_ptr->mode & PNG_HAVE_IHDR) == 0) + png_chunk_error(png_ptr, "missing IHDR"); + + else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cICP) != 0) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "duplicate"); + return; + } + + else if (length != 4) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "invalid"); + return; + } + + png_crc_read(png_ptr, buf, 4); + + if (png_crc_finish(png_ptr, 0) != 0) + return; + + png_set_cICP(png_ptr, info_ptr, buf[0], buf[1], buf[2], buf[3]); +} +#endif + #ifdef PNG_READ_eXIf_SUPPORTED void /* PRIVATE */ png_handle_eXIf(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) @@ -3684,10 +3739,6 @@ void /* PRIVATE */ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, png_uint_32 transformations /* Because these may affect the byte layout */) { - /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - /* Offset to next interlace block */ - static const unsigned int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - png_debug(1, "in png_do_read_interlace"); if (row != NULL && row_info != NULL) { @@ -4325,20 +4376,6 @@ png_read_finish_IDAT(png_structrp png_ptr) void /* PRIVATE */ png_read_finish_row(png_structrp png_ptr) { - /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* Start of interlace block */ - static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* Offset to next interlace block */ - static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - - /* Start of interlace block in the y direction */ - static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - - /* Offset to next interlace block in the y direction */ - static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; - png_debug(1, "in png_read_finish_row"); png_ptr->row_number++; if (png_ptr->row_number < png_ptr->num_rows) @@ -4390,20 +4427,6 @@ png_read_finish_row(png_structrp png_ptr) void /* PRIVATE */ png_read_start_row(png_structrp png_ptr) { - /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* Start of interlace block */ - static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* Offset to next interlace block */ - static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - - /* Start of interlace block in the y direction */ - static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - - /* Offset to next interlace block in the y direction */ - static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; - unsigned int max_pixel_depth; size_t row_bytes; diff --git a/3rdparty/libpng/pngset.c b/3rdparty/libpng/pngset.c index eb1c8c7a35..462b50cf2a 100644 --- a/3rdparty/libpng/pngset.c +++ b/3rdparty/libpng/pngset.c @@ -1,7 +1,6 @@ - /* pngset.c - storage of image information into info struct * - * Copyright (c) 2018-2024 Cosmin Truta + * Copyright (c) 2018-2025 Cosmin Truta * Copyright (c) 1998-2018 Glenn Randers-Pehrson * Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -134,6 +133,32 @@ png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X, #endif /* cHRM */ +#ifdef PNG_cICP_SUPPORTED +void PNGAPI +png_set_cICP(png_const_structrp png_ptr, png_inforp info_ptr, + png_byte colour_primaries, png_byte transfer_function, + png_byte matrix_coefficients, png_byte video_full_range_flag) +{ + png_debug1(1, "in %s storage function", "cICP"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->cicp_colour_primaries = colour_primaries; + info_ptr->cicp_transfer_function = transfer_function; + info_ptr->cicp_matrix_coefficients = matrix_coefficients; + info_ptr->cicp_video_full_range_flag = video_full_range_flag; + + if (info_ptr->cicp_matrix_coefficients != 0) + { + png_warning(png_ptr, "Invalid cICP matrix coefficients"); + return; + } + + info_ptr->valid |= PNG_INFO_cICP; +} +#endif /* cICP */ + #ifdef PNG_eXIf_SUPPORTED void PNGAPI png_set_eXIf(png_const_structrp png_ptr, png_inforp info_ptr, @@ -1395,6 +1420,7 @@ png_set_keep_unknown_chunks(png_structrp png_ptr, int keep, static const png_byte chunks_to_ignore[] = { 98, 75, 71, 68, '\0', /* bKGD */ 99, 72, 82, 77, '\0', /* cHRM */ + 99, 73, 67, 80, '\0', /* cICP */ 101, 88, 73, 102, '\0', /* eXIf */ 103, 65, 77, 65, '\0', /* gAMA */ 104, 73, 83, 84, '\0', /* hIST */ diff --git a/3rdparty/libpng/pngstruct.h b/3rdparty/libpng/pngstruct.h index e591d94d58..7e919d0a37 100644 --- a/3rdparty/libpng/pngstruct.h +++ b/3rdparty/libpng/pngstruct.h @@ -1,4 +1,3 @@ - /* pngstruct.h - header file for PNG reference library * * Copyright (c) 2018-2022 Cosmin Truta diff --git a/3rdparty/libpng/pngtrans.c b/3rdparty/libpng/pngtrans.c index 62cb21edf1..222b4987f9 100644 --- a/3rdparty/libpng/pngtrans.c +++ b/3rdparty/libpng/pngtrans.c @@ -1,4 +1,3 @@ - /* pngtrans.c - transforms the data in a row (used by both readers and writers) * * Copyright (c) 2018-2024 Cosmin Truta diff --git a/3rdparty/libpng/pngwio.c b/3rdparty/libpng/pngwio.c index 10e919dd03..38c9c006cb 100644 --- a/3rdparty/libpng/pngwio.c +++ b/3rdparty/libpng/pngwio.c @@ -1,4 +1,3 @@ - /* pngwio.c - functions for data output * * Copyright (c) 2018 Cosmin Truta diff --git a/3rdparty/libpng/pngwrite.c b/3rdparty/libpng/pngwrite.c index 77e412f43d..8b1b06c20c 100644 --- a/3rdparty/libpng/pngwrite.c +++ b/3rdparty/libpng/pngwrite.c @@ -1,7 +1,6 @@ - /* pngwrite.c - general routines to write a PNG file * - * Copyright (c) 2018-2024 Cosmin Truta + * Copyright (c) 2018-2025 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. @@ -128,29 +127,61 @@ png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr) * the application continues writing the PNG. So check the 'invalid' * flag here too. */ -#ifdef PNG_GAMMA_SUPPORTED -# ifdef PNG_WRITE_gAMA_SUPPORTED - if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 && - (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_gAMA) != 0 && - (info_ptr->valid & PNG_INFO_gAMA) != 0) - png_write_gAMA_fixed(png_ptr, info_ptr->colorspace.gamma); -# endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + /* Write unknown chunks first; PNG v3 establishes a precedence order + * for colourspace chunks. It is certain therefore that new + * colourspace chunks will have a precedence and very likely it will be + * higher than all known so far. Writing the unknown chunks here is + * most likely to present the chunks in the most convenient order. + * + * FUTURE: maybe write chunks in the order the app calls png_set_chnk + * to give the app control. + */ + write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_IHDR); #endif +#ifdef PNG_WRITE_sBIT_SUPPORTED + /* PNG v3: a streaming app will need to see this before cICP because + * the information is helpful in handling HLG encoding (which is + * natively 10 bits but gets expanded to 16 in PNG.) + * + * The app shouldn't care about the order ideally, but it might have + * no choice. In PNG v3, apps are allowed to reject PNGs where the + * APNG chunks are out of order so it behooves libpng to be nice here. + */ + if ((info_ptr->valid & PNG_INFO_sBIT) != 0) + png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); +#endif + + /* PNG v3: the July 2004 version of the TR introduced the concept of colour + * space priority. As above it therefore behooves libpng to write the colour + * space chunks in the priority order so that a streaming app need not buffer + * them. + */ #ifdef PNG_COLORSPACE_SUPPORTED - /* Write only one of sRGB or an ICC profile. If a profile was supplied - * and it matches one of the known sRGB ones issue a warning. +# ifdef PNG_WRITE_cICP_SUPPORTED /* Priority 4 */ + if ((info_ptr->valid & PNG_INFO_cICP) != 0) + { + png_write_cICP(png_ptr, + info_ptr->cicp_colour_primaries, + info_ptr->cicp_transfer_function, + info_ptr->cicp_matrix_coefficients, + info_ptr->cicp_video_full_range_flag); + } +# endif + + /* PNG v3 change: it is now permitted to write both sRGB and ICC profiles, + * however because the libpng code auto-generates an sRGB for the + * corresponding ICC profiles and because PNG v2 disallowed this we need + * to only write one. + * + * Remove the PNG v2 warning about writing an sRGB ICC profile as well + * because it's invalid with PNG v3. */ -# ifdef PNG_WRITE_iCCP_SUPPORTED +# ifdef PNG_WRITE_iCCP_SUPPORTED /* Priority 3 */ if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 && (info_ptr->valid & PNG_INFO_iCCP) != 0) { -# ifdef PNG_WRITE_sRGB_SUPPORTED - if ((info_ptr->valid & PNG_INFO_sRGB) != 0) - png_app_warning(png_ptr, - "profile matches sRGB but writing iCCP instead"); -# endif - png_write_iCCP(png_ptr, info_ptr->iccp_name, info_ptr->iccp_profile); } @@ -159,20 +190,24 @@ png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr) # endif # endif -# ifdef PNG_WRITE_sRGB_SUPPORTED +# ifdef PNG_WRITE_sRGB_SUPPORTED /* Priority 2 */ if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 && (info_ptr->valid & PNG_INFO_sRGB) != 0) png_write_sRGB(png_ptr, info_ptr->colorspace.rendering_intent); # endif /* WRITE_sRGB */ #endif /* COLORSPACE */ -#ifdef PNG_WRITE_sBIT_SUPPORTED - if ((info_ptr->valid & PNG_INFO_sBIT) != 0) - png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); +#ifdef PNG_GAMMA_SUPPORTED +# ifdef PNG_WRITE_gAMA_SUPPORTED /* Priority 1 */ + if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 && + (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_gAMA) != 0 && + (info_ptr->valid & PNG_INFO_gAMA) != 0) + png_write_gAMA_fixed(png_ptr, info_ptr->colorspace.gamma); +# endif #endif #ifdef PNG_COLORSPACE_SUPPORTED -# ifdef PNG_WRITE_cHRM_SUPPORTED +# ifdef PNG_WRITE_cHRM_SUPPORTED /* Also priority 1 */ if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 && (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) != 0 && (info_ptr->valid & PNG_INFO_cHRM) != 0) @@ -180,10 +215,6 @@ png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr) # endif #endif -#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED - write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_IHDR); -#endif - png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE; } } diff --git a/3rdparty/libpng/pngwtran.c b/3rdparty/libpng/pngwtran.c index 49a13c1e98..a20847023f 100644 --- a/3rdparty/libpng/pngwtran.c +++ b/3rdparty/libpng/pngwtran.c @@ -1,4 +1,3 @@ - /* pngwtran.c - transforms the data in a row for PNG writers * * Copyright (c) 2018 Cosmin Truta diff --git a/3rdparty/libpng/pngwutil.c b/3rdparty/libpng/pngwutil.c index 14cc4ce367..8b2bf4e6d6 100644 --- a/3rdparty/libpng/pngwutil.c +++ b/3rdparty/libpng/pngwutil.c @@ -1,4 +1,3 @@ - /* pngwutil.c - utilities to write a PNG file * * Copyright (c) 2018-2024 Cosmin Truta @@ -9,12 +8,30 @@ * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer * and license in png.h + * + * This file contains routines that are only called from within + * libpng itself during the course of writing an image. */ #include "pngpriv.h" #ifdef PNG_WRITE_SUPPORTED +#ifdef PNG_WRITE_INTERLACING_SUPPORTED +/* Arrays to facilitate interlacing - use pass (0 - 6) as index. */ + +/* Start of interlace block */ +static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; +/* Offset to next interlace block */ +static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; +/* Start of interlace block in the y direction */ +static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; +/* Offset to next interlace block in the y direction */ +static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; + +/* TODO: Move these arrays to a common utility module to avoid duplication. */ +#endif + #ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED /* Place a 32-bit number into a buffer in PNG byte order. We work * with unsigned numbers for convenience, although one supported @@ -1471,6 +1488,29 @@ png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type) } #endif +#ifdef PNG_WRITE_cICP_SUPPORTED +/* Write the cICP data */ +void /* PRIVATE */ +png_write_cICP(png_structrp png_ptr, + png_byte colour_primaries, png_byte transfer_function, + png_byte matrix_coefficients, png_byte video_full_range_flag) +{ + png_byte buf[4]; + + png_debug(1, "in png_write_cICP"); + + png_write_chunk_header(png_ptr, png_cICP, 4); + + buf[0] = colour_primaries; + buf[1] = transfer_function; + buf[2] = matrix_coefficients; + buf[3] = video_full_range_flag; + png_write_chunk_data(png_ptr, buf, 4); + + png_write_chunk_end(png_ptr); +} +#endif + #ifdef PNG_WRITE_eXIf_SUPPORTED /* Write the Exif data */ void /* PRIVATE */ @@ -1889,22 +1929,6 @@ png_write_tIME(png_structrp png_ptr, png_const_timep mod_time) void /* PRIVATE */ png_write_start_row(png_structrp png_ptr) { -#ifdef PNG_WRITE_INTERLACING_SUPPORTED - /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* Start of interlace block */ - static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* Offset to next interlace block */ - static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - - /* Start of interlace block in the y direction */ - static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - - /* Offset to next interlace block in the y direction */ - static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; -#endif - png_alloc_size_t buf_size; int usr_pixel_depth; @@ -2004,22 +2028,6 @@ png_write_start_row(png_structrp png_ptr) void /* PRIVATE */ png_write_finish_row(png_structrp png_ptr) { -#ifdef PNG_WRITE_INTERLACING_SUPPORTED - /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* Start of interlace block */ - static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* Offset to next interlace block */ - static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - - /* Start of interlace block in the y direction */ - static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - - /* Offset to next interlace block in the y direction */ - static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; -#endif - png_debug(1, "in png_write_finish_row"); /* Next row */ @@ -2095,14 +2103,6 @@ png_write_finish_row(png_structrp png_ptr) void /* PRIVATE */ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) { - /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* Start of interlace block */ - static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* Offset to next interlace block */ - static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - png_debug(1, "in png_do_write_interlace"); /* We don't have to do anything on the last pass (6) */ diff --git a/3rdparty/libpng/powerpc/powerpc_init.c b/3rdparty/libpng/powerpc/powerpc_init.c index 54426c558e..9027480098 100644 --- a/3rdparty/libpng/powerpc/powerpc_init.c +++ b/3rdparty/libpng/powerpc/powerpc_init.c @@ -1,4 +1,3 @@ - /* powerpc_init.c - POWERPC optimised filter functions * * Copyright (c) 2018 Cosmin Truta diff --git a/modules/imgcodecs/include/opencv2/imgcodecs.hpp b/modules/imgcodecs/include/opencv2/imgcodecs.hpp index 2aeac8d60a..a2ce8963b0 100644 --- a/modules/imgcodecs/include/opencv2/imgcodecs.hpp +++ b/modules/imgcodecs/include/opencv2/imgcodecs.hpp @@ -264,8 +264,9 @@ enum ImageMetadataType IMAGE_METADATA_EXIF = 0, // EXIF metadata (e.g., camera info, GPS, orientation) IMAGE_METADATA_XMP = 1, // XMP metadata (eXtensible Metadata Platform - Adobe format) IMAGE_METADATA_ICCP = 2, // ICC Profile (color profile for color management) + IMAGE_METADATA_CICP = 3, // cICP Profile (video signal type) - IMAGE_METADATA_MAX = 2 // Highest valid index (usually used for bounds checking) + IMAGE_METADATA_MAX = 3 // Highest valid index (usually used for bounds checking) }; //! @} imgcodecs_flags diff --git a/modules/imgcodecs/src/grfmt_png.cpp b/modules/imgcodecs/src/grfmt_png.cpp index 9a93f68b70..4ae933e2bb 100644 --- a/modules/imgcodecs/src/grfmt_png.cpp +++ b/modules/imgcodecs/src/grfmt_png.cpp @@ -901,6 +901,7 @@ PngEncoder::PngEncoder() m_support_metadata[IMAGE_METADATA_EXIF] = true; m_support_metadata[IMAGE_METADATA_XMP] = true; m_support_metadata[IMAGE_METADATA_ICCP] = true; + m_support_metadata[IMAGE_METADATA_CICP] = true; op_zstream1.zalloc = NULL; op_zstream2.zalloc = NULL; next_seq_num = 0; @@ -1116,6 +1117,16 @@ bool PngEncoder::write( const Mat& img, const std::vector& params ) #endif static_cast(iccp.size())); } + + std::vector& cicp = m_metadata[IMAGE_METADATA_CICP]; + if (!cicp.empty()) { +#ifdef PNG_cICP_SUPPORTED + CV_CheckEQ((size_t)4, cicp.size(), "The cICP chunk consists of four 1-byte unsigned integers"); + png_set_cICP(png_ptr, info_ptr, cicp[0], cicp[1], cicp[2], cicp[3]); +#else + CV_LOG_WARNING(NULL, "Libpng is too old and does not support cICP."); +#endif + } } png_write_info( png_ptr, info_ptr ); diff --git a/modules/videoio/src/cap_ffmpeg_impl.hpp b/modules/videoio/src/cap_ffmpeg_impl.hpp index d971ca75b3..76c81d855e 100644 --- a/modules/videoio/src/cap_ffmpeg_impl.hpp +++ b/modules/videoio/src/cap_ffmpeg_impl.hpp @@ -686,7 +686,7 @@ void CvCapture_FFMPEG::close() { #ifdef CV_FFMPEG_CODECPAR // avcodec_close removed in FFmpeg release 8.0 -# if (LIBAVCODEC_BUILD < CALC_FFMPEG_VERSION(62, 11, 100)) +# if (LIBAVCODEC_BUILD < CALC_FFMPEG_VERSION(61, 9, 108)) avcodec_close( context ); # endif #endif @@ -1719,7 +1719,16 @@ bool CvCapture_FFMPEG::retrieveFrame(int flag, unsigned char** data, int* step, if (!sw_picture || !sw_picture->data[0]) return false; - CV_LOG_DEBUG(NULL, "Input picture format: " << av_get_pix_fmt_name((AVPixelFormat)sw_picture->format)); + CV_LOG_DEBUG(NULL, "Input picture format: " << av_get_pix_fmt_name((AVPixelFormat)sw_picture->format) << ", colorspace: " +#if LIBAVUTIL_BUILD >= CALC_FFMPEG_VERSION(56, 72, 0) + << av_color_space_name(sw_picture->colorspace) +#else + << av_get_colorspace_name(sw_picture->colorspace) +#endif + << ", range: " << av_color_range_name(sw_picture->color_range) + << ", primaries: " << av_color_primaries_name(sw_picture->color_primaries) + << ", transfer: " << av_color_transfer_name(sw_picture->color_trc) + ); const AVPixelFormat result_format = convertRGB ? AV_PIX_FMT_BGR24 : (AVPixelFormat)sw_picture->format; switch (result_format) { @@ -2009,7 +2018,7 @@ void CvCapture_FFMPEG::get_rotation_angle() #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(57, 68, 100) const uint8_t *data = 0; // av_stream_get_side_data removed in FFmpeg release 8.0 -# if (LIBAVCODEC_BUILD < CALC_FFMPEG_VERSION(62, 11, 100)) +# if (LIBAVCODEC_BUILD < CALC_FFMPEG_VERSION(61, 9, 108)) data = av_stream_get_side_data(video_st, AV_PKT_DATA_DISPLAYMATRIX, NULL); # else AVPacketSideData* sd = video_st->codecpar->coded_side_data; From 98a70539cc01343d5c5319986c1f354ff1e91558 Mon Sep 17 00:00:00 2001 From: Kumataro Date: Mon, 8 Sep 2025 16:35:01 +0900 Subject: [PATCH 12/21] Merge pull request #27730 from Kumataro:fix27729 doc: fix doxygen warnings for imgcodecs, flann and objdetect #27730 Close https://github.com/opencv/opencv/issues/27729 ### 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 --- doc/opencv.bib | 8 -------- modules/flann/include/opencv2/flann/general.h | 4 ++-- modules/imgcodecs/include/opencv2/imgcodecs.hpp | 2 +- modules/objdetect/doc/objdetect.bib | 3 ++- 4 files changed, 5 insertions(+), 12 deletions(-) diff --git a/doc/opencv.bib b/doc/opencv.bib index 8ada758c27..3c3c43936d 100644 --- a/doc/opencv.bib +++ b/doc/opencv.bib @@ -1431,14 +1431,6 @@ publisher = {Kluwer Academic Publishers}, url = {https://www.face-rec.org/algorithms/Boosting-Ensemble/16981346.pdf} } -@inproceedings{wang2016iros, - author = {John Wang and Edwin Olson}, - title = {{AprilTag} 2: Efficient and robust fiducial detection}, - booktitle = {Proceedings of the {IEEE/RSJ} International Conference on Intelligent Robots and Systems {(IROS)}}, - year = {2016}, - month = {October}, - url = {https://april.eecs.umich.edu/pdfs/wang2016iros.pdf} -} @misc{Welch95, author = {Welch, Greg and Bishop, Gary}, title = {An introduction to the Kalman filter}, diff --git a/modules/flann/include/opencv2/flann/general.h b/modules/flann/include/opencv2/flann/general.h index e65cba2f8a..11ea2af645 100644 --- a/modules/flann/include/opencv2/flann/general.h +++ b/modules/flann/include/opencv2/flann/general.h @@ -54,12 +54,12 @@ public: #define FLANN_THROW(TYPE, STR) throw FLANNException(STR) +//! @endcond + #else #define FLANN_THROW(TYPE, STR) CV_Error(TYPE, STR) #endif -//! @endcond - #endif /* OPENCV_FLANN_GENERAL_H_ */ diff --git a/modules/imgcodecs/include/opencv2/imgcodecs.hpp b/modules/imgcodecs/include/opencv2/imgcodecs.hpp index a2ce8963b0..cb020e4c4e 100644 --- a/modules/imgcodecs/include/opencv2/imgcodecs.hpp +++ b/modules/imgcodecs/include/opencv2/imgcodecs.hpp @@ -184,7 +184,7 @@ enum ImwriteTiffResolutionUnitFlags { }; enum ImwriteEXRTypeFlags { - /*IMWRITE_EXR_TYPE_UNIT = 0, //!< not supported */ + // IMWRITE_EXR_TYPE_UNIT = 0, // not supported IMWRITE_EXR_TYPE_HALF = 1, //!< store as HALF (FP16) IMWRITE_EXR_TYPE_FLOAT = 2 //!< store as FP32 (default) }; diff --git a/modules/objdetect/doc/objdetect.bib b/modules/objdetect/doc/objdetect.bib index f3623732d5..9f7f06e672 100644 --- a/modules/objdetect/doc/objdetect.bib +++ b/modules/objdetect/doc/objdetect.bib @@ -16,7 +16,8 @@ title = {{AprilTag} 2: Efficient and robust fiducial detection}, booktitle = {Proceedings of the {IEEE/RSJ} International Conference on Intelligent Robots and Systems {(IROS)}}, year = {2016}, - month = {October} + month = {October}, + url = {https://april.eecs.umich.edu/pdfs/wang2016iros.pdf} } @mastersthesis{Xiangmin2015research, From 54b03cc2f84cfe83222c59b747e17cb378a9744c Mon Sep 17 00:00:00 2001 From: cudawarped <12133430+cudawarped@users.noreply.github.com> Date: Mon, 8 Sep 2025 12:34:49 +0300 Subject: [PATCH 13/21] Merge pull request #27737 from cudawarped:fix_videowriter_raw_return_code [videoio][VideoWriter] Fix return code from CvVideoWriter_FFMPEG::writeFrame() when encapsulating encoded video #27737 Currently the return code from `CvVideoWriter_FFMPEG::writeFrame()` when `encode_video==true` (encapsulating raw encoded video) is wrong and results in the following warning implying it has been unsuccessful > [ WARN:0@15.551] global cap_ffmpeg.cpp:198 write FFmpeg: Failed to write frame ### 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 - [ ] 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/videoio/src/cap_ffmpeg_impl.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/videoio/src/cap_ffmpeg_impl.hpp b/modules/videoio/src/cap_ffmpeg_impl.hpp index 76c81d855e..cda32be873 100644 --- a/modules/videoio/src/cap_ffmpeg_impl.hpp +++ b/modules/videoio/src/cap_ffmpeg_impl.hpp @@ -2531,9 +2531,9 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int if (!encode_video) { CV_Assert(cn == 1 && ((width > 0 && height == 1) || (width == 1 && height > 0 && step == 1))); const bool set_key_frame = key_frame ? key_frame : idr_period ? frame_idx % idr_period == 0 : 1; - bool ret = icv_av_encapsulate_video_FFMPEG(oc, video_st, context, (uint8_t*)data, width, frame_idx, pts_index, b_frame_dts_delay, set_key_frame); + int ret = icv_av_encapsulate_video_FFMPEG(oc, video_st, context, (uint8_t*)data, width, frame_idx, pts_index, b_frame_dts_delay, set_key_frame); frame_idx++; - return ret; + return ret == 0; } // check parameters From b28d9bef1d96d10e9a47d55a63d9f1443e6e3d2b Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Mon, 8 Sep 2025 14:52:58 +0300 Subject: [PATCH 14/21] Renamed templated BlocksCompensator::feed method to exclude claches with base class pure virtual method. --- .../opencv2/stitching/detail/exposure_compensate.hpp | 2 +- modules/stitching/src/exposure_compensate.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/stitching/include/opencv2/stitching/detail/exposure_compensate.hpp b/modules/stitching/include/opencv2/stitching/detail/exposure_compensate.hpp index dea76c957b..2954f32ca3 100644 --- a/modules/stitching/include/opencv2/stitching/detail/exposure_compensate.hpp +++ b/modules/stitching/include/opencv2/stitching/detail/exposure_compensate.hpp @@ -187,7 +187,7 @@ public: protected: template - void feed(const std::vector &corners, const std::vector &images, + void feedWithStrategy(const std::vector &corners, const std::vector &images, const std::vector > &masks); private: diff --git a/modules/stitching/src/exposure_compensate.cpp b/modules/stitching/src/exposure_compensate.cpp index 59542d95ba..f7c33fa4ef 100644 --- a/modules/stitching/src/exposure_compensate.cpp +++ b/modules/stitching/src/exposure_compensate.cpp @@ -460,7 +460,7 @@ void ChannelsCompensator::setMatGains(std::vector& umv) template -void BlocksCompensator::feed(const std::vector &corners, const std::vector &images, +void BlocksCompensator::feedWithStrategy(const std::vector &corners, const std::vector &images, const std::vector > &masks) { CV_Assert(corners.size() == images.size() && images.size() == masks.size()); @@ -605,13 +605,13 @@ void BlocksCompensator::setMatGains(std::vector& umv) void BlocksGainCompensator::feed(const std::vector &corners, const std::vector &images, const std::vector > &masks) { - BlocksCompensator::feed(corners, images, masks); + BlocksCompensator::feedWithStrategy(corners, images, masks); } void BlocksChannelsCompensator::feed(const std::vector &corners, const std::vector &images, const std::vector > &masks) { - BlocksCompensator::feed(corners, images, masks); + BlocksCompensator::feedWithStrategy(corners, images, masks); } From 9663b582a2c8ad26694b1277f8e968e3844e0c1b Mon Sep 17 00:00:00 2001 From: Nadezhda Mizonova Date: Mon, 8 Sep 2025 15:11:20 +0200 Subject: [PATCH 15/21] Merge pull request #27720 from nmizonov:fix_ipp_bilateral_tiling Set limitation to IPP Bilateral Filter tiles number to avoid too small tiles #27720 ### Pull Request Readiness Checklist This PR fixes the following issue in Bilateral Filter tiling in IPP integration: image ROI can't be closer to the image border than the filter window radius. This issue shows itself during separation of the image to tiles for multithreaded processing. If the tile size small enough, the second tile is closer to the upper image border than the bilateral filter radius, which leads to the incorrect result. To fix this, we need a limitation to the tile size - done in this PR. _Note: red build status looks like unrelated to the current change_ See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- modules/imgproc/src/bilateral_filter.dispatch.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/modules/imgproc/src/bilateral_filter.dispatch.cpp b/modules/imgproc/src/bilateral_filter.dispatch.cpp index 9ac499f685..8e0f1f5a95 100644 --- a/modules/imgproc/src/bilateral_filter.dispatch.cpp +++ b/modules/imgproc/src/bilateral_filter.dispatch.cpp @@ -410,7 +410,16 @@ static bool ipp_bilateralFilter(Mat &src, Mat &dst, int d, double sigmaColor, do if(!ok) return false; - parallel_for_(range, invoker, threads*4); + // Tile height can't be smaller than the radius. + // Otherwise, the second tile has mixed top border (pixels from both + // inmem and outside should be used), which is not supported in IPP. + int maxTiles = (int)iwDst.m_size.height / radius; + int numTiles = threads * 4; + if (numTiles > maxTiles) { + // Keep the tiles number as multiple of threads for the better workload balance. + numTiles = (maxTiles / threads) * threads; + } + parallel_for_(range, invoker, numTiles); if(!ok) return false; From 9196edd299a2b0a20149ce7a0ff94a3ff9400854 Mon Sep 17 00:00:00 2001 From: Kumataro Date: Tue, 9 Sep 2025 15:23:43 +0900 Subject: [PATCH 16/21] Merge pull request #27559 from Kumataro:fix27555 imgcodecs: bmp: support to write 32bpp BMP with BI_BITFIELDS #27559 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- .../imgcodecs/include/opencv2/imgcodecs.hpp | 12 ++++ modules/imgcodecs/src/grfmt_bmp.cpp | 60 ++++++++++++++++++- modules/imgcodecs/test/test_grfmt.cpp | 60 ++++++++++++++++++- modules/imgcodecs/test/test_precomp.hpp | 17 ++++++ 4 files changed, 145 insertions(+), 4 deletions(-) diff --git a/modules/imgcodecs/include/opencv2/imgcodecs.hpp b/modules/imgcodecs/include/opencv2/imgcodecs.hpp index cb020e4c4e..eaf62c561f 100644 --- a/modules/imgcodecs/include/opencv2/imgcodecs.hpp +++ b/modules/imgcodecs/include/opencv2/imgcodecs.hpp @@ -119,6 +119,7 @@ enum ImwriteFlags { IMWRITE_JPEGXL_EFFORT = 641,//!< For JPEG XL, encoder effort/speed level without affecting decoding speed; it is between 1 (fastest) and 10 (slowest). Default is 7. IMWRITE_JPEGXL_DISTANCE = 642,//!< For JPEG XL, distance level for lossy compression: target max butteraugli distance, lower = higher quality, 0 = lossless; range: 0 .. 25. Default is 1. IMWRITE_JPEGXL_DECODING_SPEED = 643,//!< For JPEG XL, decoding speed tier for the provided options; minimum is 0 (slowest to decode, best quality/density), and maximum is 4 (fastest to decode, at the cost of some quality/density). Default is 0. + IMWRITE_BMP_COMPRESSION = 768, //!< For BMP, use to specify compress parameter for 32bpp image. Default is IMWRITE_BMP_COMPRESSION_BITFIELDS. See cv::ImwriteBMPCompressionFlags. IMWRITE_GIF_LOOP = 1024, //!< Not functional since 4.12.0. Replaced by cv::Animation::loop_count. IMWRITE_GIF_SPEED = 1025, //!< Not functional since 4.12.0. Replaced by cv::Animation::durations. IMWRITE_GIF_QUALITY = 1026, //!< For GIF, it can be a quality from 1 to 8. Default is 2. See cv::ImwriteGifCompressionFlags. @@ -245,6 +246,12 @@ enum ImwriteHDRCompressionFlags { IMWRITE_HDR_COMPRESSION_RLE = 1 }; +//! Imwrite BMP specific values for IMWRITE_BMP_COMPRESSION parameter key. +enum ImwriteBMPCompressionFlags { + IMWRITE_BMP_COMPRESSION_RGB = 0, //!< Use BI_RGB. OpenCV v4.12.0 or before supports to encode with this compression only. + IMWRITE_BMP_COMPRESSION_BITFIELDS = 3, //!< Use BI_BITFIELDS. OpenCV v4.13.0 or later can support to encode with this compression. (only for 32 BPP images) +}; + //! Imwrite GIF specific values for IMWRITE_GIF_QUALITY parameter key, if larger than 3, then its related to the size of the color table. enum ImwriteGIFCompressionFlags { IMWRITE_GIF_FAST_NO_DITHER = 1, @@ -499,6 +506,11 @@ filename extension (see cv::imread for the list of extensions). In general, only single-channel or 3-channel (with 'BGR' channel order) images can be saved using this function, with these exceptions: +- With BMP encoder, 8-bit unsigned (CV_8U) images can be saved. + - BMP images with an alpha channel can be saved using this function. + To achieve this, create an 8-bit 4-channel (CV_8UC4) BGRA image, ensuring the alpha channel is the last component. + Fully transparent pixels should have an alpha value of 0, while fully opaque pixels should have an alpha value of 255. + OpenCV v4.13.0 or later use BI_BITFIELDS compression as default. See IMWRITE_BMP_COMPRESSION. - With OpenEXR encoder, only 32-bit float (CV_32F) images can be saved. More than 4 channels can be saved. (imread can load it then.) - 8-bit unsigned (CV_8U) images are not supported. - With Radiance HDR encoder, non 64-bit float (CV_64F) images can be saved. diff --git a/modules/imgcodecs/src/grfmt_bmp.cpp b/modules/imgcodecs/src/grfmt_bmp.cpp index a8ca6a046a..faff17811e 100644 --- a/modules/imgcodecs/src/grfmt_bmp.cpp +++ b/modules/imgcodecs/src/grfmt_bmp.cpp @@ -42,6 +42,7 @@ #include "precomp.hpp" #include "grfmt_bmp.hpp" +#include "opencv2/core/utils/logger.hpp" namespace cv { @@ -603,6 +604,7 @@ BmpEncoder::BmpEncoder() { m_description = "Windows bitmap (*.bmp;*.dib)"; m_buf_supported = true; + m_supported_encode_key = {IMWRITE_BMP_COMPRESSION}; } @@ -615,11 +617,12 @@ ImageEncoder BmpEncoder::newEncoder() const return makePtr(); } -bool BmpEncoder::write( const Mat& img, const std::vector& ) +bool BmpEncoder::write( const Mat& img, const std::vector& params ) { int width = img.cols, height = img.rows, channels = img.channels(); int fileStep = (width*channels + 3) & -4; uchar zeropad[] = "\0\0\0\0"; + WLByteStream strm; if( m_buf ) @@ -630,7 +633,35 @@ bool BmpEncoder::write( const Mat& img, const std::vector& ) else if( !strm.open( m_filename )) return false; - int bitmapHeaderSize = 40; + // sRGB colorspace requires BITMAPV5HEADER. + // See https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapv5header + bool useV5BitFields = true; + for(size_t i = 0 ; i < params.size(); i++) + { + const int value = params[i+1]; + switch(params[i]) + { + case IMWRITE_BMP_COMPRESSION: + { + switch(value) { + case IMWRITE_BMP_COMPRESSION_RGB: + useV5BitFields = false; + break; + case IMWRITE_BMP_COMPRESSION_BITFIELDS: + useV5BitFields = true; + break; + default: + useV5BitFields = true; + CV_LOG_WARNING(nullptr, cv::format("The value(%d) for IMWRITE_BMP_COMPRESSION must be one of ImwriteBMPCompressionFlags. It is fallbacked to true", value)); + break; + } + } + break; + } + } + useV5BitFields &= (channels == 4); // BMP_BITFIELDS requires 32 bit per pixel. + + int bitmapHeaderSize = useV5BitFields ? 124 : 40; int paletteSize = channels > 1 ? 0 : 1024; int headerSize = 14 /* fileheader */ + bitmapHeaderSize + paletteSize; size_t fileSize = (size_t)fileStep*height + headerSize; @@ -653,13 +684,36 @@ bool BmpEncoder::write( const Mat& img, const std::vector& ) CHECK_WRITE(strm.putDWord( height )); CHECK_WRITE(strm.putWord( 1 )); CHECK_WRITE(strm.putWord( channels << 3 )); - CHECK_WRITE(strm.putDWord( BMP_RGB )); + CHECK_WRITE(strm.putDWord( useV5BitFields ? BMP_BITFIELDS : BMP_RGB )); CHECK_WRITE(strm.putDWord( 0 )); CHECK_WRITE(strm.putDWord( 0 )); CHECK_WRITE(strm.putDWord( 0 )); CHECK_WRITE(strm.putDWord( 0 )); CHECK_WRITE(strm.putDWord( 0 )); + if( useV5BitFields ) + { + CHECK_WRITE(strm.putDWord( 0x00FF0000 )); // bV5RedMask + CHECK_WRITE(strm.putDWord( 0x0000FF00 )); // bV5GreenMask + CHECK_WRITE(strm.putDWord( 0x000000FF )); // bV5BlueMask + CHECK_WRITE(strm.putDWord( 0xFF000000 )); // bV5AlphaMask + CHECK_WRITE(strm.putBytes( "BGRs", 4)); // bV5CSType (sRGB) + { // bV5Endpoints + for(int index_rgb = 0; index_rgb < 3; index_rgb ++ ){ // Red/Green/Blue + CHECK_WRITE(strm.putDWord( 0 )); // ciexyzX + CHECK_WRITE(strm.putDWord( 0 )); // ciexyzY + CHECK_WRITE(strm.putDWord( 0 )); // ciexyzZ + } + } + CHECK_WRITE(strm.putDWord( 0 )); // bV5GammaRed + CHECK_WRITE(strm.putDWord( 0 )); // bV5GammaGreen + CHECK_WRITE(strm.putDWord( 0 )); // bV5GammaBlue + CHECK_WRITE(strm.putDWord( 0 )); // bV5Intent + CHECK_WRITE(strm.putDWord( 0 )); // bV5ProfileData + CHECK_WRITE(strm.putDWord( 0 )); // bV5ProfileSize + CHECK_WRITE(strm.putDWord( 0 )); // bV5Reserved + } + if( channels == 1 ) { FillGrayPalette( palette, 8 ); diff --git a/modules/imgcodecs/test/test_grfmt.cpp b/modules/imgcodecs/test/test_grfmt.cpp index 3ef0c9d6fb..87d8780442 100644 --- a/modules/imgcodecs/test/test_grfmt.cpp +++ b/modules/imgcodecs/test/test_grfmt.cpp @@ -360,7 +360,16 @@ TEST(Imgcodecs_Bmp, read_32bit_rgb) const string root = cvtest::TS::ptr()->get_data_path(); const string filenameInput = root + "readwrite/test_32bit_rgb.bmp"; - const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED); + Mat img; + ASSERT_NO_THROW(img = cv::imread(filenameInput)); + ASSERT_FALSE(img.empty()); + ASSERT_EQ(CV_8UC3, img.type()); + + ASSERT_NO_THROW(img = cv::imread(filenameInput, IMREAD_UNCHANGED)); + ASSERT_FALSE(img.empty()); + ASSERT_EQ(CV_8UC3, img.type()); + + ASSERT_NO_THROW(img = cv::imread(filenameInput, IMREAD_COLOR | IMREAD_ANYCOLOR | IMREAD_ANYDEPTH)); ASSERT_FALSE(img.empty()); ASSERT_EQ(CV_8UC3, img.type()); } @@ -427,6 +436,55 @@ TEST(Imgcodecs_Bmp, rgba_scale) ASSERT_EQ(data[0], 255); } +typedef testing::TestWithParam Imgcodecs_bmp_compress; +TEST_P(Imgcodecs_bmp_compress, rgba32bpp) +{ + const ImwriteBMPCompressionFlags comp = GetParam(); + + RNG rng = theRNG(); + Mat src(256, 256, CV_8UC4); + rng.fill(src, RNG::UNIFORM, Scalar(0,0,0,0), Scalar(255,255,255,255)); + + vector buf; + bool ret = false; + ASSERT_NO_THROW(ret = cv::imencode(".bmp", src, buf, {IMWRITE_BMP_COMPRESSION, static_cast(comp)})); + ASSERT_TRUE(ret); + + ASSERT_EQ(buf[0x0e], comp == IMWRITE_BMP_COMPRESSION_RGB ? 40 : 124 ); // the size of header + ASSERT_EQ(buf[0x0f], 0); + ASSERT_EQ(buf[0x1c], 32); // the number of bits per pixel = 32 + ASSERT_EQ(buf[0x1d], 0); + ASSERT_EQ(buf[0x1e], static_cast(comp)); // the compression method + ASSERT_EQ(buf[0x1f], 0); + ASSERT_EQ(buf[0x20], 0); + ASSERT_EQ(buf[0x21], 0); + + Mat dst; + ASSERT_NO_THROW(dst = cv::imdecode(buf, IMREAD_UNCHANGED)); + ASSERT_FALSE(dst.empty()); + + if(comp == IMWRITE_BMP_COMPRESSION_RGB) + { + // If BI_RGB is used, output BMP file stores RGB image. + ASSERT_EQ(CV_8UC3, dst.type()); + Mat srcBGR; + cv::cvtColor(src, srcBGR, cv::COLOR_BGRA2BGR); + EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), srcBGR, dst); + } + else + { + // If BI_BITFIELDS is used, output BMP file stores RGBA image. + ASSERT_EQ(CV_8UC4, dst.type()); + EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), src, dst); + } + +} +INSTANTIATE_TEST_CASE_P(All, + Imgcodecs_bmp_compress, + testing::Values( + IMWRITE_BMP_COMPRESSION_RGB, + IMWRITE_BMP_COMPRESSION_BITFIELDS)); + #ifdef HAVE_IMGCODEC_HDR TEST(Imgcodecs_Hdr, regression) { diff --git a/modules/imgcodecs/test/test_precomp.hpp b/modules/imgcodecs/test/test_precomp.hpp index d2095932e8..67c5e95168 100644 --- a/modules/imgcodecs/test/test_precomp.hpp +++ b/modules/imgcodecs/test/test_precomp.hpp @@ -80,6 +80,23 @@ void PrintTo(const ImreadModes& val, std::ostream* os) *os << "IMREAD_UNKNOWN(" << (int)v << ")"; } +static inline +void PrintTo(const ImwriteBMPCompressionFlags& val, std::ostream* os) +{ + switch(val) + { + case IMWRITE_BMP_COMPRESSION_RGB: + *os << "IMWRITE_BMP_COMPRESSION_RGB"; + break; + case IMWRITE_BMP_COMPRESSION_BITFIELDS: + *os << "IMWRITE_BMP_COMPRESSION_BITFIELDS"; + break; + default: + *os << "IMWRITE_BMP_COMPRESSION_UNKNOWN(" << (int)val << ")"; + break; + } +} + } // namespace #endif From 7e3550dff808c274c097c4389653ced0ed80136e Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Tue, 9 Sep 2025 09:53:08 +0200 Subject: [PATCH 17/21] Update Conan URL to use official Conan Center Signed-off-by: Uilian Ries --- .../introduction/general_install/general_install.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/tutorials/introduction/general_install/general_install.markdown b/doc/tutorials/introduction/general_install/general_install.markdown index 7b0c5d2b06..e8c679e508 100644 --- a/doc/tutorials/introduction/general_install/general_install.markdown +++ b/doc/tutorials/introduction/general_install/general_install.markdown @@ -26,7 +26,7 @@ Other organizations and people maintain their own binary distributions of OpenCV - System packages in popular Linux distributions (https://pkgs.org/search/?q=opencv) - PyPI (https://pypi.org/search/?q=opencv) - Conda (https://anaconda.org/search?q=opencv) -- Conan (https://github.com/conan-community/conan-opencv) +- Conan (https://conan.io/center/recipes/opencv) - vcpkg (https://github.com/microsoft/vcpkg/tree/master/ports/opencv) - NuGet (https://www.nuget.org/packages?q=opencv) - Brew (https://formulae.brew.sh/formula/opencv) From 8e0c0dc347f7fdbfd8dc405c2706e911c8ba7a4a Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Tue, 9 Sep 2025 14:21:18 +0300 Subject: [PATCH 18/21] Merge pull request #27755 from dkurt:ffmpeg/sws_scale_frame Optimize FFmpeg VideoCapture with swscale threads option #27755 ### Pull Request Readiness Checklist resolves https://github.com/opencv/opencv/issues/21969 * Switch to `sws_scale_from` for `libswscale >= 6.4.100` (FFmpeg >= 5.0) * Use new context init API with threads option (`libswscale >= 8.12.100`: https://github.com/FFmpeg/FFmpeg/commit/2a091d4f2ee1e367d05a6bbbe96b204257cbda87) * Replicate `sws_getCachedContext` with threads option for `libswscale < 8.12.100` 1 hour mp4 video every frame reading | HW | sws_scale | sws_scale_frame + 16 threads | sws_scale_frame + 24 threads (#cpus) | |---|---|---|---| | Intel Core i9-12900 CPU | 45.1 sec | 25.4 sec (x1.77) | 30 sec (x1.50) | | NVIDIA GPU 4090 | 232 sec | 89.4 sec (x2.59) | 77 sec (x3.01) | ``` import time import numpy as np import os import cv2 as cv # os.environ["OPENCV_FFMPEG_CAPTURE_OPTIONS"] = "hwaccel;cuvid|video_codec;h264_cuvid|vsync;0" start = time.time() video = "test.mp4" cap = cv.VideoCapture(video, cv.CAP_FFMPEG) while True: has_frame, frame = cap.read() if not has_frame: break print(time.time() - start) ``` See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake --- modules/videoio/src/cap_ffmpeg_impl.hpp | 71 ++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 8 deletions(-) diff --git a/modules/videoio/src/cap_ffmpeg_impl.hpp b/modules/videoio/src/cap_ffmpeg_impl.hpp index cda32be873..ed1d99bdb0 100644 --- a/modules/videoio/src/cap_ffmpeg_impl.hpp +++ b/modules/videoio/src/cap_ffmpeg_impl.hpp @@ -607,6 +607,7 @@ struct CvCapture_FFMPEG int hw_device; int use_opencl; int extraDataIdx; + int requestedThreads; }; void CvCapture_FFMPEG::init() @@ -658,6 +659,7 @@ void CvCapture_FFMPEG::init() hw_device = -1; use_opencl = 0; extraDataIdx = 1; + requestedThreads = cv::getNumberOfCPUs(); } @@ -993,13 +995,7 @@ inline void fill_codec_context(AVCodecContext * enc, AVDictionary * dict) if (!enc->thread_count) { int nCpus = cv::getNumberOfCPUs(); - int requestedThreads = std::min(nCpus, 16); // [OPENCV:FFMPEG:24] Application has requested XX threads. Using a thread count greater than 16 is not recommended. - std::string threads_option = utils::getConfigurationParameterString("OPENCV_FFMPEG_THREADS"); - if (!threads_option.empty()) - { - requestedThreads = atoi(threads_option.c_str()); - } - enc->thread_count = requestedThreads; + enc->thread_count = std::min(nCpus, 16); // [OPENCV:FFMPEG:24] Application has requested XX threads. Using a thread count greater than 16 is not recommended. } AVDictionaryEntry* avdiscard_entry = av_dict_get(dict, "avdiscard", NULL, 0); @@ -1120,7 +1116,7 @@ bool CvCapture_FFMPEG::open(const char* _filename, const Ptr& str #endif if (params.has(CAP_PROP_N_THREADS)) { - nThreads = params.get(CAP_PROP_N_THREADS); + nThreads = requestedThreads = params.get(CAP_PROP_N_THREADS); } if (params.warnUnusedParameters()) { @@ -1129,6 +1125,15 @@ bool CvCapture_FFMPEG::open(const char* _filename, const Ptr& str } } + if (params.empty() || !params.has(CAP_PROP_N_THREADS)) + { + std::string threads_option = utils::getConfigurationParameterString("OPENCV_FFMPEG_THREADS"); + if (!threads_option.empty()) + { + nThreads = requestedThreads = atoi(threads_option.c_str()); + } + } + #if USE_AV_INTERRUPT_CALLBACK /* interrupt callback */ interrupt_metadata.timeout_after_ms = open_timeout; @@ -1748,6 +1753,51 @@ bool CvCapture_FFMPEG::retrieveFrame(int flag, unsigned char** data, int* step, frame.height != video_st->CV_FFMPEG_CODEC_FIELD->height || frame.data == NULL ) { +#if LIBSWSCALE_BUILD >= CALC_FFMPEG_VERSION(6, 4, 100) + int buffer_width = video_st->CV_FFMPEG_CODEC_FIELD->width; + int buffer_height = video_st->CV_FFMPEG_CODEC_FIELD->height; + + // Reproduce sws_getCachedContext but with threads option + int64_t src_h_chr_pos = -513, dst_h_chr_pos = -513, + src_v_chr_pos = -513, dst_v_chr_pos = -513; + if (img_convert_ctx) + { + av_opt_get_int(img_convert_ctx, "src_h_chr_pos", 0, &src_h_chr_pos); + av_opt_get_int(img_convert_ctx, "src_v_chr_pos", 0, &src_v_chr_pos); + av_opt_get_int(img_convert_ctx, "dst_h_chr_pos", 0, &dst_h_chr_pos); + av_opt_get_int(img_convert_ctx, "dst_v_chr_pos", 0, &dst_v_chr_pos); + sws_freeContext(img_convert_ctx); + img_convert_ctx = NULL; + } + + img_convert_ctx = sws_alloc_context(); + if (img_convert_ctx == NULL) + return false;//CV_Error(0, "Cannot initialize the conversion context!"); + + av_opt_set_int(img_convert_ctx, "sws_flags", SWS_BICUBIC, 0); + av_opt_set_int(img_convert_ctx, "threads", requestedThreads, 0); + + if (swscale_version() < CALC_FFMPEG_VERSION(8, 12, 100)) + { + av_opt_set_int(img_convert_ctx, "src_h_chr_pos", src_h_chr_pos, 0); + av_opt_set_int(img_convert_ctx, "src_v_chr_pos", src_v_chr_pos, 0); + av_opt_set_int(img_convert_ctx, "dst_h_chr_pos", dst_h_chr_pos, 0); + av_opt_set_int(img_convert_ctx, "dst_v_chr_pos", dst_v_chr_pos, 0); + av_opt_set_int(img_convert_ctx, "srcw", buffer_width, 0); + av_opt_set_int(img_convert_ctx, "srch", buffer_height, 0); + av_opt_set_int(img_convert_ctx, "dstw", buffer_width, 0); + av_opt_set_int(img_convert_ctx, "dsth", buffer_height, 0); + av_opt_set_pixel_fmt(img_convert_ctx, "src_format", (AVPixelFormat)sw_picture->format, 0); + av_opt_set_pixel_fmt(img_convert_ctx, "dst_format", result_format, 0); + av_opt_set_double(img_convert_ctx, "param0", SWS_PARAM_DEFAULT, 0); + av_opt_set_double(img_convert_ctx, "param1", SWS_PARAM_DEFAULT, 0); + + if (sws_init_context(img_convert_ctx, NULL, NULL) < 0) { + sws_freeContext(img_convert_ctx); + img_convert_ctx = NULL; + } + } +#else // Some sws_scale optimizations have some assumptions about alignment of data/step/width/height // Also we use coded_width/height to workaround problem with legacy ffmpeg versions (like n0.8) int buffer_width = context->coded_width, buffer_height = context->coded_height; @@ -1761,6 +1811,7 @@ bool CvCapture_FFMPEG::retrieveFrame(int flag, unsigned char** data, int* step, SWS_BICUBIC, NULL, NULL, NULL ); +#endif if (img_convert_ctx == NULL) return false;//CV_Error(0, "Cannot initialize the conversion context!"); @@ -1790,6 +1841,9 @@ bool CvCapture_FFMPEG::retrieveFrame(int flag, unsigned char** data, int* step, frame.step = rgb_picture.linesize[0]; } +#if LIBSWSCALE_BUILD >= CALC_FFMPEG_VERSION(6, 4, 100) + sws_scale_frame(img_convert_ctx, &rgb_picture, sw_picture); +#else sws_scale( img_convert_ctx, sw_picture->data, @@ -1798,6 +1852,7 @@ bool CvCapture_FFMPEG::retrieveFrame(int flag, unsigned char** data, int* step, rgb_picture.data, rgb_picture.linesize ); +#endif *data = frame.data; *step = frame.step; From ae86b400cc281a5f0dad778cb2e7a551ebc16067 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Tue, 9 Sep 2025 16:13:43 +0300 Subject: [PATCH 19/21] Remove libavresample from CMake as it's not used in code. --- CMakeLists.txt | 1 - modules/videoio/cmake/detect_ffmpeg.cmake | 7 ------- modules/videoio/misc/plugin_ffmpeg/CMakeLists.txt | 1 - 3 files changed, 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ccb0700a1..a4c8cfceb6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1636,7 +1636,6 @@ if(WITH_FFMPEG OR HAVE_FFMPEG) status(" avformat:" FFMPEG_libavformat_VERSION THEN "YES (${FFMPEG_libavformat_VERSION})" ELSE NO) status(" avutil:" FFMPEG_libavutil_VERSION THEN "YES (${FFMPEG_libavutil_VERSION})" ELSE NO) status(" swscale:" FFMPEG_libswscale_VERSION THEN "YES (${FFMPEG_libswscale_VERSION})" ELSE NO) - status(" avresample:" FFMPEG_libavresample_VERSION THEN "YES (${FFMPEG_libavresample_VERSION})" ELSE NO) if(OPENCV_FFMPEG_ENABLE_LIBAVDEVICE) status(" avdevice:" FFMPEG_libavdevice_VERSION THEN "YES (${FFMPEG_libavdevice_VERSION})" ELSE NO) endif() diff --git a/modules/videoio/cmake/detect_ffmpeg.cmake b/modules/videoio/cmake/detect_ffmpeg.cmake index aa669f36b0..1d4faa8394 100644 --- a/modules/videoio/cmake/detect_ffmpeg.cmake +++ b/modules/videoio/cmake/detect_ffmpeg.cmake @@ -27,11 +27,6 @@ set(_used_ffmpeg_libraries ${_required_ffmpeg_libraries}) if(NOT HAVE_FFMPEG AND PKG_CONFIG_FOUND) ocv_check_modules(FFMPEG libavcodec libavformat libavutil libswscale) if(FFMPEG_FOUND) - ocv_check_modules(FFMPEG_libavresample libavresample) # optional - if(FFMPEG_libavresample_FOUND) - list(APPEND FFMPEG_LIBRARIES ${FFMPEG_libavresample_LIBRARIES}) - list(APPEND _used_ffmpeg_libraries libavresample) - endif() if(OPENCV_FFMPEG_ENABLE_LIBAVDEVICE) ocv_check_modules(FFMPEG_libavdevice libavdevice) # optional if(FFMPEG_libavdevice_FOUND) @@ -60,7 +55,6 @@ if(HAVE_FFMPEG AND NOT HAVE_FFMPEG_WRAPPER) set(_min_libavformat_version 54.20.4) set(_min_libavutil_version 52.3.0) set(_min_libswscale_version 2.1.1) - set(_min_libavresample_version 1.0.1) set(_min_libavdevice_version 53.2.0) foreach(ffmpeg_lib ${_used_ffmpeg_libraries}) if(FFMPEG_${ffmpeg_lib}_VERSION VERSION_LESS _min_${ffmpeg_lib}_version) @@ -77,7 +71,6 @@ if(HAVE_FFMPEG AND NOT HAVE_FFMPEG_WRAPPER) unset(_min_libavformat_version) unset(_min_libavutil_version) unset(_min_libswscale_version) - unset(_min_libavresample_version) unset(_min_libavdevice_version) endif() diff --git a/modules/videoio/misc/plugin_ffmpeg/CMakeLists.txt b/modules/videoio/misc/plugin_ffmpeg/CMakeLists.txt index 204a425b17..212d8e8bba 100644 --- a/modules/videoio/misc/plugin_ffmpeg/CMakeLists.txt +++ b/modules/videoio/misc/plugin_ffmpeg/CMakeLists.txt @@ -15,7 +15,6 @@ message(STATUS "FFMPEG_libavcodec_VERSION=${FFMPEG_libavcodec_VERSION}") message(STATUS "FFMPEG_libavformat_VERSION=${FFMPEG_libavformat_VERSION}") message(STATUS "FFMPEG_libavutil_VERSION=${FFMPEG_libavutil_VERSION}") message(STATUS "FFMPEG_libswscale_VERSION=${FFMPEG_libswscale_VERSION}") -message(STATUS "FFMPEG_libavresample_VERSION=${FFMPEG_libavresample_VERSION}") if(OPENCV_FFMPEG_ENABLE_LIBAVDEVICE) message(STATUS "FFMPEG_libavdevice_VERSION=${FFMPEG_libavdevice_VERSION}") endif() From eed87abbcf7655e644883b6629c97c75ab6cd6c2 Mon Sep 17 00:00:00 2001 From: Kavyansh Tyagi <142140238+KAVYANSHTYAGI@users.noreply.github.com> Date: Tue, 9 Sep 2025 23:21:14 +0530 Subject: [PATCH 20/21] Fix typos in Einsum layer and G-API docs --- modules/dnn/src/layers/einsum_layer.cpp | 60 +++++++++++----------- modules/gapi/include/opencv2/gapi/core.hpp | 6 +-- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/modules/dnn/src/layers/einsum_layer.cpp b/modules/dnn/src/layers/einsum_layer.cpp index 59157763a1..ff1062badb 100644 --- a/modules/dnn/src/layers/einsum_layer.cpp +++ b/modules/dnn/src/layers/einsum_layer.cpp @@ -231,7 +231,7 @@ Mat Diagonal(const Mat& input, int dim1, int dim2) } } - // Permutate the input so that the dims from which we need the diagonal forms the innermost dims + // Permute the input so that the dims from which we need the diagonal form the innermost dims Mat transposed = Transpose(input, input_dims, permutation); // Parse the diagonal from the innermost dims @@ -245,7 +245,7 @@ Mat Diagonal(const Mat& input, int dim1, int dim2) reverse_permutation[perm] = iter++; } - // Permutate using the reverse permutation to get back the original axes ordering + // Permute using the reverse permutation to get back the original axes ordering // (Pass in CPU Transpose function here as this Diagonal method will only be used for CPU based diagonal parsing) output = Transpose(output, shape(output), reverse_permutation); } else { @@ -298,19 +298,19 @@ public: // Preprocessed inputs std::vector preProcessedInputs; - // This is container for preporcessed inputs + // This container holds preprocessed inputs std::vector homogenizedInputDims; - // Collect outpus dimentions - MatShape einsumOutDims; // vector to store output dimentions + // Collect output dimensions + MatShape einsumOutDims; // vector to store output dimensions - // These hold equation subring, left hand side and right it of + // These hold equation substrings: the left-hand side, right-hand side, and the full equation String lhs_eq, rhs_eq, equation; - // Holds token from left hand side of the equation + // Holds tokens from the left-hand side of the equation std::vector lhs_eq_tokens; - // Idicates if equation substring is defined in explit way such as "ij, jk->ik" + // Indicates if the equation substring is defined in an explicit way such as "ij, jk->ik" // as opposed to "ij->" bool explicitEquation = false; @@ -329,14 +329,14 @@ public: // A value of -1 means the corresponding subscript index is not found in the output std::vector subscriptIndicesToOutputIndices; - // Hold max number of alphabetic numbers + // Holds the max number of alphabetic characters static const size_t numOfLetters = 52; // Stores the count corresponding to each letter encountered // A value of `0` indicates that the corresponding letter hasn't been seen at all std::array letter2count; - // Hold the assigned index corresponding to the letter seen + // Holds the assigned index corresponding to the letter seen // `-1` means the corresponding letter wasn't seen at all std::array letter2index; @@ -359,7 +359,7 @@ public: void calculateOutputShape(); void preProcessInputs(InputArrayOfArrays& inputs); Mat reduceSum(Mat& src, MatShape& reduceAxis); - Mat FinalizeOutput(const Mat& candidateOuput, const MatShape& ordered_subscript_indices_in_candidate); + Mat FinalizeOutput(const Mat& candidateOutput, const MatShape& ordered_subscript_indices_in_candidate); Mat pairwiseOperandProcess( const Mat& left, const MatShape& leftShapeOverride, @@ -410,12 +410,12 @@ public: letter2count.fill(0); letter2index.fill(-1); - // parser equation and extract tokens from the equation - // save token to lhs_eq_tokens variable + // parse equation and extract tokens from the equation + // save tokens to lhs_eq_tokens vector parseEquation(equation); // TODO: return lhs_eq_tokens // Start preprocessing related to equation parsing - // and dimention broadcasting + // and dimension broadcasting processEquation(einsumInpShapes); processBroadcastedDims(); @@ -429,7 +429,7 @@ public: backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH; } - // getMeoryShapes + // getMemoryShapes bool getMemoryShapes(const std::vector &inputs, const int requiredOutputs, std::vector &outputs, @@ -439,7 +439,7 @@ public: // check if passed and parsed inputs match up in number and dimensions CV_CheckEQ(static_cast(inputs.size()), numInputs, - "Number of inputs in forward and inputs during graph constructions do not match"); + "Number of inputs in forward and inputs during graph construction do not match"); for (int i = 0; i < numInputs; i++) { if (inputs[i] != einsumInpShapes[i]) @@ -459,7 +459,7 @@ public: { CV_TRACE_FUNCTION(); CV_TRACE_ARG_VALUE(name, "name", name.c_str()); - CV_CheckEQ((size_t)inputs_arr.total(), (size_t)numInputs, "Number of inputs in forward and inputs during graph constructions do not match"); + CV_CheckEQ((size_t)inputs_arr.total(), (size_t)numInputs, "Number of inputs in forward and inputs during graph construction do not match"); if (inputs_arr.depth() == CV_16F) { @@ -549,14 +549,14 @@ public: } } - // check of product of output dimentions and computed output dimentions match + // check that product of output dimensions and computed output dimensions match size_t reqProd = std::accumulate(einsumOutDims.begin(), einsumOutDims.end(), 1, std::multiplies()); MatShape realOutputDims = shape(result); size_t realProd = std::accumulate(realOutputDims.begin(), realOutputDims.end(), 1, std::multiplies()); CV_CheckEQ(reqProd, realProd, "Real output can not be shaped in to required output"); - // reduce dimentions + // reduce dimensions result = result.reshape(1, einsumOutDims.size(), einsumOutDims.data()); result.copyTo(outputs[0]); } // forward @@ -633,20 +633,20 @@ void LayerEinsumImpl::preProcessInputs(InputArrayOfArrays& inputs_arr) // same axes order MatShape homogenizedInputDims_(numLetterIndices, 1); - int dimIndexInIreprocessedInput = 0; + int dimIndexInPreprocessedInput = 0; int dimIndexInOriginalInput = 0; for (const auto& subscriptIndex : currSubscriptIndices) { if(subscriptIndicesToInputIndex[subscriptIndex] == -1){ - subscriptIndicesToInputIndex[subscriptIndex] = dimIndexInIreprocessedInput++; + subscriptIndicesToInputIndex[subscriptIndex] = dimIndexInPreprocessedInput++; homogenizedInputDims_[subscriptIndex] = input_dims[dimIndexInOriginalInput]; } else { // Call diagonal preprocessed = Diagonal( !preprocessed.empty() ? preprocessed : inputs[inputIter], subscriptIndicesToInputIndex[subscriptIndex], - dimIndexInIreprocessedInput); + dimIndexInPreprocessedInput); } ++dimIndexInOriginalInput; } @@ -689,7 +689,7 @@ void LayerEinsumImpl::parseEquation(String equation) std::size_t arrow_idx = equation.find("->"); if (arrow_idx != std::string::npos) { - // split left and righ hand sides of the equation + // split left- and right-hand sides of the equation lhs_eq = equation.substr(0, arrow_idx); rhs_eq = equation.substr(arrow_idx + 2); explicitEquation = true; @@ -746,7 +746,7 @@ void LayerEinsumImpl::calculateOutputShape() CV_CheckNE(letterIndex, -1, "The only permissible subscript labels are lowercase letters (a-z) and uppercase letters (A-Z)."); CV_CheckEQ(outputLetterToCount[letterIndex], 0, - "Output subscript constains repeated letters"); + "Output subscript contains repeated letters"); ++outputLetterToCount[letterIndex]; auto mappedIndex = letter2index[letterIndex]; @@ -754,7 +754,7 @@ void LayerEinsumImpl::calculateOutputShape() CV_CheckNE(mappedIndex, -1, "Output subscript has letters that were not encountered in the inputs"); - // Push output dimention + // Push output dimension // Einsum layer only has one output vector einsumOutDims.emplace_back(subscriptIndicesToDimValue[mappedIndex]); @@ -778,7 +778,7 @@ void LayerEinsumImpl::validateOutputSubscript() if(rhs_eq.find("...") == std::string::npos) { CV_Error(Error::StsError, - "Provided output subscript does not include ellipsis while Inputs subscrits constain ellipsis"); + "Provided output subscript does not include ellipsis while input subscripts contain ellipsis"); } } } @@ -973,7 +973,7 @@ void LayerEinsumImpl::processEquation(const std::vector& inputs) CV_Error(Error::StsError, cv::format("Einsum operands can not be broadcasted." "Check input shapes/equation passed." "Input shape of operand [%d]", inputIdx) + - cv::format(" is incompatible in the dimention [%zu].", static_cast(dim_count))); + cv::format(" is incompatible in the dimension [%zu].", static_cast(dim_count))); } } } @@ -1079,7 +1079,7 @@ Mat LayerEinsumImpl::pairwiseOperandProcess( Mat currentLeft; Mat currentRight; - CV_CheckEQ(leftRank, rightRank, "Raks of pair-wise operands must be equal"); + CV_CheckEQ(leftRank, rightRank, "Ranks of pair-wise operands must be equal"); // Following vectors hold: // lro: dim indices that are present in left, right, and reduce_dims @@ -1158,7 +1158,7 @@ Mat LayerEinsumImpl::pairwiseOperandProcess( } - // Permutate the left operand so that the axes order go like this: [lro, lo, reduce_dims, ro] + // Permute the left operand so that the axes order go like this: [lro, lo, reduce_dims, ro] MatShape reshaped_dims; std::vector left_permutation; left_permutation.reserve(lro.size() + lo.size() + reduceDims.size() + ro.size()); @@ -1191,7 +1191,7 @@ Mat LayerEinsumImpl::pairwiseOperandProcess( } } - // Permutate the right operand so that the axes order go like this: [lro, reduce_dims, ro, lo] + // Permute the right operand so that the axes order go like this: [lro, reduce_dims, ro, lo] std::vector right_permutation; right_permutation.reserve(lro.size() + lo.size() + reduceDims.size() + ro.size()); right_permutation.insert(right_permutation.end(), lro.begin(), lro.end()); diff --git a/modules/gapi/include/opencv2/gapi/core.hpp b/modules/gapi/include/opencv2/gapi/core.hpp index 60bb2c5074..c08e18bb4e 100644 --- a/modules/gapi/include/opencv2/gapi/core.hpp +++ b/modules/gapi/include/opencv2/gapi/core.hpp @@ -1796,7 +1796,7 @@ contains a 0-based cluster index for the \f$i^{th}\f$ sample. @note - Function textual ID is "org.opencv.core.kmeansND" - - In case of an N-dimentional points' set given, input GMat can have the following traits: + - In case of an N-dimensional points' set given, input GMat can have the following traits: 2 dimensions, a single row or column if there are N channels, or N columns if there is a single channel. Mat should have @ref CV_32F depth. - Although, if GMat with height != 1, width != 1, channels != 1 given as data, n-dimensional @@ -1806,7 +1806,7 @@ samples are considered given in amount of A, where A = height, n = width * chann width = 1, height = A, where A is samples amount, or width = bestLabels.width, height = bestLabels.height if bestLabels given; - the cluster centers are returned as 1-channel GMat with sizes -width = n, height = K, where n is samples' dimentionality and K is clusters' amount. + width = n, height = K, where n is samples' dimensionality and K is clusters' amount. - As one of possible usages, if you want to control the initial labels for each attempt by yourself, you can utilize just the core of the function. To do that, set the number of attempts to 1, initialize labels each time using a custom algorithm, pass them with the @@ -1814,7 +1814,7 @@ of attempts to 1, initialize labels each time using a custom algorithm, pass the @param data Data for clustering. An array of N-Dimensional points with float coordinates is needed. Function can take GArray, GArray for 2D and 3D cases or GMat for any -dimentionality and channels. +dimensionality and channels. @param K Number of clusters to split the set by. @param bestLabels Optional input integer array that can store the supposed initial cluster indices for every sample. Used when ( flags = #KMEANS_USE_INITIAL_LABELS ) flag is set. From 08b84558a2144a8729100f788ca0fe6318b61c76 Mon Sep 17 00:00:00 2001 From: cudawarped <12133430+cudawarped@users.noreply.github.com> Date: Wed, 10 Sep 2025 08:00:41 +0300 Subject: [PATCH 21/21] Move preprocessor directives outside of macro to avoid the following error when compiling with MSVC D:\repos\opencv\opencv\modules\videoio\src\cap_ffmpeg_impl.hpp(1727): error C2121: '#': invalid character: possibly the result of a macro expansion D:\repos\opencv\opencv\modules\videoio\src\cap_ffmpeg_impl.hpp(1727): error C2143: syntax error: missing ';' before 'if' D:\repos\opencv\opencv\modules\videoio\src\cap_ffmpeg_impl.hpp(1727): error C2059: syntax error: '>=' --- modules/videoio/src/cap_ffmpeg_impl.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/videoio/src/cap_ffmpeg_impl.hpp b/modules/videoio/src/cap_ffmpeg_impl.hpp index ed1d99bdb0..7ce18fdfbf 100644 --- a/modules/videoio/src/cap_ffmpeg_impl.hpp +++ b/modules/videoio/src/cap_ffmpeg_impl.hpp @@ -1724,12 +1724,13 @@ bool CvCapture_FFMPEG::retrieveFrame(int flag, unsigned char** data, int* step, if (!sw_picture || !sw_picture->data[0]) return false; - CV_LOG_DEBUG(NULL, "Input picture format: " << av_get_pix_fmt_name((AVPixelFormat)sw_picture->format) << ", colorspace: " #if LIBAVUTIL_BUILD >= CALC_FFMPEG_VERSION(56, 72, 0) - << av_color_space_name(sw_picture->colorspace) + const char* color_space_name = av_color_space_name(sw_picture->colorspace); #else - << av_get_colorspace_name(sw_picture->colorspace) + const char* color_space_name = av_get_colorspace_name(sw_picture->colorspace); #endif + CV_LOG_DEBUG(NULL, "Input picture format: " << av_get_pix_fmt_name((AVPixelFormat)sw_picture->format) + << ", colorspace: " << color_space_name << ", range: " << av_color_range_name(sw_picture->color_range) << ", primaries: " << av_color_primaries_name(sw_picture->color_primaries) << ", transfer: " << av_color_transfer_name(sw_picture->color_trc)