1 // This file is part of OpenCV project.
2 // It is subject to the license terms in the LICENSE file found in the top-level directory
3 // of this distribution and at http://opencv.org/license.html
6 #include "bufferpool.impl.hpp"
10 void MatAllocator::map(UMatData*, int) const
14 void MatAllocator::unmap(UMatData* u) const
16 if(u->urefcount == 0 && u->refcount == 0)
22 void MatAllocator::download(UMatData* u, void* dstptr,
23 int dims, const size_t sz[],
24 const size_t srcofs[], const size_t srcstep[],
25 const size_t dststep[]) const
30 uchar* srcptr = u->data;
31 for( int i = 0; i < dims; i++ )
33 CV_Assert( sz[i] <= (size_t)INT_MAX );
37 srcptr += srcofs[i]*(i <= dims-2 ? srcstep[i] : 1);
41 Mat src(dims, isz, CV_8U, srcptr, srcstep);
42 Mat dst(dims, isz, CV_8U, dstptr, dststep);
44 const Mat* arrays[] = { &src, &dst };
46 NAryMatIterator it(arrays, ptrs, 2);
47 size_t planesz = it.size;
49 for( size_t j = 0; j < it.nplanes; j++, ++it )
50 memcpy(ptrs[1], ptrs[0], planesz);
54 void MatAllocator::upload(UMatData* u, const void* srcptr, int dims, const size_t sz[],
55 const size_t dstofs[], const size_t dststep[],
56 const size_t srcstep[]) const
61 uchar* dstptr = u->data;
62 for( int i = 0; i < dims; i++ )
64 CV_Assert( sz[i] <= (size_t)INT_MAX );
68 dstptr += dstofs[i]*(i <= dims-2 ? dststep[i] : 1);
72 Mat src(dims, isz, CV_8U, (void*)srcptr, srcstep);
73 Mat dst(dims, isz, CV_8U, dstptr, dststep);
75 const Mat* arrays[] = { &src, &dst };
77 NAryMatIterator it(arrays, ptrs, 2);
78 size_t planesz = it.size;
80 for( size_t j = 0; j < it.nplanes; j++, ++it )
81 memcpy(ptrs[1], ptrs[0], planesz);
84 void MatAllocator::copy(UMatData* usrc, UMatData* udst, int dims, const size_t sz[],
85 const size_t srcofs[], const size_t srcstep[],
86 const size_t dstofs[], const size_t dststep[], bool /*sync*/) const
88 CV_INSTRUMENT_REGION();
93 uchar* srcptr = usrc->data;
94 uchar* dstptr = udst->data;
95 for( int i = 0; i < dims; i++ )
97 CV_Assert( sz[i] <= (size_t)INT_MAX );
101 srcptr += srcofs[i]*(i <= dims-2 ? srcstep[i] : 1);
103 dstptr += dstofs[i]*(i <= dims-2 ? dststep[i] : 1);
107 Mat src(dims, isz, CV_8U, srcptr, srcstep);
108 Mat dst(dims, isz, CV_8U, dstptr, dststep);
110 const Mat* arrays[] = { &src, &dst };
112 NAryMatIterator it(arrays, ptrs, 2);
113 size_t planesz = it.size;
115 for( size_t j = 0; j < it.nplanes; j++, ++it )
116 memcpy(ptrs[1], ptrs[0], planesz);
119 BufferPoolController* MatAllocator::getBufferPoolController(const char* id) const
122 static DummyBufferPoolController dummy;
126 class StdMatAllocator CV_FINAL : public MatAllocator
129 UMatData* allocate(int dims, const int* sizes, int type,
130 void* data0, size_t* step, int /*flags*/, UMatUsageFlags /*usageFlags*/) const CV_OVERRIDE
132 size_t total = CV_ELEM_SIZE(type);
133 for( int i = dims-1; i >= 0; i-- )
137 if( data0 && step[i] != CV_AUTOSTEP )
139 CV_Assert(total <= step[i]);
147 uchar* data = data0 ? (uchar*)data0 : (uchar*)fastMalloc(total);
148 UMatData* u = new UMatData(this);
149 u->data = u->origdata = data;
152 u->flags |= UMatData::USER_ALLOCATED;
157 bool allocate(UMatData* u, int /*accessFlags*/, UMatUsageFlags /*usageFlags*/) const CV_OVERRIDE
163 void deallocate(UMatData* u) const CV_OVERRIDE
168 CV_Assert(u->urefcount == 0);
169 CV_Assert(u->refcount == 0);
170 if( !(u->flags & UMatData::USER_ALLOCATED) )
172 fastFree(u->origdata);
181 MatAllocator* volatile g_matAllocator = NULL;
184 MatAllocator* Mat::getDefaultAllocator()
186 if (g_matAllocator == NULL)
188 cv::AutoLock lock(cv::getInitializationMutex());
189 if (g_matAllocator == NULL)
191 g_matAllocator = getStdAllocator();
194 return g_matAllocator;
196 void Mat::setDefaultAllocator(MatAllocator* allocator)
198 g_matAllocator = allocator;
200 MatAllocator* Mat::getStdAllocator()
202 CV_SINGLETON_LAZY_INIT(MatAllocator, new StdMatAllocator())
205 //==================================================================================================
207 void setSize( Mat& m, int _dims, const int* _sz, const size_t* _steps, bool autoSteps)
209 CV_Assert( 0 <= _dims && _dims <= CV_MAX_DIM );
210 if( m.dims != _dims )
212 if( m.step.p != m.step.buf )
215 m.step.p = m.step.buf;
220 m.step.p = (size_t*)fastMalloc(_dims*sizeof(m.step.p[0]) + (_dims+1)*sizeof(m.size.p[0]));
221 m.size.p = (int*)(m.step.p + _dims) + 1;
222 m.size.p[-1] = _dims;
223 m.rows = m.cols = -1;
231 size_t esz = CV_ELEM_SIZE(m.flags), esz1 = CV_ELEM_SIZE1(m.flags), total = esz;
232 for( int i = _dims-1; i >= 0; i-- )
240 if (_steps[i] % esz1 != 0)
242 CV_Error(Error::BadStep, "Step must be a multiple of esz1");
245 m.step.p[i] = i < _dims-1 ? _steps[i] : esz;
250 int64 total1 = (int64)total*s;
251 if( (uint64)total1 != (size_t)total1 )
252 CV_Error( CV_StsOutOfRange, "The total matrix size does not fit to \"size_t\" type" );
253 total = (size_t)total1;
265 int updateContinuityFlag(int flags, int dims, const int* size, const size_t* step)
268 for( i = 0; i < dims; i++ )
274 uint64 t = (uint64)size[std::min(i, dims-1)]*CV_MAT_CN(flags);
275 for( j = dims-1; j > i; j-- )
278 if( step[j]*size[j] < step[j-1] )
282 if( j <= i && t == (uint64)(int)t )
283 return flags | Mat::CONTINUOUS_FLAG;
284 return flags & ~Mat::CONTINUOUS_FLAG;
287 void Mat::updateContinuityFlag()
289 flags = cv::updateContinuityFlag(flags, dims, size.p, step.p);
292 void finalizeHdr(Mat& m)
294 m.updateContinuityFlag();
297 m.rows = m.cols = -1;
299 m.datastart = m.data = m.u->data;
302 m.datalimit = m.datastart + m.size[0]*m.step[0];
305 m.dataend = m.ptr() + m.size[d-1]*m.step[d-1];
306 for( int i = 0; i < d-1; i++ )
307 m.dataend += (m.size[i] - 1)*m.step[i];
310 m.dataend = m.datalimit;
313 m.dataend = m.datalimit = 0;
316 //==================================================================================================
318 void Mat::create(int d, const int* _sizes, int _type)
321 CV_Assert(0 <= d && d <= CV_MAX_DIM && _sizes);
322 _type = CV_MAT_TYPE(_type);
324 if( data && (d == dims || (d == 1 && dims <= 2)) && _type == type() )
326 if( d == 2 && rows == _sizes[0] && cols == _sizes[1] )
328 for( i = 0; i < d; i++ )
329 if( size[i] != _sizes[i] )
331 if( i == d && (d > 1 || size[1] == 1))
335 int _sizes_backup[CV_MAX_DIM]; // #5991
336 if (_sizes == (this->size.p))
338 for(i = 0; i < d; i++ )
339 _sizes_backup[i] = _sizes[i];
340 _sizes = _sizes_backup;
346 flags = (_type & CV_MAT_TYPE_MASK) | MAGIC_VAL;
347 setSize(*this, d, _sizes, 0, true);
351 MatAllocator *a = allocator, *a0 = getDefaultAllocator();
353 if( !a || a == tegra::getAllocator() )
354 a = tegra::getAllocator(d, _sizes, _type);
360 u = a->allocate(dims, size, _type, 0, step.p, 0, USAGE_DEFAULT);
367 u = a0->allocate(dims, size, _type, 0, step.p, 0, USAGE_DEFAULT);
370 CV_Assert( step[dims-1] == (size_t)CV_ELEM_SIZE(flags) );
377 void Mat::create(const std::vector<int>& _sizes, int _type)
379 create((int)_sizes.size(), _sizes.data(), _type);
382 void Mat::copySize(const Mat& m)
384 setSize(*this, m.dims, 0, 0);
385 for( int i = 0; i < dims; i++ )
392 void Mat::deallocate()
398 (u_->currAllocator ? u_->currAllocator : allocator ? allocator : getDefaultAllocator())->unmap(u_);
402 Mat::Mat(const Mat& m, const Range& _rowRange, const Range& _colRange)
403 : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
404 datalimit(0), allocator(0), u(0), size(&rows)
406 CV_Assert( m.dims >= 2 );
409 AutoBuffer<Range> rs(m.dims);
412 for( int i = 2; i < m.dims; i++ )
413 rs[i] = Range::all();
414 *this = m(rs.data());
421 if( _rowRange != Range::all() && _rowRange != Range(0,rows) )
423 CV_Assert( 0 <= _rowRange.start && _rowRange.start <= _rowRange.end
424 && _rowRange.end <= m.rows );
425 rows = _rowRange.size();
426 data += step*_rowRange.start;
427 flags |= SUBMATRIX_FLAG;
430 if( _colRange != Range::all() && _colRange != Range(0,cols) )
432 CV_Assert( 0 <= _colRange.start && _colRange.start <= _colRange.end
433 && _colRange.end <= m.cols );
434 cols = _colRange.size();
435 data += _colRange.start*elemSize();
436 flags |= SUBMATRIX_FLAG;
445 updateContinuityFlag();
447 if( rows <= 0 || cols <= 0 )
455 Mat::Mat(const Mat& m, const Rect& roi)
456 : flags(m.flags), dims(2), rows(roi.height), cols(roi.width),
457 data(m.data + roi.y*m.step[0]),
458 datastart(m.datastart), dataend(m.dataend), datalimit(m.datalimit),
459 allocator(m.allocator), u(m.u), size(&rows)
461 CV_Assert( m.dims <= 2 );
463 size_t esz = CV_ELEM_SIZE(flags);
465 CV_Assert( 0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols &&
466 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows );
468 CV_XADD(&u->refcount, 1);
469 if( roi.width < m.cols || roi.height < m.rows )
470 flags |= SUBMATRIX_FLAG;
472 step[0] = m.step[0]; step[1] = esz;
473 updateContinuityFlag();
475 if( rows <= 0 || cols <= 0 )
483 Mat::Mat(int _dims, const int* _sizes, int _type, void* _data, const size_t* _steps)
484 : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
485 datalimit(0), allocator(0), u(0), size(&rows)
487 flags |= CV_MAT_TYPE(_type);
488 datastart = data = (uchar*)_data;
489 setSize(*this, _dims, _sizes, _steps, true);
494 Mat::Mat(const std::vector<int>& _sizes, int _type, void* _data, const size_t* _steps)
495 : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
496 datalimit(0), allocator(0), u(0), size(&rows)
498 flags |= CV_MAT_TYPE(_type);
499 datastart = data = (uchar*)_data;
500 setSize(*this, (int)_sizes.size(), _sizes.data(), _steps, true);
505 Mat::Mat(const Mat& m, const Range* ranges)
506 : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
507 datalimit(0), allocator(0), u(0), size(&rows)
512 for( int i = 0; i < d; i++ )
515 CV_Assert( r == Range::all() || (0 <= r.start && r.start < r.end && r.end <= m.size[i]) );
518 for( int i = 0; i < d; i++ )
521 if( r != Range::all() && r != Range(0, size.p[i]))
523 size.p[i] = r.end - r.start;
524 data += r.start*step.p[i];
525 flags |= SUBMATRIX_FLAG;
528 updateContinuityFlag();
531 Mat::Mat(const Mat& m, const std::vector<Range>& ranges)
532 : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0),
533 datalimit(0), allocator(0), u(0), size(&rows)
537 CV_Assert((int)ranges.size() == d);
538 for (int i = 0; i < d; i++)
541 CV_Assert(r == Range::all() || (0 <= r.start && r.start < r.end && r.end <= m.size[i]));
544 for (int i = 0; i < d; i++)
547 if (r != Range::all() && r != Range(0, size.p[i]))
549 size.p[i] = r.end - r.start;
550 data += r.start*step.p[i];
551 flags |= SUBMATRIX_FLAG;
554 updateContinuityFlag();
558 Mat Mat::diag(int d) const
560 CV_Assert( dims <= 2 );
562 size_t esz = elemSize();
567 len = std::min(cols - d, rows);
572 len = std::min(rows + d, cols);
575 CV_DbgAssert( len > 0 );
577 m.size[0] = m.rows = len;
578 m.size[1] = m.cols = 1;
579 m.step[0] += (len > 1 ? esz : 0);
581 m.updateContinuityFlag();
583 if( size() != Size(1,1) )
584 m.flags |= SUBMATRIX_FLAG;
590 void Mat::pop_back(size_t nelems)
592 CV_Assert( nelems <= (size_t)size.p[0] );
595 *this = rowRange(0, size.p[0] - (int)nelems);
598 size.p[0] -= (int)nelems;
599 dataend -= nelems*step.p[0];
604 void Mat::push_back_(const void* elem)
606 size_t r = size.p[0];
607 if( isSubmatrix() || dataend + step.p[0] > datalimit )
608 reserve( std::max(r + 1, (r*3+1)/2) );
610 size_t esz = elemSize();
611 memcpy(data + r*step.p[0], elem, esz);
612 size.p[0] = int(r + 1);
613 dataend += step.p[0];
614 uint64 tsz = size.p[0];
615 for( int i = 1; i < dims; i++ )
617 if( esz < step.p[0] || tsz != (uint64)(int)tsz )
618 flags &= ~CONTINUOUS_FLAG;
622 void Mat::reserve(size_t nelems)
624 const size_t MIN_SIZE = 64;
626 CV_Assert( (int)nelems >= 0 );
627 if( !isSubmatrix() && data + step.p[0]*nelems <= datalimit )
632 if( (size_t)r >= nelems )
635 size.p[0] = std::max((int)nelems, 1);
636 size_t newsize = total()*elemSize();
638 if( newsize < MIN_SIZE )
639 size.p[0] = (int)((MIN_SIZE + newsize - 1)*nelems/newsize);
641 Mat m(dims, size.p, type());
645 Mat mpart = m.rowRange(0, r);
651 dataend = data + step.p[0]*r;
655 void Mat::reserveBuffer(size_t nbytes)
661 if (!isSubmatrix() && data + nbytes <= dataend)//Should it be datalimit?
667 size_t nelems = (nbytes - 1) / esz + 1;
669 #if SIZE_MAX > UINT_MAX
670 CV_Assert(nelems <= size_t(INT_MAX)*size_t(INT_MAX));
671 int newrows = nelems > size_t(INT_MAX) ? nelems > 0x400*size_t(INT_MAX) ? nelems > 0x100000 * size_t(INT_MAX) ? nelems > 0x40000000 * size_t(INT_MAX) ?
672 size_t(INT_MAX) : 0x40000000 : 0x100000 : 0x400 : 1;
674 int newrows = nelems > size_t(INT_MAX) ? 2 : 1;
676 int newcols = (int)((nelems - 1) / newrows + 1);
678 create(newrows, newcols, mtype);
682 void Mat::resize(size_t nelems)
684 int saveRows = size.p[0];
685 if( saveRows == (int)nelems )
687 CV_Assert( (int)nelems >= 0 );
689 if( isSubmatrix() || data + step.p[0]*nelems > datalimit )
692 size.p[0] = (int)nelems;
693 dataend += (size.p[0] - saveRows)*step.p[0];
695 //updateContinuityFlag(*this);
699 void Mat::resize(size_t nelems, const Scalar& s)
701 int saveRows = size.p[0];
704 if( size.p[0] > saveRows )
706 Mat part = rowRange(saveRows, size.p[0]);
711 void Mat::push_back(const Mat& elems)
713 size_t r = size.p[0];
714 size_t delta = elems.size.p[0];
725 *this = elems.clone();
729 size.p[0] = elems.size.p[0];
730 bool eq = size == elems.size;
733 CV_Error(CV_StsUnmatchedSizes, "Pushed vector length is not equal to matrix row length");
734 if( type() != elems.type() )
735 CV_Error(CV_StsUnmatchedFormats, "Pushed vector type is not the same as matrix type");
737 if( isSubmatrix() || dataend + step.p[0]*delta > datalimit )
738 reserve( std::max(r + delta, (r*3+1)/2) );
740 size.p[0] += int(delta);
741 dataend += step.p[0]*delta;
743 //updateContinuityFlag(*this);
745 if( isContinuous() && elems.isContinuous() )
746 memcpy(data + r*step.p[0], elems.data, elems.total()*elems.elemSize());
749 Mat part = rowRange(int(r), int(r + delta));
755 void Mat::locateROI( Size& wholeSize, Point& ofs ) const
757 CV_Assert( dims <= 2 && step[0] > 0 );
758 size_t esz = elemSize(), minstep;
759 ptrdiff_t delta1 = data - datastart, delta2 = dataend - datastart;
765 ofs.y = (int)(delta1/step[0]);
766 ofs.x = (int)((delta1 - step[0]*ofs.y)/esz);
767 CV_DbgAssert( data == datastart + ofs.y*step[0] + ofs.x*esz );
769 minstep = (ofs.x + cols)*esz;
770 wholeSize.height = (int)((delta2 - minstep)/step[0] + 1);
771 wholeSize.height = std::max(wholeSize.height, ofs.y + rows);
772 wholeSize.width = (int)((delta2 - step*(wholeSize.height-1))/esz);
773 wholeSize.width = std::max(wholeSize.width, ofs.x + cols);
776 Mat& Mat::adjustROI( int dtop, int dbottom, int dleft, int dright )
778 CV_Assert( dims <= 2 && step[0] > 0 );
779 Size wholeSize; Point ofs;
780 size_t esz = elemSize();
781 locateROI( wholeSize, ofs );
782 int row1 = std::min(std::max(ofs.y - dtop, 0), wholeSize.height), row2 = std::max(0, std::min(ofs.y + rows + dbottom, wholeSize.height));
783 int col1 = std::min(std::max(ofs.x - dleft, 0), wholeSize.width), col2 = std::max(0, std::min(ofs.x + cols + dright, wholeSize.width));
785 std::swap(row1, row2);
787 std::swap(col1, col2);
789 data += (row1 - ofs.y)*step + (col1 - ofs.x)*esz;
790 rows = row2 - row1; cols = col2 - col1;
791 size.p[0] = rows; size.p[1] = cols;
792 updateContinuityFlag();
796 Mat Mat::reshape(int new_cn, int new_rows) const
803 if( new_rows == 0 && new_cn != 0 && size[dims-1]*cn % new_cn == 0 )
805 hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((new_cn-1) << CV_CN_SHIFT);
806 hdr.step[dims-1] = CV_ELEM_SIZE(hdr.flags);
807 hdr.size[dims-1] = hdr.size[dims-1]*cn / new_cn;
812 int sz[] = { new_rows, (int)(total()/new_rows) };
813 return reshape(new_cn, 2, sz);
817 CV_Assert( dims <= 2 );
822 int total_width = cols * cn;
824 if( (new_cn > total_width || total_width % new_cn != 0) && new_rows == 0 )
825 new_rows = rows * total_width / new_cn;
827 if( new_rows != 0 && new_rows != rows )
829 int total_size = total_width * rows;
830 if( !isContinuous() )
831 CV_Error( CV_BadStep,
832 "The matrix is not continuous, thus its number of rows can not be changed" );
834 if( (unsigned)new_rows > (unsigned)total_size )
835 CV_Error( CV_StsOutOfRange, "Bad new number of rows" );
837 total_width = total_size / new_rows;
839 if( total_width * new_rows != total_size )
840 CV_Error( CV_StsBadArg, "The total number of matrix elements "
841 "is not divisible by the new number of rows" );
844 hdr.step[0] = total_width * elemSize1();
847 int new_width = total_width / new_cn;
849 if( new_width * new_cn != total_width )
850 CV_Error( CV_BadNumChannels,
851 "The total width is not divisible by the new number of channels" );
853 hdr.cols = new_width;
854 hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((new_cn-1) << CV_CN_SHIFT);
855 hdr.step[1] = CV_ELEM_SIZE(hdr.flags);
859 Mat Mat::reshape(int _cn, int _newndims, const int* _newsz) const
861 if(_newndims == dims)
866 return reshape(_cn, _newsz[0]);
871 CV_Assert(_cn >= 0 && _newndims > 0 && _newndims <= CV_MAX_DIM && _newsz);
874 _cn = this->channels();
876 CV_Assert(_cn <= CV_CN_MAX);
878 size_t total_elem1_ref = this->total() * this->channels();
879 size_t total_elem1 = _cn;
881 AutoBuffer<int, 4> newsz_buf( (size_t)_newndims );
883 for (int i = 0; i < _newndims; i++)
885 CV_Assert(_newsz[i] >= 0);
888 newsz_buf[i] = _newsz[i];
890 newsz_buf[i] = this->size[i];
892 CV_Error(CV_StsOutOfRange, "Copy dimension (which has zero size) is not present in source matrix");
894 total_elem1 *= (size_t)newsz_buf[i];
897 if (total_elem1 != total_elem1_ref)
898 CV_Error(CV_StsUnmatchedSizes, "Requested and source matrices have different count of elements");
901 hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((_cn-1) << CV_CN_SHIFT);
902 setSize(hdr, _newndims, newsz_buf.data(), NULL, true);
907 CV_Error(CV_StsNotImplemented, "Reshaping of n-dimensional non-continuous matrices is not supported yet");
911 Mat Mat::reshape(int _cn, const std::vector<int>& _newshape) const
913 if(_newshape.empty())
919 return reshape(_cn, (int)_newshape.size(), &_newshape[0]);
922 Mat Mat::diag(const Mat& d)
924 CV_Assert( d.cols == 1 || d.rows == 1 );
925 int len = d.rows + d.cols - 1;
926 Mat m(len, len, d.type(), Scalar(0));
935 int Mat::checkVector(int _elemChannels, int _depth, bool _requireContinuous) const
937 return data && (depth() == _depth || _depth <= 0) &&
938 (isContinuous() || !_requireContinuous) &&
939 ((dims == 2 && (((rows == 1 || cols == 1) && channels() == _elemChannels) ||
940 (cols == _elemChannels && channels() == 1))) ||
941 (dims == 3 && channels() == 1 && size.p[2] == _elemChannels && (size.p[0] == 1 || size.p[1] == 1) &&
942 (isContinuous() || step.p[1] == step.p[2]*size.p[2])))
943 ? (int)(total()*channels()/_elemChannels) : -1;
947 static inline Size getContinuousSize_(int flags, int cols, int rows, int widthScale)
949 int64 sz = (int64)cols * rows * widthScale;
950 bool has_int_overflow = sz >= INT_MAX;
951 bool isContiguous = (flags & Mat::CONTINUOUS_FLAG) != 0;
952 return (isContiguous && !has_int_overflow)
954 : Size(cols * widthScale, rows);
957 Size getContinuousSize2D(Mat& m1, int widthScale)
959 CV_CheckLE(m1.dims, 2, "");
960 return getContinuousSize_(m1.flags,
961 m1.cols, m1.rows, widthScale);
963 Size getContinuousSize2D(Mat& m1, Mat& m2, int widthScale)
965 CV_CheckLE(m1.dims, 2, "");
966 CV_CheckLE(m2.dims, 2, "");
967 const Size sz1 = m1.size();
968 if (sz1 != m2.size()) // reshape all matrixes to the same size (#4159)
970 size_t total_sz = m1.total();
971 CV_CheckEQ(total_sz, m2.total(), "");
972 bool is_m1_vector = m1.cols == 1 || m1.rows == 1;
973 bool is_m2_vector = m2.cols == 1 || m2.rows == 1;
974 CV_Assert(is_m1_vector); CV_Assert(is_m2_vector);
975 int total = (int)total_sz; // vector-column
976 bool isContiguous = ((m1.flags & m2.flags) & Mat::CONTINUOUS_FLAG) != 0;
977 bool has_int_overflow = ((int64)total_sz * widthScale) >= INT_MAX;
978 if (isContiguous && !has_int_overflow)
979 total = 1; // vector-row
980 m1 = m1.reshape(0, total);
981 m2 = m2.reshape(0, total);
982 CV_Assert(m1.cols == m2.cols && m1.rows == m2.rows);
983 return Size(m1.cols * widthScale, m1.rows);
985 return getContinuousSize_(m1.flags & m2.flags,
986 m1.cols, m1.rows, widthScale);
989 Size getContinuousSize2D(Mat& m1, Mat& m2, Mat& m3, int widthScale)
991 CV_CheckLE(m1.dims, 2, "");
992 CV_CheckLE(m2.dims, 2, "");
993 CV_CheckLE(m3.dims, 2, "");
994 const Size sz1 = m1.size();
995 if (sz1 != m2.size() || sz1 != m3.size()) // reshape all matrixes to the same size (#4159)
997 size_t total_sz = m1.total();
998 CV_CheckEQ(total_sz, m2.total(), "");
999 CV_CheckEQ(total_sz, m3.total(), "");
1000 bool is_m1_vector = m1.cols == 1 || m1.rows == 1;
1001 bool is_m2_vector = m2.cols == 1 || m2.rows == 1;
1002 bool is_m3_vector = m3.cols == 1 || m3.rows == 1;
1003 CV_Assert(is_m1_vector); CV_Assert(is_m2_vector); CV_Assert(is_m3_vector);
1004 int total = (int)total_sz; // vector-column
1005 bool isContiguous = ((m1.flags & m2.flags & m3.flags) & Mat::CONTINUOUS_FLAG) != 0;
1006 bool has_int_overflow = ((int64)total_sz * widthScale) >= INT_MAX;
1007 if (isContiguous && !has_int_overflow)
1008 total = 1; // vector-row
1009 m1 = m1.reshape(0, total);
1010 m2 = m2.reshape(0, total);
1011 m3 = m3.reshape(0, total);
1012 CV_Assert(m1.cols == m2.cols && m1.rows == m2.rows && m1.cols == m3.cols && m1.rows == m3.rows);
1013 return Size(m1.cols * widthScale, m1.rows);
1015 return getContinuousSize_(m1.flags & m2.flags & m3.flags,
1016 m1.cols, m1.rows, widthScale);