added Mat::push_back, pop_back and related operations; enabled reading/writing/creati...
authorVadim Pisarevsky <no@email>
Mon, 18 Oct 2010 08:51:46 +0000 (08:51 +0000)
committerVadim Pisarevsky <no@email>
Mon, 18 Oct 2010 08:51:46 +0000 (08:51 +0000)
modules/core/include/opencv2/core/core.hpp
modules/core/include/opencv2/core/mat.hpp
modules/core/include/opencv2/core/operations.hpp
modules/core/include/opencv2/core/types_c.h
modules/core/src/array.cpp
modules/core/src/copy.cpp
modules/core/src/matrix.cpp
modules/core/src/persistence.cpp

index 59b319b..b969100 100644 (file)
@@ -94,6 +94,7 @@ class CV_EXPORTS VectorArg;
 class CV_EXPORTS MatArg;
 class CV_EXPORTS MatConstIterator;
 
+template<typename _Tp> class CV_EXPORTS Mat_;
 template<typename _Tp> class CV_EXPORTS MatIterator_;
 template<typename _Tp> class CV_EXPORTS MatConstIterator_;
 template<typename _Tp> class CV_EXPORTS MatCommaInitializer_;
@@ -1600,7 +1601,22 @@ public:
     void deallocate();
     //! internal use function; properly re-allocates _size, _step arrays
     void copySize(const Mat& m);
-
+    
+    //! reserves enough space to fit sz hyper-planes
+    void reserve(size_t sz);
+    //! resizes matrix to the specified number of hyper-planes
+    void resize(size_t sz);
+    //! resizes matrix to the specified number of hyper-planes; initializes the newly added elements
+    void resize(size_t sz, const Scalar& s);
+    //! internal function
+    void push_back_(const void* elem);
+    //! adds element to the end of 1d matrix (or possibly multiple elements when _Tp=Mat)
+    template<typename _Tp> void push_back(const _Tp& elem);
+    template<typename _Tp> void push_back(const Mat_<_Tp>& elem);
+    void push_back(const Mat& m);
+    //! removes several hyper-planes from bottom of the matrix
+    void pop_back(size_t nelems);
+    
     //! locates matrix header within a parent matrix. See below
     void locateROI( Size& wholeSize, Point& ofs ) const;
     //! moves/resizes the current matrix ROI inside the parent matrix.
@@ -1626,6 +1642,10 @@ public:
     // (i.e. when there are no gaps between successive rows).
     // similar to CV_IS_MAT_CONT(cvmat->type)
     bool isContinuous() const;
+    
+    //! returns true if the matrix is a submatrix of another matrix
+    bool isSubmatrix() const;
+    
     //! returns element size in bytes,
     // similar to CV_ELEM_SIZE(cvmat->type)
     size_t elemSize() const;
@@ -1707,7 +1727,7 @@ public:
     template<typename _Tp> MatConstIterator_<_Tp> begin() const;
     template<typename _Tp> MatConstIterator_<_Tp> end() const;
 
