Skip to content

Commit

Permalink
Merge pull request opencv#24929 from asmorkalov:as/imdecode_user_buffer
Browse files Browse the repository at this point in the history
Do not release user-provided buffer, if image decoder failed
  • Loading branch information
asmorkalov authored Jan 29, 2024
2 parents 54b7caf + c9671da commit 8ea939f
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 9 deletions.
3 changes: 2 additions & 1 deletion modules/imgcodecs/include/opencv2/imgcodecs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,8 @@ CV_EXPORTS_W Mat imdecode( InputArray buf, int flags );
@param buf Input array or vector of bytes.
@param flags The same flags as in cv::imread, see cv::ImreadModes.
@param dst The optional output placeholder for the decoded matrix. It can save the image
reallocations when the function is called repeatedly for images of the same size.
reallocations when the function is called repeatedly for images of the same size. In case of decoder
failure the function returns empty cv::Mat object, but does not release user-provided dst buffer.
*/
CV_EXPORTS Mat imdecode( InputArray buf, int flags, Mat* dst);

Expand Down
17 changes: 9 additions & 8 deletions modules/imgcodecs/src/loadsave.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -800,7 +800,7 @@ imdecode_( const Mat& buf, int flags, Mat& mat )

ImageDecoder decoder = findDecoder(buf_row);
if( !decoder )
return 0;
return false;

int scale_denom = 1;
if( flags > IMREAD_LOAD_GDAL )
Expand All @@ -821,7 +821,7 @@ imdecode_( const Mat& buf, int flags, Mat& mat )
filename = tempfile();
FILE* f = fopen( filename.c_str(), "wb" );
if( !f )
return 0;
return false;
size_t bufSize = buf_row.total()*buf.elemSize();
if (fwrite(buf_row.ptr(), 1, bufSize, f) != bufSize)
{
Expand Down Expand Up @@ -859,7 +859,7 @@ imdecode_( const Mat& buf, int flags, Mat& mat )
CV_LOG_WARNING(NULL, "unable to remove temporary file:" << filename);
}
}
return 0;
return false;
}

// established the required input image size
Expand Down Expand Up @@ -905,7 +905,6 @@ imdecode_( const Mat& buf, int flags, Mat& mat )

if (!success)
{
mat.release();
return false;
}

Expand All @@ -929,7 +928,8 @@ Mat imdecode( InputArray _buf, int flags )
CV_TRACE_FUNCTION();

Mat buf = _buf.getMat(), img;
imdecode_( buf, flags, img );
if (!imdecode_(buf, flags, img))
img.release();

return img;
}
Expand All @@ -940,9 +940,10 @@ Mat imdecode( InputArray _buf, int flags, Mat* dst )

Mat buf = _buf.getMat(), img;
dst = dst ? dst : &img;
imdecode_( buf, flags, *dst );

return *dst;
if (imdecode_(buf, flags, *dst))
return *dst;
else
return cv::Mat();
}

static bool
Expand Down
13 changes: 13 additions & 0 deletions modules/imgcodecs/test/test_grfmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,19 @@ TEST(Imgcodecs, write_parameter_type)
EXPECT_EQ(0, remove(tmp_file.c_str()));
}

TEST(Imgcodecs, imdecode_user_buffer)
{
cv::Mat encoded = cv::Mat::zeros(1, 1024, CV_8UC1);
cv::Mat user_buffer(1, 1024, CV_8UC1);
cv::Mat result = cv::imdecode(encoded, IMREAD_ANYCOLOR, &user_buffer);
EXPECT_TRUE(result.empty());
// the function does not release user-provided buffer
EXPECT_FALSE(user_buffer.empty());

result = cv::imdecode(encoded, IMREAD_ANYCOLOR);
EXPECT_TRUE(result.empty());
}

}} // namespace

#if defined(HAVE_OPENEXR) && defined(OPENCV_IMGCODECS_ENABLE_OPENEXR_TESTS)
Expand Down

0 comments on commit 8ea939f

Please sign in to comment.