Merge pull request #25703 from mshabunin:fix-imread-arg

imgproc: fixed imread with output image argument
pull/25723/head
Alexander Smorkalov 5 months ago committed by GitHub
commit 0d1ed49d2a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 16
      modules/imgcodecs/src/grfmt_hdr.cpp
  2. 97
      modules/imgcodecs/src/loadsave.cpp
  3. 13
      modules/imgcodecs/test/test_png.cpp
  4. 29
      modules/imgcodecs/test/test_read_write.cpp

@ -93,10 +93,18 @@ bool HdrDecoder::readData(Mat& _img)
RGBE_ReadPixels_RLE(file, const_cast<float*>(img.ptr<float>()), img.cols, img.rows);
fclose(file); file = NULL;
if(_img.depth() == img.depth()) {
img.convertTo(_img, _img.type());
} else {
img.convertTo(_img, _img.type(), 255);
// NOTE: 'img' has type CV32FC3
switch (_img.depth())
{
case CV_8U: img.convertTo(img, _img.depth(), 255); break;
case CV_32F: break;
default: CV_Error(Error::StsError, "Wrong expected image depth, allowed: CV_8U and CV_32F");
}
switch (_img.channels())
{
case 1: cvtColor(img, _img, COLOR_BGR2GRAY); break;
case 3: img.copyTo(_img); break;
default: CV_Error(Error::StsError, "Wrong expected image channels, allowed: 1 and 3");
}
return true;
}