-    enum { MAGIC_VAL=0x42FF0000, AUTO_STEP=0, CONTINUOUS_FLAG=CV_MAT_CONT_FLAG };
+    enum { MAGIC_VAL=0x42FF0000, AUTO_STEP=0, CONTINUOUS_FLAG=CV_MAT_CONT_FLAG, SUBMATRIX_FLAG=CV_SUBMAT_FLAG };
 
     /*! includes several bit-fields:
          - the magic signature
@@ -1730,6 +1750,8 @@ public:
     //! helper fields used in locateROI and adjustROI
     uchar* datastart;
     uchar* dataend;
+    uchar* datalimit;
+    
     //! custom allocator
     ArrayAllocator* allocator;
     
@@ -2252,13 +2274,13 @@ CV_EXPORTS void fillConvexPoly(Mat& img, CV_CARRAY(npts) const Point* pts, int n
                                int shift=0);
 
 //! fills an area bounded by one or more polygons
-CV_EXPORTS void fillPoly(Mat& img, CV_CARRAY(ncontours) const Point** pts,
+CV_EXPORTS void fillPoly(Mat& img, CV_CARRAY(ncontours.npts) const Point** pts,
                          CV_CARRAY(ncontours) const int* npts, int ncontours,
                          const Scalar& color, int lineType=8, int shift=0,
                          Point offset=Point() );
 
 //! draws one or more polygonal curves
-CV_EXPORTS void polylines(Mat& img, CV_CARRAY(ncontours) const Point** pts, CV_CARRAY(ncontours) const int* npts,
+CV_EXPORTS void polylines(Mat& img, CV_CARRAY(ncontours.npts) const Point** pts, CV_CARRAY(ncontours) const int* npts,
                           int ncontours, bool isClosed, const Scalar& color,
                           int thickness=1, int lineType=8, int shift=0 );
 
index c034215..e53761f 100644 (file)
@@ -57,20 +57,20 @@ namespace cv
 
 inline Mat::Mat()
     : flags(0), dims(0), rows(0), cols(0), data(0), refcount(0),
-    datastart(0), dataend(0), allocator(0), size(&rows)
+    datastart(0), dataend(0), datalimit(0), allocator(0), size(&rows)
 {
 }
 
 inline Mat::Mat(int _rows, int _cols, int _type)
     : flags(0), dims(0), rows(0), cols(0), data(0), refcount(0),
-    datastart(0), dataend(0), allocator(0), size(&rows)
+    datastart(0), dataend(0), datalimit(0), allocator(0), size(&rows)
 {
     create(_rows, _cols, _type);
 }
 
 inline Mat::Mat(int _rows, int _cols, int _type, const Scalar& _s)
     : flags(0), dims(0), rows(0), cols(0), data(0), refcount(0),
-    datastart(0), dataend(0), allocator(0), size(&rows)
+    datastart(0), dataend(0), datalimit(0), allocator(0), size(&rows)
 {
     create(_rows, _cols, _type);
     *this = _s;
@@ -78,14 +78,14 @@ inline Mat::Mat(int _rows, int _cols, int _type, const Scalar& _s)
 
 inline Mat::Mat(Size _sz, int _type)
     : flags(0), dims(0), rows(0), cols(0), data(0), refcount(0),
-    datastart(0), dataend(0), allocator(0), size(&rows)
+    datastart(0), dataend(0), datalimit(0), allocator(0), size(&rows)
 {
     create( _sz.height, _sz.width, _type );
 }
     
 inline Mat::Mat(Size _sz, int _type, const Scalar& _s)
     : flags(0), dims(0), rows(0), cols(0), data(0), refcount(0),
-    datastart(0), dataend(0), allocator(0), size(&rows)
+    datastart(0), dataend(0), datalimit(0), allocator(0), size(&rows)
 {
     create(_sz.height, _sz.width, _type);
     *this = _s;
@@ -93,14 +93,14 @@ inline Mat::Mat(Size _sz, int _type, const Scalar& _s)
     
 inline Mat::Mat(int _dims, const int* _sz, int _type)
     : flags(0), dims(0), rows(0), cols(0), data(0), refcount(0),
-    datastart(0), dataend(0), allocator(0), size(&rows)
+    datastart(0), dataend(0), datalimit(0), allocator(0), size(&rows)
 {
     create(_dims, _sz, _type);
 }
 
 inline Mat::Mat(int _dims, const int* _sz, int _type, const Scalar& _s)
     : flags(0), dims(0), rows(0), cols(0), data(0), refcount(0),
-    datastart(0), dataend(0), allocator(0), size(&rows)
+    datastart(0), dataend(0), datalimit(0), allocator(0), size(&rows)
 {
     create(_dims, _sz, _type);
     *this = _s;
@@ -109,7 +109,7 @@ inline Mat::Mat(int _dims, const int* _sz, int _type, const Scalar& _s)
 inline Mat::Mat(const Mat& m)
     : flags(m.flags), dims(m.dims), rows(m.rows), cols(m.cols), data(m.data),
     refcount(m.refcount), datastart(m.datastart), dataend(m.dataend),
-    allocator(m.allocator), size(&rows)
+    datalimit(m.datalimit), allocator(m.allocator), size(&rows)
 {
     if( refcount )
         CV_XADD(refcount, 1);
@@ -126,10 +126,10 @@ inline Mat::Mat(const Mat& m)
 
 inline Mat::Mat(int _rows, int _cols, int _type, void* _data, size_t _step)
     : flags(MAGIC_VAL + (_type & TYPE_MASK)), dims(2), rows(_rows), cols(_cols),
-    data((uchar*)_data), refcount(0), datastart((uchar*)_data), dataend((uchar*)_data),
-    allocator(0), size(&rows)
+    data((uchar*)_data), refcount(0), datastart((uchar*)_data), dataend(0),
+    datalimit(0), allocator(0), size(&rows)
 {
-    size_t minstep = cols*elemSize();
+    size_t esz = CV_ELEM_SIZE(_type), minstep = cols*esz;
     if( _step == AUTO_STEP )
     {
         _step = minstep;
@@ -141,16 +141,17 @@ inline Mat::Mat(int _rows, int _cols, int _type, void* _data, size_t _step)
         CV_DbgAssert( _step >= minstep );
         flags |= _step == minstep ? CONTINUOUS_FLAG : 0;
     }
-    step[0] = _step; step[1] = elemSize();
-    dataend += _step*(rows-1) + minstep;
+    step[0] = _step; step[1] = esz;
+    datalimit = datastart + _step*rows;
+    dataend = datalimit - _step + minstep;
 }
 
 inline Mat::Mat(Size _sz, int _type, void* _data, size_t _step)
     : flags(MAGIC_VAL + (_type & TYPE_MASK)), dims(2), rows(_sz.height), cols(_sz.width),
-    data((uchar*)_data), refcount(0), datastart((uchar*)_data), dataend((uchar*)_data),
-    allocator(0), size(&rows)
+    data((uchar*)_data), refcount(0), datastart((uchar*)_data), dataend(0),
+    datalimit(0), allocator(0), size(&rows)
 {
-    size_t minstep = cols*elemSize();
+    size_t esz = CV_ELEM_SIZE(_type), minstep = cols*esz;
     if( _step == AUTO_STEP )
     {
         _step = minstep;
@@ -162,23 +163,25 @@ inline Mat::Mat(Size _sz, int _type, void* _data, size_t _step)
         CV_DbgAssert( _step >= minstep );
         flags |= _step == minstep ? CONTINUOUS_FLAG : 0;
     }
-    step[0] = _step; step[1] = elemSize();
-    dataend += _step*(rows-1) + minstep;
+    step[0] = _step; step[1] = esz;
+    datalimit = datastart + _step*rows;
+    dataend = datalimit - _step + minstep;
 }
 
     
 inline Mat::Mat(const CvMat* m, bool copyData)
     : flags(MAGIC_VAL + (m->type & (CV_MAT_TYPE_MASK|CV_MAT_CONT_FLAG))),
     dims(2), rows(m->rows), cols(m->cols), data(m->data.ptr), refcount(0),
-    datastart(m->data.ptr), dataend(m->data.ptr),
+    datastart(0), dataend(0),
     allocator(0), size(&rows)
 {
     if( !copyData )
     {
-        size_t esz = elemSize(), minstep = cols*esz, _step = m->step;
+        size_t esz = CV_ELEM_SIZE(m->type), minstep = cols*esz, _step = m->step;
         if( _step == 0 )
             _step = minstep;
-        dataend += _step*(rows-1) + minstep;
+        datalimit = datastart + _step*rows;
+        dataend = datalimit - _step + minstep;
         step[0] = _step; step[1] = esz;
     }
     else
@@ -199,7 +202,7 @@ template<typename _Tp> inline Mat::Mat(const vector<_Tp>& vec, bool copyData)
     {
         step[0] = step[1] = sizeof(_Tp);
         data = datastart = (uchar*)&vec[0];
-        dataend = datastart + rows*step[0];
+        datalimit = dataend = datastart + rows*step[0];
     }
     else
         Mat((int)vec.size(), 1, DataType<_Tp>::type, (uchar*)&vec[0]).copyTo(*this);
@@ -215,7 +218,7 @@ template<typename _Tp, int n> inline Mat::Mat(const Vec<_Tp, n>& vec, bool copyD
     {
         step[0] = step[1] = sizeof(_Tp);
         data = datastart = (uchar*)vec.val;
-        dataend = datastart + rows*step[0];
+        datalimit = dataend = datastart + rows*step[0];
     }
     else
         Mat(n, 1, DataType<_Tp>::type, (void*)vec.val).copyTo(*this);
@@ -232,7 +235,7 @@ template<typename _Tp, int m, int n> inline Mat::Mat(const Matx<_Tp,m,n>& M, boo
         step[0] = cols*sizeof(_Tp);
         step[1] = sizeof(_Tp);
         data = datastart = (uchar*)M.val;
-        dataend = datastart + rows*step[0];
+        datalimit = dataend = datastart + rows*step[0];
     }
     else
         Mat(m, n, DataType<_Tp>::type, (uchar*)M.val).copyTo(*this);    
@@ -248,7 +251,7 @@ template<typename _Tp> inline Mat::Mat(const Point_<_Tp>& pt, bool copyData)
     {
         step[0] = step[1] = sizeof(_Tp);
         data = datastart = (uchar*)&pt.x;
-        dataend = datastart + rows*step[0];
+        datalimit = dataend = datastart + rows*step[0];
     }
     else
     {
@@ -268,7 +271,7 @@ template<typename _Tp> inline Mat::Mat(const Point3_<_Tp>& pt, bool copyData)
     {
         step[0] = step[1] = sizeof(_Tp);
         data = datastart = (uchar*)&pt.x;
-        dataend = datastart + rows*step[0];
+        datalimit = dataend = datastart + rows*step[0];
     }
     else
     {
@@ -314,7 +317,9 @@ inline Mat& Mat::operator = (const Mat& m)
         else
             copySize(m);
         data = m.data;
-        datastart = m.datastart; dataend = m.dataend;
+        datastart = m.datastart;
+        dataend = m.dataend;
+        datalimit = m.datalimit;
         refcount = m.refcount;
         allocator = m.allocator;
     }
@@ -375,8 +380,8 @@ inline void Mat::release()
 {
     if( refcount && CV_XADD(refcount, -1) == 1 )
         deallocate();
-    data = datastart = dataend = 0;
-    rows = cols = 0;
+    data = datastart = dataend = datalimit = 0;
+    size.p[0] = 0;
     refcount = 0;
 }
 
@@ -403,13 +408,14 @@ inline Mat::operator CvMat() const
 }
 
 inline bool Mat::isContinuous() const { return (flags & CONTINUOUS_FLAG) != 0; }
-inline size_t Mat::elemSize() const { return CV_ELEM_SIZE(flags); }
+inline bool Mat::isSubmatrix() const { return (flags & SUBMATRIX_FLAG) != 0; }
+inline size_t Mat::elemSize() const { return step.p[dims-1]; }
 inline size_t Mat::elemSize1() const { return CV_ELEM_SIZE1(flags); }
 inline int Mat::type() const { return CV_MAT_TYPE(flags); }
 inline int Mat::depth() const { return CV_MAT_DEPTH(flags); }
 inline int Mat::channels() const { return CV_MAT_CN(flags); }
 inline size_t Mat::step1(int i) const { return step.p[i]/elemSize1(); }
-inline bool Mat::empty() const { return data == 0; }
+inline bool Mat::empty() const { return data == 0 || size.p[0] == 0; }
 inline size_t Mat::total() const
 {
     if( dims <= 2 )
@@ -581,7 +587,7 @@ template<typename _Tp> inline MatIterator_<_Tp> Mat::end()
 
 template<typename _Tp> inline Mat::operator vector<_Tp>() const
 {
-    if( !data )
+    if( empty() )
         return vector<_Tp>();
     CV_Assert( dims >= 1 && DataType<_Tp>::channels == channels());
     vector<_Tp> v(total());
@@ -611,10 +617,34 @@ template<typename _Tp, int m, int n> inline Mat::operator Matx<_Tp, m, n>() cons
     Matx<_Tp, m, n> mtx; Mat tmp(rows, cols, DataType<_Tp>::type, mtx.val);
     convertTo(tmp, tmp.type());
     return mtx;
-}    
+}
 
+
+template<typename _Tp> inline void Mat::push_back(const _Tp& elem)
+{
+    CV_Assert(DataType<_Tp>::type == type() && cols == 1
+              /* && dims == 2 (cols == 1 implies dims == 2) */);
+    uchar* tmp = dataend + step[0];
+    if( !isSubmatrix() && isContinuous() && tmp <= datalimit )
+    {
+        *(_Tp*)(data + (size.p[0]++)*step.p[0]) = elem;
+        dataend = tmp;
+    }
+    else
+        push_back_(&elem);
+}
+    
+template<typename _Tp> inline void Mat::push_back(const Mat_<_Tp>& m)
+{
+    push_back((const Mat&)m);
+}    
+    
 inline Mat::MSize::MSize(int* _p) : p(_p) {}
