Skip to content

core: add writeTo() for ROI operation #27318

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: 4.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions modules/core/include/opencv2/core/mat.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1237,8 +1237,13 @@ class CV_EXPORTS Mat

When the operation mask is specified, if the Mat::create call shown above reallocates the matrix,
the newly allocated matrix is initialized with all zeros before copying the data.

If (re)allocation of destination memory is not necessary (e.g. updating ROI), use writeTo() .

@param m Destination matrix. If it does not have a proper size or type before the operation, it is
reallocated.

@sa writeTo
*/
void copyTo( OutputArray m ) const;

Expand All @@ -1250,6 +1255,30 @@ class CV_EXPORTS Mat
*/
void copyTo( OutputArray m, InputArray mask ) const;

/** @brief Overwrites the existing matrix

This method writes existing matrix data, just like copyTo().
But if it does not have a proper size or type before the operation, an exception is thrown.
This function is helpful to update ROI in an existing matrix.

If (re)allocation of destination memory is necessary, use copyTo() .

@param m Destination matrix.
If it does not have a proper size or type before the operation, an exception is thrown.

@sa copyTo

*/
void writeTo( OutputArray m ) const;

/** @overload
@param m Destination matrix.
If it does not have a proper size or type before the operation, an exception is thrown.
@param mask Operation mask of the same size as \*this. Its non-zero elements indicate which matrix
elements need to be copied. The mask has to be of type CV_8U and can have 1 or multiple channels.
*/
void writeTo( OutputArray m, InputArray mask ) const;

/** @brief Converts an array to another data type with optional scaling.

The method converts source pixel values to the target data type. saturate_cast\<\> is applied at
Expand Down
22 changes: 22 additions & 0 deletions modules/core/src/copy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,28 @@ void Mat::copyTo( OutputArray _dst, InputArray _mask ) const
copymask(ptrs[0], 0, ptrs[2], 0, ptrs[1], 0, sz, &esz);
}

/* dst = src */
void Mat::writeTo( OutputArray _dst ) const
{
CV_INSTRUMENT_REGION();

Mat dst = _dst.getMat();
CV_CheckTrue( !dst.empty(), "dst must not be empty" );
CV_CheckTypeEQ(type(), dst.type(), "Make the type of dst the same as src");
CV_CheckEQ(size(), dst.size(), "Make the size of dst the same as src");
copyTo(_dst);
}
void Mat::writeTo( OutputArray _dst, InputArray _mask ) const
{
CV_INSTRUMENT_REGION();

Mat dst = _dst.getMat();
CV_CheckTrue( !dst.empty(), "dst must not be empty" );
CV_CheckTypeEQ(type(), dst.type(), "Make the type of dst the same as src");
CV_CheckEQ(size(), dst.size(), "Make the size of dst the same as src");
copyTo(_dst, _mask);
}


static bool can_apply_memset(const Mat &mat, const Scalar &s, int &fill_value)
{
Expand Down
65 changes: 65 additions & 0 deletions modules/core/test/test_mat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2670,4 +2670,69 @@ TEST(Mat, Recreate1DMatWithSameMeta)
EXPECT_NO_THROW(m.create(dims, depth));
}

// see https://github.com/opencv/opencv/issues/27298
TEST(Mat, writeTo_regression27298)
{
cv::Mat src(40/*height*/, 30/*width*/, CV_8UC1, Scalar(255));
// Normal
{
cv::Mat dst(100, 100, CV_8UC1, Scalar(0));
cv::Mat roi(dst, cv::Rect(0, 0, 30/*width*/, 40/*height*/));
void* roiData = roi.data;
EXPECT_NO_THROW(src.copyTo(roi));
EXPECT_EQ(roi.data, roiData);
EXPECT_EQ(countNonZero(roi), roi.size().width * roi.size().height) << roi;
}
{
cv::Mat dst(100, 100, CV_8UC1, Scalar(0));
cv::Mat roi(dst, cv::Rect(0, 0, 30/*width*/, 40/*height*/));
void* roiData = roi.data;
EXPECT_NO_THROW(src.writeTo(roi));
EXPECT_EQ(roi.data, roiData);
EXPECT_EQ(countNonZero(roi), roi.size().width * roi.size().height) << roi;
}

// Empty
{
cv::Mat roi; // empty
EXPECT_NO_THROW(src.copyTo(roi));
EXPECT_NE(roi.data, nullptr); // Allocated
EXPECT_EQ(countNonZero(roi), roi.size().width * roi.size().height) << roi;
}
{
cv::Mat roi; // empty
EXPECT_ANY_THROW(src.writeTo(roi));
}

// Different Type
{
cv::Mat dst(100, 100, CV_16UC1, Scalar(0));
cv::Mat roi(dst, cv::Rect(0, 0, 30/*width*/, 40/*height*/));
void* roiData = roi.data;
EXPECT_NO_THROW(src.copyTo(roi));
EXPECT_NE(roi.data, roiData); // Reallocated
EXPECT_EQ(countNonZero(roi), roi.size().width * roi.size().height) << roi;
}
{
cv::Mat dst(100, 100, CV_16UC1, Scalar(0));
cv::Mat roi(dst, cv::Rect(0, 0, 30/*width*/, 40/*height*/));
EXPECT_ANY_THROW(src.writeTo(roi));
}

// Different Size
{
cv::Mat dst(100, 100, CV_8UC1, Scalar(0));
cv::Mat roi(dst, cv::Rect(0, 0, 40/*width*/, 30/*height*/));
void* roiData = roi.data;
EXPECT_NO_THROW(src.copyTo(roi));
EXPECT_NE(roi.data, roiData); // Reallocated
EXPECT_EQ(countNonZero(roi), roi.size().width * roi.size().height) << roi;
}
{
cv::Mat dst(100, 100, CV_8UC1, Scalar(0));
cv::Mat roi(dst, cv::Rect(0, 0, 40/*width*/, 30/*height*/));
EXPECT_ANY_THROW(src.writeTo(roi));
}
}

}} // namespace
2 changes: 1 addition & 1 deletion modules/imgcodecs/src/grfmt_gif.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ bool GifDecoder::readData(Mat &img) {
if(!restore.empty())
{
Mat roi = Mat(lastImage, cv::Rect(left,top,width,height));
restore.copyTo(roi);
restore.writeTo(roi);
}

return hasRead;
Expand Down
Loading
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy