diff --git a/modules/imgcodecs/src/grfmt_exr.cpp b/modules/imgcodecs/src/grfmt_exr.cpp index e93448e355..0ffd0d2618 100644 --- a/modules/imgcodecs/src/grfmt_exr.cpp +++ b/modules/imgcodecs/src/grfmt_exr.cpp @@ -235,6 +235,17 @@ bool ExrDecoder::readData( Mat& img ) ( (m_iscolor && !m_ischroma) || color) ? 3 : alphasupported ? 2 : 1 ); // number of channels to read may exceed channels in output img size_t xStride = floatsize * channelstoread; + // See https://github.com/opencv/opencv/issues/26705 + // If ALGO_HINT_ACCURATE is set, read BGR and swap to RGB. + // If ALGO_HINT_APPROX is set, read RGB directly. + bool doReadRGB = m_use_rgb; + bool doPostColorSwap = false; // After decoding, swap BGR to RGB + if(m_use_rgb && (getDefaultAlgorithmHint() == ALGO_HINT_ACCURATE) ) + { + doReadRGB = false; + doPostColorSwap = true; + } + AutoBuffer copy_buffer; if( !justcopy ) @@ -373,7 +384,7 @@ bool ExrDecoder::readData( Mat& img ) if( m_iscolor ) { - if (m_use_rgb) + if (doReadRGB) { if( m_red && (m_red->xSampling != 1 || m_red->ySampling != 1) ) UpSample( data, channelstoread, step / xstep, m_red->xSampling, m_red->ySampling ); @@ -397,7 +408,7 @@ bool ExrDecoder::readData( Mat& img ) if( chromatorgb ) { - if (m_use_rgb) + if (doReadRGB) ChromaToRGB( (float *)data, m_height, channelstoread, step / xstep ); else ChromaToBGR( (float *)data, m_height, channelstoread, step / xstep ); @@ -424,7 +435,7 @@ bool ExrDecoder::readData( Mat& img ) { if( chromatorgb ) { - if (m_use_rgb) + if (doReadRGB) ChromaToRGB( (float *)buffer, 1, defaultchannels, step ); else ChromaToBGR( (float *)buffer, 1, defaultchannels, step ); @@ -452,7 +463,7 @@ bool ExrDecoder::readData( Mat& img ) } if( color ) { - if (m_use_rgb) + if (doReadRGB) { if( m_red && (m_red->xSampling != 1 || m_red->ySampling != 1) ) UpSampleY( data, defaultchannels, step / xstep, m_red->ySampling ); @@ -477,6 +488,11 @@ bool ExrDecoder::readData( Mat& img ) close(); + if(doPostColorSwap) + { + cvtColor( img, img, cv::COLOR_BGR2RGB ); + } + return result; } diff --git a/modules/imgcodecs/test/test_exr.impl.hpp b/modules/imgcodecs/test/test_exr.impl.hpp index 32984ff731..6b4ac0b8d1 100644 --- a/modules/imgcodecs/test/test_exr.impl.hpp +++ b/modules/imgcodecs/test/test_exr.impl.hpp @@ -35,7 +35,8 @@ TEST(Imgcodecs_EXR, readWrite_32FC1) ASSERT_TRUE(cv::imwrite(filenameOutput, img)); // Check generated file size to ensure that it's compressed with proper options - ASSERT_EQ(396u, getFileSize(filenameOutput)); + ASSERT_LE(396u, getFileSize(filenameOutput)); // OpenEXR 2 + ASSERT_LE( getFileSize(filenameOutput), 440u); // OpenEXR 3.2+ const Mat img2 = cv::imread(filenameOutput, IMREAD_UNCHANGED); ASSERT_EQ(img2.type(), img.type()); ASSERT_EQ(img2.size(), img.size()); @@ -199,7 +200,11 @@ TEST(Imgcodecs_EXR, read_YC_changeDepth) cvtColor(img_rgb, img_rgb, COLOR_RGB2BGR); - EXPECT_TRUE(cvtest::norm(img, img_rgb, NORM_INF) == 0); + // See https://github.com/opencv/opencv/issues/26705 + // If ALGO_HINT_ACCURATE is set, norm should be 0. + // If ALGO_HINT_APPROX is set, norm should be 1(or 0). + EXPECT_LE(cvtest::norm(img, img_rgb, NORM_INF), + (cv::getDefaultAlgorithmHint() == ALGO_HINT_ACCURATE)?0:1); // Cannot test writing, EXR encoder doesn't support 8U depth }