diff --git a/modules/core/src/matrix_expressions.cpp b/modules/core/src/matrix_expressions.cpp index 86acab9d93..ee2ad50014 100644 --- a/modules/core/src/matrix_expressions.cpp +++ b/modules/core/src/matrix_expressions.cpp @@ -1341,8 +1341,13 @@ void MatOp_AddEx::assign(const MatExpr& e, Mat& m, int _type) const cv::subtract(e.s, e.a, dst); else { - e.a.convertTo(dst, e.a.type(), e.alpha); - cv::add(dst, e.s, dst); + int depth = e.a.depth(); + int precType = (depth == CV_8U || depth == CV_16U) ? CV_16S : CV_32F; + cv::Mat prec; + e.a.convertTo(prec, precType); + prec = prec * e.alpha; + cv::add(prec, e.s, prec); + prec.convertTo(dst, e.a.type()); } if( dst.data != m.data ) diff --git a/modules/core/test/test_mat.cpp b/modules/core/test/test_mat.cpp index d77aca06cb..0e649a9f87 100644 --- a/modules/core/test/test_mat.cpp +++ b/modules/core/test/test_mat.cpp @@ -2634,4 +2634,29 @@ TEST(Mat, Recreate1DMatWithSameMeta) EXPECT_NO_THROW(m.create(dims, depth)); } +TEST(Mat, ScalarMultiplicationSaturation) { + for (int c = 1; c <= 9; c++) { + cv::Mat m1 = cv::Mat::zeros(1,1, CV_8UC1); + cv::Mat m3 = cv::Mat::zeros(1,1, CV_8UC3); + m1 += cv::Scalar(100); + m3 += cv::Scalar(100,100,100); + cv::Scalar b1 = cv::Scalar(70); + cv::Scalar b3 = cv::Scalar(70,70,70); + m1 = c * (m1 - b1); + m3 = c * (m3 - b3); + int m1_val = m1.at(0,0); + int m3_val = m3.at(0,0)[0]; + + if (c * (100 - 70) > 255) { + EXPECT_EQ(m1_val, 255); + } else { + EXPECT_EQ(m1_val, c * (100 - 70)); + } + if (c * (100 - 70) > 255) { + EXPECT_EQ(m3_val, 255); + } else { + EXPECT_EQ(m3_val, c * (100 - 70)); + } + } + } }} // namespace