@ -81,6 +81,22 @@ static Size validateInputImageSize(const Size& size)
}
static inline int calcType(int type, int flags)
{
if( (flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED )
{
if( (flags & IMREAD_ANYDEPTH) == 0 )
type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));
if( (flags & IMREAD_COLOR) != 0 ||
((flags & IMREAD_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1) )
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3);
else
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1);
}
return type;
}
namespace {
class ByteStreamBuffer: public std::streambuf
@ -328,7 +344,7 @@ static ImageEncoder findEncoder( const String& _ext )
}
static void ExifTransform(int orientation, Mat& img)
static void ExifTransform(int orientation, OutputArray img)
{
switch( orientation )
{
@ -365,7 +381,7 @@ static void ExifTransform(int orientation, Mat& img)
}
}
static void ApplyExifOrientation(ExifEntry_t orientationTag, Mat& img)
static void ApplyExifOrientation(ExifEntry_t orientationTag, OutputArray img)
{
int orientation = IMAGE_ORIENTATION_TL;
@ -385,7 +401,7 @@ static void ApplyExifOrientation(ExifEntry_t orientationTag, Mat& img)
*
*/
static bool
imread_( const String& filename, int flags, Mat& mat )
imread_( const String& filename, int flags, OutputArray mat )
{
/// Search for the relevant decoder to handle the imagery
ImageDecoder decoder;
@ -444,18 +460,7 @@ imread_( const String& filename, int flags, Mat& mat )
Size size = validateInputImageSize(Size(decoder->width(), decoder->height()));
// grab the decoded type
int type = decoder->type();
if( (flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED )
{
if( (flags & IMREAD_ANYDEPTH) == 0 )
type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));
if( (flags & IMREAD_COLOR) != 0 ||
((flags & IMREAD_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1) )
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3);
else
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1);
}
const int type = calcType(decoder->type(), flags);
if (mat.empty())
{
@ -469,11 +474,16 @@ imread_( const String& filename, int flags, Mat& mat )
}
// read the image data
Mat real_mat = mat.getMat();
const void * original_ptr = real_mat.data;
bool success = false;
try
{
if (decoder->readData(mat))
if (decoder->readData(real_mat))
{
CV_CheckTrue(original_ptr == real_mat.data, "Internal imread issue");
success = true;
}
}
catch (const cv::Exception& e)
{
@ -567,18 +577,7 @@ imreadmulti_(const String& filename, int flags, std::vector<Mat>& mats, int star
while (current < count)
{
// grab the decoded type
int type = decoder->type();
if ((flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED)
{
if ((flags & IMREAD_ANYDEPTH) == 0)
type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));
if ((flags & IMREAD_COLOR) != 0 ||
((flags & IMREAD_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1))
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3);
else
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1);
}
const int type = calcType(decoder->type(), flags);
// established the required input image size
Size size = validateInputImageSize(Size(decoder->width(), decoder->height()));
@ -645,10 +644,8 @@ void imread( const String& filename, OutputArray dst, int flags )
{
CV_TRACE_FUNCTION();
Mat img = dst.getMat();
/// load the data
imread_(filename, flags, img);
imread_(filename, flags, dst);
}
/**
@ -884,18 +881,7 @@ imdecode_( const Mat& buf, int flags, Mat& mat )
// established the required input image size
Size size = validateInputImageSize(Size(decoder->width(), decoder->height()));
int type = decoder->type();
if( (flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED )
{
if( (flags & IMREAD_ANYDEPTH) == 0 )
type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));
if( (flags & IMREAD_COLOR) != 0 ||
((flags & IMREAD_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1) )
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3);
else
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1);
}
const int type = calcType(decoder->type(), flags);
mat.create( size.height, size.width, type );
@ -1046,18 +1032,7 @@ imdecodemulti_(const Mat& buf, int flags, std::vector<Mat>& mats, int start, int
while (current < count)
{
// grab the decoded type
int type = decoder->type();
if ((flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED)
{
if ((flags & IMREAD_ANYDEPTH) == 0)
type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));
if ((flags & IMREAD_COLOR) != 0 ||
((flags & IMREAD_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1))
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3);
else
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1);
}
const int type = calcType(decoder->type(), flags);
// established the required input image size
Size size = validateInputImageSize(Size(decoder->width(), decoder->height()));
@ -1316,17 +1291,7 @@ bool ImageCollection::Impl::readHeader() {
// readHeader must be called before calling this method
Mat ImageCollection::Impl::readData() {
int type = m_decoder->type();
if ((m_flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && m_flags != IMREAD_UNCHANGED) {
if ((m_flags & IMREAD_ANYDEPTH) == 0)
type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));
if ((m_flags & IMREAD_COLOR) != 0 ||
((m_flags & IMREAD_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1))
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3);
else
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1);
}
const int type = calcType(m_decoder->type(), m_flags);
// established the required input image size
Size size = validateInputImageSize(Size(m_width, m_height));

@ -7,19 +7,6 @@ namespace opencv_test { namespace {
#if defined(HAVE_PNG) || defined(HAVE_SPNG)
TEST(Imgcodecs_Png, imread_passing_mat)
{
const string root = cvtest::TS::ptr()->get_data_path();
const string imgName = root + "../cv/shared/lena.png";
Mat ref = imread(imgName);
Mat img(ref.size(), ref.type());
void* ptr = img.data;
imread(imgName, img);
EXPECT_EQ(cv::norm(ref, img, NORM_INF), 0);
EXPECT_EQ(img.data, ptr);
}
TEST(Imgcodecs_Png, write_big)
{
const string root = cvtest::TS::ptr()->get_data_path();

@ -282,6 +282,35 @@ TEST(Imgcodecs_Image, regression_9376)
EXPECT_EQ(32, m.rows);
}
TEST(Imgcodecs_Image, imread_overload)
{
const string root = cvtest::TS::ptr()->get_data_path();
const string imgName = findDataFile("../highgui/readwrite/ordinary.bmp");
Mat ref = imread(imgName);
ASSERT_FALSE(ref.empty());
{
Mat img(ref.size(), ref.type(), Scalar::all(0)); // existing image
void * ptr = img.data;
imread(imgName, img);
ASSERT_FALSE(img.empty());
EXPECT_EQ(cv::norm(ref, img, NORM_INF), 0);
EXPECT_EQ(img.data, ptr); // no reallocation
}
{
Mat img; // empty image
imread(imgName, img);
ASSERT_FALSE(img.empty());
EXPECT_EQ(cv::norm(ref, img, NORM_INF), 0);
}
{
UMat img; // empty UMat
imread(imgName, img);
ASSERT_FALSE(img.empty());
EXPECT_EQ(cv::norm(ref, img, NORM_INF), 0);
}
}
//==================================================================================================
TEST(Imgcodecs_Image, write_umat)

Loading…
Cancel
Save