-inline Size Mat::MSize::operator()() const { return Size(p[1], p[0]); }
+inline Size Mat::MSize::operator()() const
+{
+    CV_DbgAssert(p[-1] <= 2); 
+    return Size(p[1], p[0]);
+}
 inline int Mat::MSize::operator[](int i) const { return p[i]; }
 inline int& Mat::MSize::operator[](int i) { return p[i]; }
 inline Mat::MSize::operator const int*() const { return p; }
@@ -642,8 +672,17 @@ inline Mat::MStep::MStep() { p = buf; p[0] = p[1] = 0; }
 inline Mat::MStep::MStep(size_t s) { p = buf; p[0] = s; p[1] = 0; }
 inline size_t Mat::MStep::operator[](int i) const { return p[i]; }
 inline size_t& Mat::MStep::operator[](int i) { return p[i]; }
-inline Mat::MStep::operator size_t() const { return p[0]; }
-inline Mat::MStep& Mat::MStep::operator = (size_t s) { p[0] = s; return *this; }
+inline Mat::MStep::operator size_t() const
+{
+    CV_DbgAssert( p == buf );
+    return buf[0];
+}
+inline Mat::MStep& Mat::MStep::operator = (size_t s)
+{
+    CV_DbgAssert( p == buf );
+    buf[0] = s;
+    return *this;
+}
     
 static inline Mat cvarrToMatND(const CvArr* arr, bool copyData=false, int coiMode=0)
 {
index 8e0b5aa..8341022 100644 (file)
@@ -2692,7 +2692,6 @@ operator << ( FileStorage& fs, const vector<_Tp>& vec )
 }
 
 CV_EXPORTS void write( FileStorage& fs, const string& name, const Mat& value );
-CV_EXPORTS void write( FileStorage& fs, const string& name, const MatND& value );
 CV_EXPORTS void write( FileStorage& fs, const string& name, const SparseMat& value );
 
 template<typename _Tp> static inline FileStorage& operator << (FileStorage& fs, const _Tp& value)
index 7e7d761..986cdab 100644 (file)
@@ -601,9 +601,9 @@ IplConvKernelFP;
 #define CV_MAT_CONT_FLAG        (1 << CV_MAT_CONT_FLAG_SHIFT)
 #define CV_IS_MAT_CONT(flags)   ((flags) & CV_MAT_CONT_FLAG)
 #define CV_IS_CONT_MAT          CV_IS_MAT_CONT
-#define CV_MAT_TEMP_FLAG_SHIFT  15
-#define CV_MAT_TEMP_FLAG        (1 << CV_MAT_TEMP_FLAG_SHIFT)
-#define CV_IS_TEMP_MAT(flags)   ((flags) & CV_MAT_TEMP_FLAG)
+#define CV_SUBMAT_FLAG_SHIFT    15
+#define CV_SUBMAT_FLAG          (1 << CV_SUBMAT_FLAG_SHIFT)
+#define CV_IS_SUBMAT(flags)     ((flags) & CV_MAT_SUBMAT_FLAG)
 
 #define CV_MAGIC_MASK       0xFFFF0000
 #define CV_MAT_MAGIC_VAL    0x42420000
@@ -653,6 +653,11 @@ CvMat;
     (((const CvMat*)(mat))->type & CV_MAGIC_MASK) == CV_MAT_MAGIC_VAL && \
     ((const CvMat*)(mat))->cols > 0 && ((const CvMat*)(mat))->rows > 0)
 
+#define CV_IS_MAT_HDR_Z(mat) \
+    ((mat) != NULL && \
+    (((const CvMat*)(mat))->type & CV_MAGIC_MASK) == CV_MAT_MAGIC_VAL && \
+    ((const CvMat*)(mat))->cols >= 0 && ((const CvMat*)(mat))->rows >= 0)
+
 #define CV_IS_MAT(mat) \
     (CV_IS_MAT_HDR(mat) && ((const CvMat*)(mat))->data.ptr != NULL)
 
index 7778084..d78bfe2 100644 (file)
@@ -109,7 +109,7 @@ cvCreateMatHeader( int rows, int cols, int type )
 {
     type = CV_MAT_TYPE(type);
 
-    if( rows <= 0 || cols <= 0 )
+    if( rows < 0 || cols <= 0 )
         CV_Error( CV_StsBadSize, "Non-positive width or height" );
 
     int min_step = CV_ELEM_SIZE(type)*cols;
@@ -142,7 +142,7 @@ cvInitMatHeader( CvMat* arr, int rows, int cols,
     if( (unsigned)CV_MAT_DEPTH(type) > CV_DEPTH_MAX )
         CV_Error( CV_BadNumChannels, "" );
 
-    if( rows <= 0 || cols <= 0 )
+    if( rows < 0 || cols <= 0 )
         CV_Error( CV_StsBadSize, "Non-positive cols or rows" );
  
     type = CV_MAT_TYPE( type );
@@ -175,12 +175,6 @@ cvInitMatHeader( CvMat* arr, int rows, int cols,
 }
 
 
-#undef CV_IS_MAT_HDR_Z
-#define CV_IS_MAT_HDR_Z(mat) \
-    ((mat) != NULL && \
-    (((const CvMat*)(mat))->type & CV_MAGIC_MASK) == CV_MAT_MAGIC_VAL && \
-    ((const CvMat*)(mat))->cols >= 0 && ((const CvMat*)(mat))->rows >= 0)
-
 // Deallocates the CvMat structure and underlying data
 CV_IMPL void
 cvReleaseMat( CvMat** array )
@@ -248,7 +242,7 @@ cvInitMatNDHeader( CvMatND* mat, int dims, const int* sizes,
 
     for( int i = dims - 1; i >= 0; i-- )
     {
-        if( sizes[i] <= 0 )
+        if( sizes[i] < 0 )
             CV_Error( CV_StsBadSize, "one of dimesion sizes is non-positive" );
         mat->dim[i].size = sizes[i];
         if( step > INT_MAX )
@@ -795,12 +789,15 @@ icvDeleteNode( CvSparseMat* mat, const int* idx, unsigned* precalc_hashval )
 CV_IMPL void
 cvCreateData( CvArr* arr )
 {
-    if( CV_IS_MAT_HDR( arr ))
+    if( CV_IS_MAT_HDR_Z( arr ))
     {
         size_t step, total_size;
         CvMat* mat = (CvMat*)arr;
         step = mat->step;
 
+        if( mat->rows == 0 || mat->cols == 0 )
+            return;
+        
         if( mat->data.ptr != 0 )
             CV_Error( CV_StsError, "Data is already allocated" );
 
@@ -849,6 +846,9 @@ cvCreateData( CvArr* arr )
         CvMatND* mat = (CvMatND*)arr;
         int i;
         size_t total_size = CV_ELEM_SIZE(mat->type);
+        
+        if( mat->dim[0].size == 0 )
+            return;
 
         if( mat->data.ptr != 0 )
             CV_Error( CV_StsError, "Data is already allocated" );
@@ -1207,7 +1207,7 @@ cvGetSize( const CvArr* arr )
 {
     CvSize size = { 0, 0 };
 
-    if( CV_IS_MAT_HDR( arr ))
+    if( CV_IS_MAT_HDR_Z( arr ))
     {
         CvMat *mat = (CvMat*)arr;
 
index 9119866..84950cd 100644 (file)
@@ -166,38 +166,45 @@ static SetMaskFunc setMaskFuncTab[] =
 /* dst = src */
 void Mat::copyTo( Mat& dst ) const
 {
-    if( data == dst.data )
+    if( data == dst.data && data != 0 )
         return;
     
     if( dims > 2 )
     {
         dst.create( dims, size, type() );
-        const Mat* arrays[] = { this, &dst, 0 };
-        Mat planes[2];
-        NAryMatIterator it(arrays, planes);
-        CV_DbgAssert(it.planes[0].isContinuous() &&
-                     it.planes[1].isContinuous());
-        size_t planeSize = it.planes[0].elemSize()*it.planes[0].rows*it.planes[0].cols;
-    
-        for( int i = 0; i < it.nplanes; i++, ++it )
-            memcpy(it.planes[1].data, it.planes[0].data, planeSize);
+        if( total() != 0 )
+        {
+            const Mat* arrays[] = { this, &dst, 0 };
+            Mat planes[2];
+            NAryMatIterator it(arrays, planes);
+            CV_DbgAssert(it.planes[0].isContinuous() &&
+                         it.planes[1].isContinuous());
+            size_t planeSize = it.planes[0].elemSize()*it.planes[0].rows*it.planes[0].cols;
+        
+            for( int i = 0; i < it.nplanes; i++, ++it )
+                memcpy(it.planes[1].data, it.planes[0].data, planeSize);
+        }
         return;
     }
     
     dst.create( rows, cols, type() );
     Size sz = size();
-    const uchar* sptr = data;
-    uchar* dptr = dst.data;
-
-    sz.width *= (int)elemSize();
-    if( isContinuous() && dst.isContinuous() )
+    
+    if( rows > 0 && cols > 0 )
     {
-        sz.width *= sz.height;
-        sz.height = 1;
-    }
+        const uchar* sptr = data;
+        uchar* dptr = dst.data;
 
-    for( ; sz.height--; sptr += step, dptr += dst.step )
-        memcpy( dptr, sptr, sz.width );
+        size_t width = sz.width*elemSize();
+        if( isContinuous() && dst.isContinuous() )
+        {
+            width *= sz.height;
+            sz.height = 1;
+        }
+
+        for( ; sz.height--; sptr += step, dptr += dst.step )
+            memcpy( dptr, sptr, width );
+    }
 }
 
 void Mat::copyTo( Mat& dst, const Mat& mask ) const
index 781a060..80113e9 100644 (file)
@@ -94,12 +94,12 @@ static inline void setSize( Mat& m, int _dims, const int* _sz,
     if( !_sz )
         return;
     
-    size_t esz = m.elemSize(), total = esz;
+    size_t esz = CV_ELEM_SIZE(m.flags), total = esz;
     int i;
     for( i = _dims-1; i >= 0; i-- )
     {
         int s = _sz[i];
-        CV_Assert( s > 0 );
+        CV_Assert( s >= (i == 0 ? 0 : 1) );
         m.size.p[i] = s;
         
         if( _steps )
@@ -121,11 +121,10 @@ static inline void setSize( Mat& m, int _dims, const int* _sz,
         m.step[1] = esz;
     }
 }
-    
-static void finalizeHdr(Mat& m)
+   
+static void updateContinuityFlag(Mat& m)
 {
     int i, j;
-    
     for( i = 0; i < m.dims; i++ )
     {
         if( m.size[i] > 1 )
@@ -137,19 +136,33 @@ static void finalizeHdr(Mat& m)
         if( m.step[j]*m.size[j] < m.step[j-1] )
             break;
     }
-    m.flags &= ~Mat::CONTINUOUS_FLAG;
-    int64 t = (int64)(m.step[0]/m.elemSize())*m.size[0];
+    
+    int64 t = (int64)(m.step[0]/CV_ELEM_SIZE(m.flags))*m.size[0];
     if( j <= i && t == (int)t )
         m.flags |= Mat::CONTINUOUS_FLAG;
+    else
+        m.flags &= ~Mat::CONTINUOUS_FLAG;
+}
     
+static void finalizeHdr(Mat& m)
+{
+    updateContinuityFlag(m);
     if( m.dims > 2 )
         m.rows = m.cols = -1;
     if( m.data )
     {
-        m.dataend = m.data;
-        for( i = 0; i < m.dims; i++ )
-            m.dataend += (m.size[i] - 1)*m.step[i];
+        m.datalimit = m.datastart + m.size[0]*m.step[0];
+        if( m.size[0] > 0 )
+        {
+            m.dataend = m.data;
+            for( int i = 0; i < m.dims; i++ )
+                m.dataend += (m.size[i] - 1)*m.step[i];
+        }
+        else
+            m.dataend = m.datalimit;
     }
+    else
+        m.dataend = m.datalimit = 0;
 }
     
     
@@ -176,17 +189,20 @@ void Mat::create(int d, const int* _sizes, int _type)
     flags = (_type & CV_MAT_TYPE_MASK) | MAGIC_VAL;
     setSize(*this, d, _sizes, 0, allocator == 0);
     
-    if( !allocator )
-    {
-        size_t total = alignSize(step.p[0]*size.p[0], (int)sizeof(*refcount));
-        data = datastart = (uchar*)fastMalloc(total + (int)sizeof(*refcount));
-        refcount = (int*)(data + total);
-        *refcount = 1;
-    }
-    else
+    if( size.p[0] > 0 )
     {
-        allocator->allocate(dims, size, _type, refcount, datastart, data, step.p);
-        CV_Assert( step[dims-1] == elemSize() );
+        if( !allocator )
+        {
+            size_t total = alignSize(step.p[0]*size.p[0], (int)sizeof(*refcount));
+            data = datastart = (uchar*)fastMalloc(total + (int)sizeof(*refcount));
+            refcount = (int*)(data + total);
+            *refcount = 1;
+        }
+        else
+        {
+            allocator->allocate(dims, size, _type, refcount, datastart, data, step.p);
+            CV_Assert( step[dims-1] == (size_t)CV_ELEM_SIZE(flags) );
+        }
     }
     
     finalizeHdr(*this);
@@ -216,7 +232,7 @@ void Mat::deallocate()
     
 Mat::Mat(const Mat& m, const Range& rowRange, const Range& colRange)
     : flags(0), dims(0), rows(0), cols(0), data(0), refcount(0),
-    datastart(0), dataend(0), allocator(0), size(&rows)
+    datastart(0), dataend(0), datalimit(0), allocator(0), size(&rows)
 {
     CV_Assert( m.dims >= 2 );
     if( m.dims > 2 )
@@ -231,19 +247,21 @@ Mat::Mat(const Mat& m, const Range& rowRange, const Range& colRange)
     }
     
     *this = m;
-    if( rowRange != Range::all() )
+    if( rowRange != Range::all() && rowRange != Range(0,rows) )
     {
         CV_Assert( 0 <= rowRange.start && rowRange.start <= rowRange.end && rowRange.end <= m.rows );
         rows = rowRange.size();
         data += step*rowRange.start;
+        flags |= SUBMATRIX_FLAG;
     }
     
-    if( colRange != Range::all() )
+    if( colRange != Range::all() && colRange != Range(0,cols) )
     {
         CV_Assert( 0 <= colRange.start && colRange.start <= colRange.end && colRange.end <= m.cols );
         cols = colRange.size();
         data += colRange.start*elemSize();
         flags &= cols < m.cols ? ~CONTINUOUS_FLAG : -1;
+        flags |= SUBMATRIX_FLAG;
     }
     
     if( rows == 1 )
@@ -262,18 +280,21 @@ Mat::Mat(const Mat& m, const Range& rowRange, const Range& colRange)
 Mat::Mat(const Mat& m, const Rect& roi)
     : flags(m.flags), dims(2), rows(roi.height), cols(roi.width),
     data(m.data + roi.y*m.step[0]), refcount(m.refcount),
-    datastart(m.datastart), dataend(m.dataend), allocator(m.allocator), size(&rows)
+    datastart(m.datastart), dataend(m.dataend), datalimit(m.datalimit),
+    allocator(m.allocator), 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 = elemSize();
+    size_t esz = CV_ELEM_SIZE(flags);
     data += roi.x*esz;
     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 )
         CV_XADD(refcount, 1);
+    if( roi.width < m.cols || roi.height < m.rows )
+        flags |= SUBMATRIX_FLAG;
     
     step[0] = m.step[0]; step[1] = esz;
     
@@ -286,9 +307,10 @@ Mat::Mat(const Mat& m, const Rect& roi)
 
     
 Mat::Mat(int _dims, const int* _sizes, int _type, void* _data, const size_t* _steps)
-    : flags(MAGIC_VAL|CV_MAT_TYPE(_type)), dims(0), rows(0), cols(0),
-    data((uchar*)_data), refcount(0),
-    datastart((uchar*)_data), dataend((uchar*)_data), allocator(0), size(&rows)
+    : flags(MAGIC_VAL|CV_MAT_TYPE(_type)), dims(0),
+    rows(0), cols(0), data((uchar*)_data), refcount(0),
+    datastart((uchar*)_data), dataend((uchar*)_data), datalimit((uchar*)_data),
+    allocator(0), size(&rows)
 {
     setSize(*this, _dims, _sizes, _steps, true);
     finalizeHdr(*this);
@@ -297,7 +319,7 @@ Mat::Mat(int _dims, const int* _sizes, int _type, void* _data, const size_t* _st
     
 Mat::Mat(const Mat& m, const Range* ranges)
     : flags(m.flags), dims(0), rows(0), cols(0), data(0), refcount(0),
-    datastart(0), dataend(0), allocator(0), size(&rows)
+    datastart(0), dataend(0), datalimit(0), allocator(0), size(&rows)
 {
     int i, d = m.dims;
     
@@ -311,21 +333,21 @@ Mat::Mat(const Mat& m, const Range* ranges)
     for( i = 0; i < d; i++ )
     {
         Range r = ranges[i];
-        if( r != Range::all() )
+        if( r != Range::all() && r != Range(0, size.p[i]))
         {
-            size[i] = r.end - r.start;
-            data += r.start*step[i];
+            size.p[i] = r.end - r.start;
+            data += r.start*step.p[i];
+            flags |= SUBMATRIX_FLAG;
         }
     }
-    
-    finalizeHdr(*this);
+    updateContinuityFlag(*this);
 }
  
     
 Mat::Mat(const CvMatND* m, bool copyData)
     : flags(MAGIC_VAL|CV_MAT_TYPE(m->type)), dims(0), rows(0), cols(0),
     data((uchar*)m->data.ptr), refcount(0),
-    datastart((uchar*)m->data.ptr), dataend((uchar*)m->data.ptr), allocator(0),
+    datastart((uchar*)m->data.ptr), allocator(0),
     size(&rows)
 {
     int _sizes[CV_MAX_DIM];
@@ -376,6 +398,10 @@ Mat Mat::diag(int d) const
         m.flags &= ~CONTINUOUS_FLAG;
     else
         m.flags |= CONTINUOUS_FLAG;
+    
+    if( size() != Size(1,1) )
+        m.flags |= SUBMATRIX_FLAG;
+    
     return m;
 }
     
@@ -396,7 +422,7 @@ Mat::Mat(const IplImage* img, bool copyData)
         flags = MAGIC_VAL + CV_MAKETYPE(depth, img->nChannels);
         rows = img->height; cols = img->width;
         datastart = data = (uchar*)img->imageData;
-        esz = elemSize(); 
+        esz = CV_ELEM_SIZE(flags);
     }
     else
     {
@@ -404,13 +430,14 @@ Mat::Mat(const IplImage* img, bool copyData)
         bool selectedPlane = img->roi->coi && img->dataOrder == IPL_DATA_ORDER_PLANE;
         flags = MAGIC_VAL + CV_MAKETYPE(depth, selectedPlane ? 1 : img->nChannels);
         rows = img->roi->height; cols = img->roi->width;
-        esz = elemSize();
+        esz = CV_ELEM_SIZE(flags);
         data = datastart = (uchar*)img->imageData +
                        (selectedPlane ? (img->roi->coi - 1)*step*img->height : 0) +
                        img->roi->yOffset*step[0] + img->roi->xOffset*esz;        
     }
-    dataend = datastart + step*(rows-1) + esz*cols;
-    flags |= (cols*esz == step || rows == 1 ? CONTINUOUS_FLAG : 0);
+    datalimit = datastart + step.p[0]*rows;
+    dataend = datastart + step.p[0]*(rows-1) + esz*cols;
+    flags |= (cols*esz == step.p[0] || rows == 1 ? CONTINUOUS_FLAG : 0);
     step[1] = esz;
 
     if( copyData )
@@ -438,7 +465,132 @@ Mat::operator IplImage() const
     cvSetData(&img, data, (int)step[0]);
     return img;
 }
+
+    
+void Mat::pop_back(size_t nelems)
+{
+    CV_Assert( nelems <= (size_t)size.p[0] );
+    
+    if( isSubmatrix() )
+        *this = rowRange(0, size.p[0] - (int)nelems);
+    else
+    {
+        size.p[0] -= (int)nelems;
+        dataend -= nelems*step.p[0];
+        /*if( size.p[0] <= 1 )
+        {
+            if( dims <= 2 )
+                flags |= CONTINUOUS_FLAG;
+            else
+                updateContinuityFlag(*this);
+        }*/
+    }
+}
+    
+    
+void Mat::push_back_(const void* elem)
+{
+    int r = size.p[0];
+    if( isSubmatrix() || dataend + step.p[0] > datalimit )
+        reserve( std::max(r + 1, (r*3+1)/2) );
+    
+    size_t esz = elemSize();
+    memcpy(data + r*step.p[0], elem, esz);
+    size.p[0] = r + 1;
+    dataend += step.p[0];
+    if( esz < step.p[0] )
+        flags &= ~CONTINUOUS_FLAG;
+}
+
+void Mat::reserve(size_t nelems)
+{
+    const size_t MIN_SIZE = 64;
+    
+    CV_Assert( (int)nelems >= 0 );
+    if( !isSubmatrix() && data + step.p[0]*nelems <= datalimit )
+        return;
+    
+    int r = size.p[0];
+    size.p[0] = std::max((int)nelems, 1);
+    size_t newsize = total()*elemSize();
+    
+    if( newsize < MIN_SIZE )
+        size.p[0] = (int)((MIN_SIZE + newsize - 1)*nelems/newsize);
+    
+    Mat m(dims, size.p, type());
+    size.p[0] = r;
+    if( r > 0 )
+    {
+        Mat mpart = m.rowRange(0, r);
+        copyTo(mpart);
+    }
     
+    *this = m;
+    size.p[0] = r;
+    dataend = data + step.p[0]*r;
+}
+
+    
+void Mat::resize(size_t nelems)
+{
+    int saveRows = size.p[0];
+    CV_Assert( (int)nelems >= 0 );
+    
+    if( isSubmatrix() || data + step.p[0]*nelems > datalimit )
+        reserve(nelems);
+    
+    size.p[0] = (int)nelems;
+    dataend += (size.p[0] - saveRows)*step.p[0];
+    
+    //updateContinuityFlag(*this);
+}    
+
+    
+void Mat::resize(size_t nelems, const Scalar& s)
+{
+    int saveRows = size.p[0];
+    resize(nelems);
+    
+    if( size.p[0] > saveRows )
+    {
+        Mat part = rowRange(saveRows, size.p[0]);
+        part = s;
+    }
+}    
+    
+void Mat::push_back(const Mat& elems)
+{
+    int r = size.p[0], delta = elems.size.p[0];
+    if( delta == 0 )
+        return;
+    if( this != &elems )
+    {
+        size.p[0] = elems.size.p[0];
+        bool eq = size == elems.size;
+        size.p[0] = r;
+        if( !eq )
+            CV_Error(CV_StsUnmatchedSizes, "");
+        if( type() != elems.type() )
+            CV_Error(CV_StsUnmatchedFormats, "");
+    }
+    
+    if( isSubmatrix() || dataend + step.p[0]*delta > datalimit )
+        reserve( std::max(r + delta, (r*3+1)/2) );
+    
+    size.p[0] += delta;
+    dataend += step.p[0]*delta;
+    
+    //updateContinuityFlag(*this);
+    
+    if( isContinuous() && elems.isContinuous() )
+        memcpy(data + r*step.p[0], elems.data, elems.total()*elems.elemSize());
+    else
+    {
+        Mat part = rowRange(r, r + delta);
+        elems.copyTo(part);
+    }
+}
+
     
 Mat cvarrToMat(const CvArr* arr, bool copyData,
                bool allowND, int coiMode)
index 0e09624..4bf4dff 100644 (file)
@@ -3328,7 +3328,7 @@ cvGetFileNodeName( const CvFileNode* file_node )
 static int
 icvIsMat( const void* ptr )
 {
-    return CV_IS_MAT_HDR(ptr);
+    return CV_IS_MAT_HDR_Z(ptr);
 }
 
 static void
@@ -3340,7 +3340,7 @@ icvWriteMat( CvFileStorage* fs, const char* name,
     CvSize size;
     int y;
 
-    assert( CV_IS_MAT(mat) );
+    assert( CV_IS_MAT_HDR_Z(mat) );
 
     cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_MAT );
     cvWriteInt( fs, "rows", mat->rows );
@@ -3349,14 +3349,17 @@ icvWriteMat( CvFileStorage* fs, const char* name,
     cvStartWriteStruct( fs, "data", CV_NODE_SEQ + CV_NODE_FLOW );
 
     size = cvGetSize(mat);
-    if( CV_IS_MAT_CONT(mat->type) )
+    if( size.height > 0 && size.width > 0 && mat->data.ptr )
     {
-        size.width *= size.height;
-        size.height = 1;
-    }
+        if( CV_IS_MAT_CONT(mat->type) )
+        {
+            size.width *= size.height;
+            size.height = 1;
+        }
 
-    for( y = 0; y < size.height; y++ )
-        cvWriteRawData( fs, mat->data.ptr + y*mat->step, size.width, dt );
+        for( y = 0; y < size.height; y++ )
+            cvWriteRawData( fs, mat->data.ptr + y*mat->step, size.width, dt );
+    }
     cvEndWriteStruct( fs );
     cvEndWriteStruct( fs );
 }
@@ -3379,11 +3382,11 @@ icvReadMat( CvFileStorage* fs, CvFileNode* node )
     CvFileNode* data;
     int rows, cols, elem_type;
 
-    rows = cvReadIntByName( fs, node, "rows", 0 );
-    cols = cvReadIntByName( fs, node, "cols", 0 );
+    rows = cvReadIntByName( fs, node, "rows", -1 );
+    cols = cvReadIntByName( fs, node, "cols", -1 );
     dt = cvReadStringByName( fs, node, "dt", 0 );
 
-    if( rows == 0 || cols == 0 || dt == 0 )
+    if( rows < 0 || cols < 0 || dt < 0 )
         CV_Error( CV_StsError, "Some of essential matrix attributes are absent" );
 
     elem_type = icvDecodeSimpleFormat( dt );
@@ -3391,13 +3394,19 @@ icvReadMat( CvFileStorage* fs, CvFileNode* node )
     data = cvGetFileNodeByName( fs, node, "data" );
     if( !data )
         CV_Error( CV_StsError, "The matrix data is not found in file storage" );
-
-    if( icvFileNodeSeqLen( data ) != rows*cols*CV_MAT_CN(elem_type) )
+    
+    int nelems = icvFileNodeSeqLen( data );
+    if( nelems > 0 && nelems != rows*cols*CV_MAT_CN(elem_type) )
         CV_Error( CV_StsUnmatchedSizes,
-        "The matrix size does not match to the number of stored elements" );
-
-    mat = cvCreateMat( rows, cols, elem_type );
-    cvReadRawData( fs, data, mat->data.ptr, dt );
+                 "The matrix size does not match to the number of stored elements" );
+    
+    if( nelems > 0 )
+    {
+        mat = cvCreateMat( rows, cols, elem_type );
+        cvReadRawData( fs, data, mat->data.ptr, dt );
+    }
+    else
+        mat = cvCreateMatHeader( rows, cols, elem_type );
 
     ptr = mat;
     return ptr;
@@ -3409,7 +3418,7 @@ icvReadMat( CvFileStorage* fs, CvFileNode* node )
 static int
 icvIsMatND( const void* ptr )
 {
-    return CV_IS_MATND(ptr);
+    return CV_IS_MATND_HDR(ptr);
 }
 
 
@@ -3417,13 +3426,13 @@ static void
 icvWriteMatND( CvFileStorage* fs, const char* name,
                const void* struct_ptr, CvAttrList /*attr*/ )
 {
-    void* mat = (void*)struct_ptr;
+    CvMatND* mat = (CvMatND*)struct_ptr;
     CvMatND stub;
     CvNArrayIterator iterator;
     int dims, sizes[CV_MAX_DIM];
     char dt[16];
 
-    assert( CV_IS_MATND(mat) );
+    assert( CV_IS_MATND_HDR(mat) );
 
     cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_MATND );
     dims = cvGetDims( mat, sizes );
@@ -3433,11 +3442,14 @@ icvWriteMatND( CvFileStorage* fs, const char* name,
     cvWriteString( fs, "dt", icvEncodeFormat( cvGetElemType(mat), dt ), 0 );
     cvStartWriteStruct( fs, "data", CV_NODE_SEQ + CV_NODE_FLOW );
 
-    cvInitNArrayIterator( 1, &mat, 0, &stub, &iterator );
+    if( mat->dim[0].size > 0 && mat->data.ptr )
+    {
+        cvInitNArrayIterator( 1, (CvArr**)&mat, 0, &stub, &iterator );
 
-    do
-        cvWriteRawData( fs, iterator.ptr[0], iterator.size.width, dt );
-    while( cvNextNArraySlice( &iterator ));
+        do
+            cvWriteRawData( fs, iterator.ptr[0], iterator.size.width, dt );
+        while( cvNextNArraySlice( &iterator ));
+    }
     cvEndWriteStruct( fs );
     cvEndWriteStruct( fs );
 }
@@ -3472,16 +3484,25 @@ icvReadMatND( CvFileStorage* fs, CvFileNode* node )
     data = cvGetFileNodeByName( fs, node, "data" );
     if( !data )
         CV_Error( CV_StsError, "The matrix data is not found in file storage" );
-
+    
+    
+    
     for( total_size = CV_MAT_CN(elem_type), i = 0; i < dims; i++ )
         total_size *= sizes[i];
-
-    if( icvFileNodeSeqLen( data ) != total_size )
+    
+    int nelems = icvFileNodeSeqLen( data );
+    
+    if( nelems > 0 && nelems != total_size )
         CV_Error( CV_StsUnmatchedSizes,
-        "The matrix size does not match to the number of stored elements" );
-
-    mat = cvCreateMatND( dims, sizes, elem_type );
-    cvReadRawData( fs, data, mat->data.ptr, dt );
+                 "The matrix size does not match to the number of stored elements" );
+    
+    if( nelems > 0 )
+    {
+        mat = cvCreateMatND( dims, sizes, elem_type );
+        cvReadRawData( fs, data, mat->data.ptr, dt );
+    }
+    else
+        mat = cvCreateMatNDHeader( dims, sizes, elem_type );
 
     ptr = mat;
     return ptr;
@@ -5304,12 +5325,12 @@ void read( const FileNode& node, Mat& mat, const Mat& default_mat )
         return;
     }
     void* obj = cvRead((CvFileStorage*)node.fs, (CvFileNode*)*node);
-    if(CV_IS_MAT(obj))
+    if(CV_IS_MAT_HDR_Z(obj))
     {
         Mat((const CvMat*)obj).copyTo(mat);
         cvReleaseMat((CvMat**)&obj);
     }
-    else if(CV_IS_MATND(obj))
+    else if(CV_IS_MATND_HDR(obj))
     {
         Mat((const CvMatND*)obj).copyTo(mat);
         cvReleaseMatND((CvMatND**)&obj);