mirror of
https://github.com/opencv/opencv.git
synced 2026-07-29 15:23:05 +04:00
handle huge matrices correctly (#11505)
* make sure that the matrix with more than INT_MAX elements is marked as non-continuous, and thus all the pixel-wise functions process it correctly (i.e. row-by-row, not as a single row, where integer overflow may occur when computing the total number of elements)
This commit is contained in:
+26
-34
@@ -262,31 +262,36 @@ void setSize( Mat& m, int _dims, const int* _sz, const size_t* _steps, bool auto
|
||||
}
|
||||
}
|
||||
|
||||
static void updateContinuityFlag(Mat& m)
|
||||
int updateContinuityFlag(int flags, int dims, const int* size, const size_t* step)
|
||||
{
|
||||
int i, j;
|
||||
for( i = 0; i < m.dims; i++ )
|
||||
for( i = 0; i < dims; i++ )
|
||||
{
|
||||
if( m.size[i] > 1 )
|
||||
if( size[i] > 1 )
|
||||
break;
|
||||
}
|
||||
|
||||
for( j = m.dims-1; j > i; j-- )
|
||||
uint64 t = (uint64)size[std::min(i, dims-1)]*CV_MAT_CN(flags);
|
||||
for( j = dims-1; j > i; j-- )
|
||||
{
|
||||
if( m.step[j]*m.size[j] < m.step[j-1] )
|
||||
t *= size[j];
|
||||
if( step[j]*size[j] < step[j-1] )
|
||||
break;
|
||||
}
|
||||
|
||||
uint64 t = (uint64)m.step[0]*m.size[0];
|
||||
if( j <= i && t == (size_t)t )
|
||||
m.flags |= Mat::CONTINUOUS_FLAG;
|
||||
else
|
||||
m.flags &= ~Mat::CONTINUOUS_FLAG;
|
||||
if( j <= i && t == (uint64)(int)t )
|
||||
return flags | Mat::CONTINUOUS_FLAG;
|
||||
return flags & ~Mat::CONTINUOUS_FLAG;
|
||||
}
|
||||
|
||||
void Mat::updateContinuityFlag()
|
||||
{
|
||||
flags = cv::updateContinuityFlag(flags, dims, size.p, step.p);
|
||||
}
|
||||
|
||||
void finalizeHdr(Mat& m)
|
||||
{
|
||||
updateContinuityFlag(m);
|
||||
m.updateContinuityFlag();
|
||||
int d = m.dims;
|
||||
if( d > 2 )
|
||||
m.rows = m.cols = -1;
|
||||
@@ -427,7 +432,6 @@ Mat::Mat(const Mat& m, const Range& _rowRange, const Range& _colRange)
|
||||
&& _colRange.end <= m.cols );
|
||||
cols = _colRange.size();
|
||||
data += _colRange.start*elemSize();
|
||||
flags &= cols < m.cols ? ~CONTINUOUS_FLAG : -1;
|
||||
flags |= SUBMATRIX_FLAG;
|
||||
}
|
||||
}
|
||||
@@ -437,8 +441,7 @@ Mat::Mat(const Mat& m, const Range& _rowRange, const Range& _colRange)
|
||||
CV_RETHROW();
|
||||
}
|
||||
|
||||
if( rows == 1 )
|
||||
flags |= CONTINUOUS_FLAG;
|
||||
updateContinuityFlag();
|
||||
|
||||
if( rows <= 0 || cols <= 0 )
|
||||
{
|
||||
@@ -455,8 +458,6 @@ Mat::Mat(const Mat& m, const Rect& roi)
|
||||
allocator(m.allocator), u(m.u), size(&rows)
|
||||
{
|
||||
CV_Assert( m.dims <= 2 );
|
||||
flags &= roi.width < m.cols ? ~CONTINUOUS_FLAG : -1;
|
||||
flags |= roi.height == 1 ? CONTINUOUS_FLAG : 0;
|
||||
|
||||
size_t esz = CV_ELEM_SIZE(flags);
|
||||
data += roi.x*esz;
|
||||
@@ -468,6 +469,7 @@ Mat::Mat(const Mat& m, const Rect& roi)
|
||||
flags |= SUBMATRIX_FLAG;
|
||||
|
||||
step[0] = m.step[0]; step[1] = esz;
|
||||
updateContinuityFlag();
|
||||
|
||||
if( rows <= 0 || cols <= 0 )
|
||||
{
|
||||
@@ -522,7 +524,7 @@ Mat::Mat(const Mat& m, const Range* ranges)
|
||||
flags |= SUBMATRIX_FLAG;
|
||||
}
|
||||
}
|
||||
updateContinuityFlag(*this);
|
||||
updateContinuityFlag();
|
||||
}
|
||||
|
||||
Mat::Mat(const Mat& m, const std::vector<Range>& ranges)
|
||||
@@ -548,7 +550,7 @@ Mat::Mat(const Mat& m, const std::vector<Range>& ranges)
|
||||
flags |= SUBMATRIX_FLAG;
|
||||
}
|
||||
}
|
||||
updateContinuityFlag(*this);
|
||||
updateContinuityFlag();
|
||||
}
|
||||
|
||||
|
||||
@@ -575,10 +577,7 @@ Mat Mat::diag(int d) const
|
||||
m.size[1] = m.cols = 1;
|
||||
m.step[0] += (len > 1 ? esz : 0);
|
||||
|
||||
if( m.rows > 1 )
|
||||
m.flags &= ~CONTINUOUS_FLAG;
|
||||
else
|
||||
m.flags |= CONTINUOUS_FLAG;
|
||||
m.updateContinuityFlag();
|
||||
|
||||
if( size() != Size(1,1) )
|
||||
m.flags |= SUBMATRIX_FLAG;
|
||||
@@ -597,13 +596,6 @@ void Mat::pop_back(size_t nelems)
|
||||
{
|
||||
size.p[0] -= (int)nelems;
|
||||
dataend -= nelems*step.p[0];
|
||||
/*if( size.p[0] <= 1 )
|
||||
{
|
||||
if( dims <= 2 )
|
||||
flags |= CONTINUOUS_FLAG;
|
||||
else
|
||||
updateContinuityFlag(*this);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -618,7 +610,10 @@ void Mat::push_back_(const void* elem)
|
||||
memcpy(data + r*step.p[0], elem, esz);
|
||||
size.p[0] = r + 1;
|
||||
dataend += step.p[0];
|
||||
if( esz < step.p[0] )
|
||||
uint64 tsz = size.p[0];
|
||||
for( int i = 1; i < dims; i++ )
|
||||
tsz *= size.p[i];
|
||||
if( esz < step.p[0] || tsz != (uint64)(int)tsz )
|
||||
flags &= ~CONTINUOUS_FLAG;
|
||||
}
|
||||
|
||||
@@ -792,10 +787,7 @@ Mat& Mat::adjustROI( int dtop, int dbottom, int dleft, int dright )
|
||||
data += (row1 - ofs.y)*step + (col1 - ofs.x)*esz;
|
||||
rows = row2 - row1; cols = col2 - col1;
|
||||
size.p[0] = rows; size.p[1] = cols;
|
||||
if( esz*cols == step[0] || rows == 1 )
|
||||
flags |= CONTINUOUS_FLAG;
|
||||
else
|
||||
flags &= ~CONTINUOUS_FLAG;
|
||||
updateContinuityFlag();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user