Unverified Commit e0dbe5cf authored by Vadim Pisarevsky's avatar Vadim Pisarevsky Committed by GitHub

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)
parent c6a9de81
...@@ -305,6 +305,9 @@ public: ...@@ -305,6 +305,9 @@ public:
//! returns true if GpuMat data is NULL //! returns true if GpuMat data is NULL
bool empty() const; bool empty() const;
//! internal use method: updates the continuity flag
void updateContinuityFlag();
/*! includes several bit-fields: /*! includes several bit-fields:
- the magic signature - the magic signature
- continuity flag - continuity flag
......
...@@ -2092,6 +2092,9 @@ public: ...@@ -2092,6 +2092,9 @@ public:
static MatAllocator* getDefaultAllocator(); static MatAllocator* getDefaultAllocator();
static void setDefaultAllocator(MatAllocator* allocator); static void setDefaultAllocator(MatAllocator* allocator);
//! internal use method: updates the continuity flag
void updateContinuityFlag();
//! interaction with UMat //! interaction with UMat
UMatData* u; UMatData* u;
...@@ -2565,6 +2568,9 @@ public: ...@@ -2565,6 +2568,9 @@ public:
//! and the standard allocator //! and the standard allocator
static MatAllocator* getStdAllocator(); static MatAllocator* getStdAllocator();
//! internal use method: updates the continuity flag
void updateContinuityFlag();
// black-box container of UMat data // black-box container of UMat data
UMatData* u; UMatData* u;
......
...@@ -505,24 +505,20 @@ Mat::Mat(int _rows, int _cols, int _type, void* _data, size_t _step) ...@@ -505,24 +505,20 @@ Mat::Mat(int _rows, int _cols, int _type, void* _data, size_t _step)
if( _step == AUTO_STEP ) if( _step == AUTO_STEP )
{ {
_step = minstep; _step = minstep;
flags |= CONTINUOUS_FLAG;
} }
else else
{ {
CV_DbgAssert( _step >= minstep ); CV_DbgAssert( _step >= minstep );
if (_step % esz1 != 0) if (_step % esz1 != 0)
{ {
CV_Error(Error::BadStep, "Step must be a multiple of esz1"); CV_Error(Error::BadStep, "Step must be a multiple of esz1");
} }
if (_step == minstep || rows == 1)
flags |= CONTINUOUS_FLAG;
} }
step[0] = _step; step[0] = _step;
step[1] = esz; step[1] = esz;
datalimit = datastart + _step * rows; datalimit = datastart + _step * rows;
dataend = datalimit - _step + minstep; dataend = datalimit - _step + minstep;
updateContinuityFlag();
} }
inline inline
...@@ -538,7 +534,6 @@ Mat::Mat(Size _sz, int _type, void* _data, size_t _step) ...@@ -538,7 +534,6 @@ Mat::Mat(Size _sz, int _type, void* _data, size_t _step)
if( _step == AUTO_STEP ) if( _step == AUTO_STEP )
{ {
_step = minstep; _step = minstep;
flags |= CONTINUOUS_FLAG;
} }
else else
{ {
...@@ -548,14 +543,12 @@ Mat::Mat(Size _sz, int _type, void* _data, size_t _step) ...@@ -548,14 +543,12 @@ Mat::Mat(Size _sz, int _type, void* _data, size_t _step)
{ {
CV_Error(Error::BadStep, "Step must be a multiple of esz1"); CV_Error(Error::BadStep, "Step must be a multiple of esz1");
} }
if (_step == minstep || rows == 1)
flags |= CONTINUOUS_FLAG;
} }
step[0] = _step; step[0] = _step;
step[1] = esz; step[1] = esz;
datalimit = datastart + _step*rows; datalimit = datastart + _step*rows;
dataend = datalimit - _step + minstep; dataend = datalimit - _step + minstep;
updateContinuityFlag();
} }
template<typename _Tp> inline template<typename _Tp> inline
......
...@@ -489,7 +489,7 @@ public class MatTest extends OpenCVTestCase { ...@@ -489,7 +489,7 @@ public class MatTest extends OpenCVTestCase {
public void testIsContinuous() { public void testIsContinuous() {
assertTrue(gray0.isContinuous()); assertTrue(gray0.isContinuous());
Mat subMat = gray0.submat(0, 0, gray0.rows() / 2, gray0.cols() / 2); Mat subMat = gray0.submat(0, gray0.rows() / 2, 0, gray0.cols() / 2);
assertFalse(subMat.isContinuous()); assertFalse(subMat.isContinuous());
} }
...@@ -937,7 +937,7 @@ public class MatTest extends OpenCVTestCase { ...@@ -937,7 +937,7 @@ public class MatTest extends OpenCVTestCase {
} }
public void testSubmatRect() { public void testSubmatRect() {
Mat submat = gray255.submat(new Rect(5, gray255.rows() / 2, 5, gray255.cols() / 2)); Mat submat = gray255.submat(new Rect(5, 5, gray255.cols() / 2, gray255.rows() / 2));
assertTrue(submat.isSubmatrix()); assertTrue(submat.isSubmatrix());
assertFalse(submat.isContinuous()); assertFalse(submat.isContinuous());
......
...@@ -46,6 +46,13 @@ ...@@ -46,6 +46,13 @@
using namespace cv; using namespace cv;
using namespace cv::cuda; using namespace cv::cuda;
void cv::cuda::GpuMat::updateContinuityFlag()
{
int sz[] = { rows, cols };
size_t steps[] = { step, elemSize() };
flags = cv::updateContinuityFlag(flags, 2, sz, steps);
}
cv::cuda::GpuMat::GpuMat(int rows_, int cols_, int type_, void* data_, size_t step_) : cv::cuda::GpuMat::GpuMat(int rows_, int cols_, int type_, void* data_, size_t step_) :
flags(Mat::MAGIC_VAL + (type_ & Mat::TYPE_MASK)), rows(rows_), cols(cols_), flags(Mat::MAGIC_VAL + (type_ & Mat::TYPE_MASK)), rows(rows_), cols(cols_),
step(step_), data((uchar*)data_), refcount(0), step(step_), data((uchar*)data_), refcount(0),
...@@ -57,7 +64,6 @@ cv::cuda::GpuMat::GpuMat(int rows_, int cols_, int type_, void* data_, size_t st ...@@ -57,7 +64,6 @@ cv::cuda::GpuMat::GpuMat(int rows_, int cols_, int type_, void* data_, size_t st
if (step == Mat::AUTO_STEP) if (step == Mat::AUTO_STEP)
{ {
step = minstep; step = minstep;
flags |= Mat::CONTINUOUS_FLAG;
} }
else else
{ {
...@@ -65,11 +71,10 @@ cv::cuda::GpuMat::GpuMat(int rows_, int cols_, int type_, void* data_, size_t st ...@@ -65,11 +71,10 @@ cv::cuda::GpuMat::GpuMat(int rows_, int cols_, int type_, void* data_, size_t st
step = minstep; step = minstep;
CV_DbgAssert( step >= minstep ); CV_DbgAssert( step >= minstep );
flags |= step == minstep ? Mat::CONTINUOUS_FLAG : 0;
} }
dataend += step * (rows - 1) + minstep; dataend += step * (rows - 1) + minstep;
updateContinuityFlag();
} }
cv::cuda::GpuMat::GpuMat(Size size_, int type_, void* data_, size_t step_) : cv::cuda::GpuMat::GpuMat(Size size_, int type_, void* data_, size_t step_) :
...@@ -83,7 +88,6 @@ cv::cuda::GpuMat::GpuMat(Size size_, int type_, void* data_, size_t step_) : ...@@ -83,7 +88,6 @@ cv::cuda::GpuMat::GpuMat(Size size_, int type_, void* data_, size_t step_) :
if (step == Mat::AUTO_STEP) if (step == Mat::AUTO_STEP)
{ {
step = minstep; step = minstep;
flags |= Mat::CONTINUOUS_FLAG;
} }
else else
{ {
...@@ -91,11 +95,10 @@ cv::cuda::GpuMat::GpuMat(Size size_, int type_, void* data_, size_t step_) : ...@@ -91,11 +95,10 @@ cv::cuda::GpuMat::GpuMat(Size size_, int type_, void* data_, size_t step_) :
step = minstep; step = minstep;
CV_DbgAssert( step >= minstep ); CV_DbgAssert( step >= minstep );
flags |= step == minstep ? Mat::CONTINUOUS_FLAG : 0;
} }
dataend += step * (rows - 1) + minstep; dataend += step * (rows - 1) + minstep;
updateContinuityFlag();
} }
cv::cuda::GpuMat::GpuMat(const GpuMat& m, Range rowRange_, Range colRange_) cv::cuda::GpuMat::GpuMat(const GpuMat& m, Range rowRange_, Range colRange_)
...@@ -127,17 +130,15 @@ cv::cuda::GpuMat::GpuMat(const GpuMat& m, Range rowRange_, Range colRange_) ...@@ -127,17 +130,15 @@ cv::cuda::GpuMat::GpuMat(const GpuMat& m, Range rowRange_, Range colRange_)
cols = colRange_.size(); cols = colRange_.size();
data += colRange_.start*elemSize(); data += colRange_.start*elemSize();
flags &= cols < m.cols ? ~Mat::CONTINUOUS_FLAG : -1;
} }
if (rows == 1)
flags |= Mat::CONTINUOUS_FLAG;
if (refcount) if (refcount)
CV_XADD(refcount, 1); CV_XADD(refcount, 1);
if (rows <= 0 || cols <= 0) if (rows <= 0 || cols <= 0)
rows = cols = 0; rows = cols = 0;
updateContinuityFlag();
} }
cv::cuda::GpuMat::GpuMat(const GpuMat& m, Rect roi) : cv::cuda::GpuMat::GpuMat(const GpuMat& m, Rect roi) :
...@@ -146,16 +147,19 @@ cv::cuda::GpuMat::GpuMat(const GpuMat& m, Rect roi) : ...@@ -146,16 +147,19 @@ cv::cuda::GpuMat::GpuMat(const GpuMat& m, Rect roi) :
datastart(m.datastart), dataend(m.dataend), datastart(m.datastart), dataend(m.dataend),
allocator(m.allocator) allocator(m.allocator)
{ {
flags &= roi.width < m.cols ? ~Mat::CONTINUOUS_FLAG : -1;
data += roi.x * elemSize(); data += roi.x * elemSize();
CV_Assert( 0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows ); CV_Assert( 0 <= roi.x && 0 <= roi.width &&
roi.x + roi.width <= m.cols &&
0 <= roi.y && 0 <= roi.height &&
roi.y + roi.height <= m.rows );
if (refcount) if (refcount)
CV_XADD(refcount, 1); CV_XADD(refcount, 1);
if (rows <= 0 || cols <= 0) if (rows <= 0 || cols <= 0)
rows = cols = 0; rows = cols = 0;
updateContinuityFlag();
} }
GpuMat cv::cuda::GpuMat::reshape(int new_cn, int new_rows) const GpuMat cv::cuda::GpuMat::reshape(int new_cn, int new_rows) const
...@@ -245,11 +249,7 @@ GpuMat& cv::cuda::GpuMat::adjustROI(int dtop, int dbottom, int dleft, int dright ...@@ -245,11 +249,7 @@ GpuMat& cv::cuda::GpuMat::adjustROI(int dtop, int dbottom, int dleft, int dright
rows = row2 - row1; rows = row2 - row1;
cols = col2 - col1; cols = col2 - col1;
if (esz * cols == step || rows == 1) updateContinuityFlag();
flags |= Mat::CONTINUOUS_FLAG;
else
flags &= ~Mat::CONTINUOUS_FLAG;
return *this; return *this;
} }
......
...@@ -201,10 +201,13 @@ void cv::cuda::HostMem::create(int rows_, int cols_, int type_) ...@@ -201,10 +201,13 @@ void cv::cuda::HostMem::create(int rows_, int cols_, int type_)
if (rows_ > 0 && cols_ > 0) if (rows_ > 0 && cols_ > 0)
{ {
flags = Mat::MAGIC_VAL + Mat::CONTINUOUS_FLAG + type_; flags = Mat::MAGIC_VAL + type_;
rows = rows_; rows = rows_;
cols = cols_; cols = cols_;
step = elemSize() * cols; step = elemSize() * cols;
int sz[] = { rows, cols };
size_t steps[] = { step, CV_ELEM_SIZE(type_) };
flags = updateContinuityFlag(flags, 2, sz, steps);
if (alloc_type == SHARED) if (alloc_type == SHARED)
{ {
......
...@@ -262,31 +262,36 @@ void setSize( Mat& m, int _dims, const int* _sz, const size_t* _steps, bool auto ...@@ -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; 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; 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; break;
} }
uint64 t = (uint64)m.step[0]*m.size[0]; if( j <= i && t == (uint64)(int)t )
if( j <= i && t == (size_t)t ) return flags | Mat::CONTINUOUS_FLAG;
m.flags |= Mat::CONTINUOUS_FLAG; return flags & ~Mat::CONTINUOUS_FLAG;
else }
m.flags &= ~Mat::CONTINUOUS_FLAG;
void Mat::updateContinuityFlag()
{
flags = cv::updateContinuityFlag(flags, dims, size.p, step.p);
} }
void finalizeHdr(Mat& m) void finalizeHdr(Mat& m)
{ {
updateContinuityFlag(m); m.updateContinuityFlag();
int d = m.dims; int d = m.dims;
if( d > 2 ) if( d > 2 )
m.rows = m.cols = -1; m.rows = m.cols = -1;
...@@ -427,7 +432,6 @@ Mat::Mat(const Mat& m, const Range& _rowRange, const Range& _colRange) ...@@ -427,7 +432,6 @@ Mat::Mat(const Mat& m, const Range& _rowRange, const Range& _colRange)
&& _colRange.end <= m.cols ); && _colRange.end <= m.cols );
cols = _colRange.size(); cols = _colRange.size();
data += _colRange.start*elemSize(); data += _colRange.start*elemSize();
flags &= cols < m.cols ? ~CONTINUOUS_FLAG : -1;
flags |= SUBMATRIX_FLAG; flags |= SUBMATRIX_FLAG;
} }
} }
...@@ -437,8 +441,7 @@ Mat::Mat(const Mat& m, const Range& _rowRange, const Range& _colRange) ...@@ -437,8 +441,7 @@ Mat::Mat(const Mat& m, const Range& _rowRange, const Range& _colRange)
CV_RETHROW(); CV_RETHROW();
} }
if( rows == 1 ) updateContinuityFlag();
flags |= CONTINUOUS_FLAG;
if( rows <= 0 || cols <= 0 ) if( rows <= 0 || cols <= 0 )
{ {
...@@ -455,8 +458,6 @@ Mat::Mat(const Mat& m, const Rect& roi) ...@@ -455,8 +458,6 @@ Mat::Mat(const Mat& m, const Rect& roi)
allocator(m.allocator), u(m.u), size(&rows) allocator(m.allocator), u(m.u), size(&rows)
{ {
CV_Assert( m.dims <= 2 ); 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); size_t esz = CV_ELEM_SIZE(flags);
data += roi.x*esz; data += roi.x*esz;
...@@ -468,6 +469,7 @@ Mat::Mat(const Mat& m, const Rect& roi) ...@@ -468,6 +469,7 @@ Mat::Mat(const Mat& m, const Rect& roi)
flags |= SUBMATRIX_FLAG; flags |= SUBMATRIX_FLAG;
step[0] = m.step[0]; step[1] = esz; step[0] = m.step[0]; step[1] = esz;
updateContinuityFlag();
if( rows <= 0 || cols <= 0 ) if( rows <= 0 || cols <= 0 )
{ {
...@@ -522,7 +524,7 @@ Mat::Mat(const Mat& m, const Range* ranges) ...@@ -522,7 +524,7 @@ Mat::Mat(const Mat& m, const Range* ranges)
flags |= SUBMATRIX_FLAG; flags |= SUBMATRIX_FLAG;
} }
} }
updateContinuityFlag(*this); updateContinuityFlag();
} }
Mat::Mat(const Mat& m, const std::vector<Range>& ranges) Mat::Mat(const Mat& m, const std::vector<Range>& ranges)
...@@ -548,7 +550,7 @@ 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; flags |= SUBMATRIX_FLAG;
} }
} }
updateContinuityFlag(*this); updateContinuityFlag();
} }
...@@ -575,10 +577,7 @@ Mat Mat::diag(int d) const ...@@ -575,10 +577,7 @@ Mat Mat::diag(int d) const
m.size[1] = m.cols = 1; m.size[1] = m.cols = 1;
m.step[0] += (len > 1 ? esz : 0); m.step[0] += (len > 1 ? esz : 0);
if( m.rows > 1 ) m.updateContinuityFlag();
m.flags &= ~CONTINUOUS_FLAG;
else
m.flags |= CONTINUOUS_FLAG;
if( size() != Size(1,1) ) if( size() != Size(1,1) )
m.flags |= SUBMATRIX_FLAG; m.flags |= SUBMATRIX_FLAG;
...@@ -597,13 +596,6 @@ void Mat::pop_back(size_t nelems) ...@@ -597,13 +596,6 @@ void Mat::pop_back(size_t nelems)
{ {
size.p[0] -= (int)nelems; size.p[0] -= (int)nelems;
dataend -= nelems*step.p[0]; 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) ...@@ -618,7 +610,10 @@ void Mat::push_back_(const void* elem)
memcpy(data + r*step.p[0], elem, esz); memcpy(data + r*step.p[0], elem, esz);
size.p[0] = r + 1; size.p[0] = r + 1;
dataend += step.p[0]; 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; flags &= ~CONTINUOUS_FLAG;
} }
...@@ -792,10 +787,7 @@ Mat& Mat::adjustROI( int dtop, int dbottom, int dleft, int dright ) ...@@ -792,10 +787,7 @@ Mat& Mat::adjustROI( int dtop, int dbottom, int dleft, int dright )
data += (row1 - ofs.y)*step + (col1 - ofs.x)*esz; data += (row1 - ofs.y)*step + (col1 - ofs.x)*esz;
rows = row2 - row1; cols = col2 - col1; rows = row2 - row1; cols = col2 - col1;
size.p[0] = rows; size.p[1] = cols; size.p[0] = rows; size.p[1] = cols;
if( esz*cols == step[0] || rows == 1 ) updateContinuityFlag();
flags |= CONTINUOUS_FLAG;
else
flags &= ~CONTINUOUS_FLAG;
return *this; return *this;
} }
......
...@@ -120,8 +120,8 @@ static Mat iplImageToMat(const IplImage* img, bool copyData) ...@@ -120,8 +120,8 @@ static Mat iplImageToMat(const IplImage* img, bool copyData)
} }
m.datalimit = m.datastart + m.step.p[0]*m.rows; m.datalimit = m.datastart + m.step.p[0]*m.rows;
m.dataend = m.datastart + m.step.p[0]*(m.rows-1) + esz*m.cols; m.dataend = m.datastart + m.step.p[0]*(m.rows-1) + esz*m.cols;
m.flags |= (m.cols*esz == m.step.p[0] || m.rows == 1 ? Mat::CONTINUOUS_FLAG : 0);
m.step[1] = esz; m.step[1] = esz;
m.updateContinuityFlag();
if( copyData ) if( copyData )
{ {
......
...@@ -5681,8 +5681,6 @@ namespace cv { ...@@ -5681,8 +5681,6 @@ namespace cv {
// three funcs below are implemented in umatrix.cpp // three funcs below are implemented in umatrix.cpp
void setSize( UMat& m, int _dims, const int* _sz, const size_t* _steps, void setSize( UMat& m, int _dims, const int* _sz, const size_t* _steps,
bool autoSteps = false ); bool autoSteps = false );
void updateContinuityFlag(UMat& m);
void finalizeHdr(UMat& m); void finalizeHdr(UMat& m);
} // namespace cv } // namespace cv
......
...@@ -197,6 +197,7 @@ inline Size getContinuousSize( const Mat& m1, const Mat& m2, ...@@ -197,6 +197,7 @@ inline Size getContinuousSize( const Mat& m1, const Mat& m2,
void setSize( Mat& m, int _dims, const int* _sz, const size_t* _steps, bool autoSteps=false ); void setSize( Mat& m, int _dims, const int* _sz, const size_t* _steps, bool autoSteps=false );
void finalizeHdr(Mat& m); void finalizeHdr(Mat& m);
int updateContinuityFlag(int flags, int dims, const int* size, const size_t* step);
struct NoVec struct NoVec
{ {
......
...@@ -318,32 +318,15 @@ void setSize( UMat& m, int _dims, const int* _sz, ...@@ -318,32 +318,15 @@ void setSize( UMat& m, int _dims, const int* _sz,
} }
void updateContinuityFlag(UMat& m) void UMat::updateContinuityFlag()
{ {
int i, j; flags = cv::updateContinuityFlag(flags, dims, size.p, step.p);
for( i = 0; i < m.dims; i++ )
{
if( m.size[i] > 1 )
break;
}
for( j = m.dims-1; j > i; j-- )
{
if( m.step[j]*m.size[j] < m.step[j-1] )
break;
}
uint64 total = (uint64)m.step[0]*m.size[0];
if( j <= i && total == (size_t)total )
m.flags |= UMat::CONTINUOUS_FLAG;
else
m.flags &= ~UMat::CONTINUOUS_FLAG;
} }
void finalizeHdr(UMat& m) void finalizeHdr(UMat& m)
{ {
updateContinuityFlag(m); m.updateContinuityFlag();
int d = m.dims; int d = m.dims;
if( d > 2 ) if( d > 2 )
m.rows = m.cols = -1; m.rows = m.cols = -1;
...@@ -537,12 +520,10 @@ UMat::UMat(const UMat& m, const Range& _rowRange, const Range& _colRange) ...@@ -537,12 +520,10 @@ UMat::UMat(const UMat& m, const Range& _rowRange, const Range& _colRange)
CV_Assert( 0 <= _colRange.start && _colRange.start <= _colRange.end && _colRange.end <= m.cols ); CV_Assert( 0 <= _colRange.start && _colRange.start <= _colRange.end && _colRange.end <= m.cols );
cols = _colRange.size(); cols = _colRange.size();
offset += _colRange.start*elemSize(); offset += _colRange.start*elemSize();
flags &= cols < m.cols ? ~CONTINUOUS_FLAG : -1;
flags |= SUBMATRIX_FLAG; flags |= SUBMATRIX_FLAG;
} }
if( rows == 1 ) updateContinuityFlag();
flags |= CONTINUOUS_FLAG;
if( rows <= 0 || cols <= 0 ) if( rows <= 0 || cols <= 0 )
{ {
...@@ -557,8 +538,6 @@ UMat::UMat(const UMat& m, const Rect& roi) ...@@ -557,8 +538,6 @@ UMat::UMat(const UMat& m, const Rect& roi)
allocator(m.allocator), usageFlags(m.usageFlags), u(m.u), offset(m.offset + roi.y*m.step[0]), size(&rows) allocator(m.allocator), usageFlags(m.usageFlags), u(m.u), offset(m.offset + roi.y*m.step[0]), size(&rows)
{ {
CV_Assert( m.dims <= 2 ); 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); size_t esz = CV_ELEM_SIZE(flags);
offset += roi.x*esz; offset += roi.x*esz;
...@@ -570,6 +549,7 @@ UMat::UMat(const UMat& m, const Rect& roi) ...@@ -570,6 +549,7 @@ UMat::UMat(const UMat& m, const Rect& roi)
flags |= SUBMATRIX_FLAG; flags |= SUBMATRIX_FLAG;
step[0] = m.step[0]; step[1] = esz; step[0] = m.step[0]; step[1] = esz;
updateContinuityFlag();
if( rows <= 0 || cols <= 0 ) if( rows <= 0 || cols <= 0 )
{ {
...@@ -601,7 +581,7 @@ UMat::UMat(const UMat& m, const Range* ranges) ...@@ -601,7 +581,7 @@ UMat::UMat(const UMat& m, const Range* ranges)
flags |= SUBMATRIX_FLAG; flags |= SUBMATRIX_FLAG;
} }
} }
updateContinuityFlag(*this); updateContinuityFlag();
} }
UMat::UMat(const UMat& m, const std::vector<Range>& ranges) UMat::UMat(const UMat& m, const std::vector<Range>& ranges)
...@@ -626,7 +606,7 @@ UMat::UMat(const UMat& m, const std::vector<Range>& ranges) ...@@ -626,7 +606,7 @@ UMat::UMat(const UMat& m, const std::vector<Range>& ranges)
flags |= SUBMATRIX_FLAG; flags |= SUBMATRIX_FLAG;
} }
} }
updateContinuityFlag(*this); updateContinuityFlag();
} }
UMat UMat::diag(int d) const UMat UMat::diag(int d) const
...@@ -652,10 +632,7 @@ UMat UMat::diag(int d) const ...@@ -652,10 +632,7 @@ UMat UMat::diag(int d) const
m.size[1] = m.cols = 1; m.size[1] = m.cols = 1;
m.step[0] += (len > 1 ? esz : 0); m.step[0] += (len > 1 ? esz : 0);
if( m.rows > 1 ) m.updateContinuityFlag();
m.flags &= ~CONTINUOUS_FLAG;
else
m.flags |= CONTINUOUS_FLAG;
if( size() != Size(1,1) ) if( size() != Size(1,1) )
m.flags |= SUBMATRIX_FLAG; m.flags |= SUBMATRIX_FLAG;
...@@ -701,10 +678,7 @@ UMat& UMat::adjustROI( int dtop, int dbottom, int dleft, int dright ) ...@@ -701,10 +678,7 @@ UMat& UMat::adjustROI( int dtop, int dbottom, int dleft, int dright )
offset += (row1 - ofs.y)*step + (col1 - ofs.x)*esz; offset += (row1 - ofs.y)*step + (col1 - ofs.x)*esz;
rows = row2 - row1; cols = col2 - col1; rows = row2 - row1; cols = col2 - col1;
size.p[0] = rows; size.p[1] = cols; size.p[0] = rows; size.p[1] = cols;
if( esz*cols == step[0] || rows == 1 ) updateContinuityFlag();
flags |= CONTINUOUS_FLAG;
else
flags &= ~CONTINUOUS_FLAG;
return *this; return *this;
} }
......
...@@ -420,4 +420,34 @@ void CV_ThreshTest::prepare_to_validation( int /*test_case_idx*/ ) ...@@ -420,4 +420,34 @@ void CV_ThreshTest::prepare_to_validation( int /*test_case_idx*/ )
TEST(Imgproc_Threshold, accuracy) { CV_ThreshTest test; test.safe_run(); } TEST(Imgproc_Threshold, accuracy) { CV_ThreshTest test; test.safe_run(); }
#if defined(_M_X64) || defined(__x86_64__)
TEST(Imgproc_Threshold, huge) /* since the test needs a lot of memory, enable it only on 64-bit Intel/AMD platforms, otherwise it may take a lot of time because of heavy swapping */
#else
TEST(DISABLED_Imgproc_Threshold, huge)
#endif
{
Mat m;
try
{
m.create(65000, 40000, CV_8U);
}
catch(...)
{
}
if( !m.empty() )
{
ASSERT_FALSE(m.isContinuous());
uint64 i, n = (uint64)m.rows*m.cols;
for( i = 0; i < n; i++ )
m.data[i] = (uchar)(i & 255);
cv::threshold(m, m, 127, 255, cv::THRESH_BINARY);
int nz = cv::countNonZero(m);
ASSERT_EQ(nz, (int)(n/2));
}
// just skip the test if there is no enough memory
}
}} // namespace }} // namespace
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment