]> rtime.felk.cvut.cz Git - opencv.git/blobdiff - opencv/src/cxcore/cxarray.cpp
fixed other 2 bugs in documentation and cvReleaseMat()
[opencv.git] / opencv / src / cxcore / cxarray.cpp
index c956d38d74fc8368f93e9b57a9f7f8791dc8e827..7d0ef6762da12478c150ce3b4f63bce0abb83ecf 100644 (file)
@@ -67,12 +67,12 @@ cvSetIPLAllocators( Cv_iplCreateImageHeader createHeader,
                     Cv_iplCreateROI createROI,
                     Cv_iplCloneImage cloneImage )
 {
-    if( !createHeader || !allocateData || !deallocate || !createROI || !cloneImage )
-    {
-        if( createHeader || allocateData || deallocate || createROI || cloneImage )
-            CV_Error( CV_StsBadArg, "Either all the pointers should be null or "
-                                    "they all should be non-null" );
-    }
+    int count = (createHeader != 0) + (allocateData != 0) + (deallocate != 0) +
+        (createROI != 0) + (cloneImage != 0);
+    
+    if( count != 0 && count != 5 )
+        CV_Error( CV_StsBadArg, "Either all the pointers should be null or "
+                                 "they all should be non-null" );
 
     CvIPL.createHeader = createHeader;
     CvIPL.allocateData = allocateData;
@@ -118,9 +118,8 @@ cvCreateMatHeader( int rows, int cols, int type )
 
     CvMat* arr = (CvMat*)cvAlloc( sizeof(*arr));
 
-    arr->step = rows == 1 ? 0 : cvAlign(min_step, CV_DEFAULT_MAT_ROW_ALIGN);
-    arr->type = CV_MAT_MAGIC_VAL | type |
-                (arr->step == 0 || arr->step == min_step ? CV_MAT_CONT_FLAG : 0);
+    arr->step = min_step;
+    arr->type = CV_MAT_MAGIC_VAL | type | CV_MAT_CONT_FLAG;
     arr->rows = rows;
     arr->cols = cols;
     arr->data.ptr = 0;
@@ -154,15 +153,14 @@ cvInitMatHeader( CvMat* arr, int rows, int cols,
     arr->refcount = 0;
     arr->hdr_refcount = 0;
 
-    int mask = (arr->rows <= 1) - 1;
     int pix_size = CV_ELEM_SIZE(type);
-    int min_step = arr->cols*pix_size & mask;
+    int min_step = arr->cols*pix_size;
 
     if( step != CV_AUTOSTEP && step != 0 )
     {
         if( step < min_step )
             CV_Error( CV_BadStep, "" );
-        arr->step = step & mask;
+        arr->step = step;
     }
     else
     {
@@ -170,13 +168,19 @@ cvInitMatHeader( CvMat* arr, int rows, int cols,
     }
 
     arr->type = CV_MAT_MAGIC_VAL | type |
-                (arr->step == min_step ? CV_MAT_CONT_FLAG : 0);
+        (arr->rows == 1 || arr->step == min_step ? CV_MAT_CONT_FLAG : 0);
 
     icvCheckHuge( arr );
     return arr;
 }
 
 
+#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 )
@@ -188,7 +192,7 @@ cvReleaseMat( CvMat** array )
     {
         CvMat* arr = *array;
         
-        if( !CV_IS_MAT_HDR(arr) && !CV_IS_MATND_HDR(arr) )
+        if( !CV_IS_MAT_HDR_Z(arr) && !CV_IS_MATND_HDR(arr) )
             CV_Error( CV_StsBadFlag, "" );
 
         *array = 0;
@@ -803,7 +807,10 @@ cvCreateData( CvArr* arr )
         if( step == 0 )
             step = CV_ELEM_SIZE(mat->type)*mat->cols;
 
-        total_size = step*mat->rows + sizeof(int) + CV_MALLOC_ALIGN;
+        int64 _total_size = (int64)step*mat->rows + sizeof(int) + CV_MALLOC_ALIGN;
+        total_size = (size_t)_total_size;
+        if(_total_size != (int64)total_size)
+            CV_Error(CV_StsNoMem, "Too big buffer is allocated" );
         mat->refcount = (int*)cvAlloc( (size_t)total_size );
         mat->data.ptr = (uchar*)cvAlignPtr( mat->refcount + 1, CV_MALLOC_ALIGN );
         *mat->refcount = 1;
@@ -825,7 +832,7 @@ cvCreateData( CvArr* arr )
             int depth = img->depth;
             int width = img->width;
 
-            if( img->depth == IPL_DEPTH_32F || img->nChannels == 64 )
+            if( img->depth == IPL_DEPTH_32F || img->depth == IPL_DEPTH_64F )
             {
                 img->width *= img->depth == IPL_DEPTH_32F ? sizeof(float) : sizeof(double);
                 img->depth = IPL_DEPTH_8U;
@@ -887,22 +894,20 @@ cvSetData( CvArr* arr, void* data, int step )
     
         int type = CV_MAT_TYPE(mat->type);
         pix_size = CV_ELEM_SIZE(type);
-        min_step = mat->cols*pix_size & ((mat->rows <= 1) - 1);
+        min_step = mat->cols*pix_size;
 
-        if( step != CV_AUTOSTEP )
+        if( step != CV_AUTOSTEP && step != 0 )
         {
             if( step < min_step && data != 0 )
                 CV_Error( CV_BadStep, "" );
-            mat->step = step & ((mat->rows <= 1) - 1);
+            mat->step = step;
         }
         else
-        {
             mat->step = min_step;
-        }
 
         mat->data.ptr = (uchar*)data;
         mat->type = CV_MAT_MAGIC_VAL | type |
-                    (mat->step==min_step ? CV_MAT_CONT_FLAG : 0);
+                    (mat->rows == 1 || mat->step == min_step ? CV_MAT_CONT_FLAG : 0);
         icvCheckHuge( mat );
     }
     else if( CV_IS_IMAGE_HDR( arr ))
@@ -928,13 +933,9 @@ cvSetData( CvArr* arr, void* data, int step )
 
         if( (((int)(size_t)data | step) & 7) == 0 &&
             cvAlign(img->width * pix_size, 8) == step )
-        {
             img->align = 8;
-        }
         else
-        {
             img->align = 4;
-        }
     }
     else if( CV_IS_MATND_HDR( arr ))
     {
@@ -1057,7 +1058,7 @@ cvGetRawData( const CvArr* arr, uchar** data, int* step, CvSize* roi_size )
             }
 
             if( step )
-                *step = size1 == 1 ? 0 : mat->dim[0].step;
+                *step = mat->dim[0].step;
         }
     }
     else
@@ -1074,7 +1075,7 @@ cvGetElemType( const CvArr* arr )
     else if( CV_IS_IMAGE(arr))
     {
         IplImage* img = (IplImage*)arr;
-        type = CV_MAKETYPE( IplToCvDepth(img->depth), img->nChannels );
+        type = CV_MAKETYPE( IPL2CV_DEPTH(img->depth), img->nChannels );
     }
     else
         CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
@@ -1266,9 +1267,9 @@ cvGetSubRect( const CvArr* arr, CvMat* submat, CvRect rect )
     */
     submat->data.ptr = mat->data.ptr + (size_t)rect.y*mat->step +
                        rect.x*CV_ELEM_SIZE(mat->type);
-    submat->step = mat->step & (rect.height > 1 ? -1 : 0);
+    submat->step = mat->step;
     submat->type = (mat->type & (rect.width < mat->cols ? ~CV_MAT_CONT_FLAG : -1)) |
-                   (submat->step == 0 ? CV_MAT_CONT_FLAG : 0);
+                   (rect.height <= 1 ? CV_MAT_CONT_FLAG : 0);
     submat->rows = rect.height;
     submat->cols = rect.width;
     submat->refcount = 0;
@@ -1309,7 +1310,7 @@ cvGetRows( const CvArr* arr, CvMat* submat,
     if( delta_row == 1 )
     {
         submat->rows = end_row - start_row;
-        submat->step = mat->step & (submat->rows > 1 ? -1 : 0);
+        submat->step = mat->step;
     }
     else
     {
@@ -1320,8 +1321,8 @@ cvGetRows( const CvArr* arr, CvMat* submat,
     submat->cols = mat->cols;
     submat->step &= submat->rows > 1 ? -1 : 0;
     submat->data.ptr = mat->data.ptr + (size_t)start_row*mat->step;
-    submat->type = (mat->type | (submat->step == 0 ? CV_MAT_CONT_FLAG : 0)) &
-                   (delta_row != 1 ? ~CV_MAT_CONT_FLAG : -1);
+    submat->type = (mat->type | (submat->rows == 1 ? CV_MAT_CONT_FLAG : 0)) &
+                   (delta_row != 1 && submat->rows > 1 ? ~CV_MAT_CONT_FLAG : -1);
     submat->refcount = 0;
     submat->hdr_refcount = 0;
     res = submat;
@@ -1361,9 +1362,9 @@ cvGetCols( const CvArr* arr, CvMat* submat, int start_col, int end_col )
     */
     submat->rows = mat->rows;
     submat->cols = end_col - start_col;
-    submat->step = mat->step & (submat->rows > 1 ? -1 : 0);
+    submat->step = mat->step;
     submat->data.ptr = mat->data.ptr + (size_t)start_col*CV_ELEM_SIZE(mat->type);
-    submat->type = mat->type & (submat->step && submat->cols < cols ? ~CV_MAT_CONT_FLAG : -1);
+    submat->type = mat->type & (submat->rows > 1 && submat->cols < cols ? ~CV_MAT_CONT_FLAG : -1);
     submat->refcount = 0;
     submat->hdr_refcount = 0;
     res = submat;
@@ -1421,9 +1422,9 @@ cvGetDiag( const CvArr* arr, CvMat* submat, int diag )
 
     submat->rows = len;
     submat->cols = 1;
-    submat->step = (mat->step + pix_size) & (submat->rows > 1 ? -1 : 0);
+    submat->step = mat->step + (submat->rows > 1 ? pix_size : 0);
     submat->type = mat->type;
-    if( submat->step )
+    if( submat->rows > 1 )
         submat->type &= ~CV_MAT_CONT_FLAG;
     else
         submat->type |= CV_MAT_CONT_FLAG;
@@ -1793,7 +1794,7 @@ cvPtr2D( const CvArr* arr, int y, int x, int* _type )
 
         if( _type )
         {
-            int type = IplToCvDepth(img->depth);
+            int type = IPL2CV_DEPTH(img->depth);
             if( type < 0 || (unsigned)(img->nChannels - 1) > 3 )
                 CV_Error( CV_StsUnsupportedFormat, "" );
 
@@ -2389,7 +2390,7 @@ cvGetMat( const CvArr* array, CvMat* mat,
         if( img->imageData == 0 )
             CV_Error( CV_StsNullPtr, "The image has NULL data pointer" );
 
-        depth = IplToCvDepth( img->depth );
+        depth = IPL2CV_DEPTH( img->depth );
         if( depth < 0 )
             CV_Error( CV_BadDepth, "" );
 
@@ -2406,11 +2407,11 @@ cvGetMat( const CvArr* array, CvMat* mat,
                     "Images with planar data layout should be used with COI selected" );
 
                 cvInitMatHeader( mat, img->roi->height,
-                                   img->roi->width, type,
-                                   img->imageData + (img->roi->coi-1)*img->imageSize +
-                                   img->roi->yOffset*img->widthStep +
-                                   img->roi->xOffset*CV_ELEM_SIZE(type),
-                                   img->widthStep );
+                                img->roi->width, type,
+                                img->imageData + (img->roi->coi-1)*img->imageSize +
+                                img->roi->yOffset*img->widthStep +
+                                img->roi->xOffset*CV_ELEM_SIZE(type),
+                                img->widthStep );
             }
             else /* pixel order */
             {
@@ -2422,10 +2423,10 @@ cvGetMat( const CvArr* array, CvMat* mat,
                         "The image is interleaved and has over CV_CN_MAX channels" );
 
                 cvInitMatHeader( mat, img->roi->height, img->roi->width,
-                                          type, img->imageData +
-                                          img->roi->yOffset*img->widthStep +
-                                          img->roi->xOffset*CV_ELEM_SIZE(type),
-                                          img->widthStep );
+                                 type, img->imageData +
+                                 img->roi->yOffset*img->widthStep +
+                                 img->roi->xOffset*CV_ELEM_SIZE(type),
+                                 img->widthStep );
             }
         }
         else
@@ -2436,7 +2437,7 @@ cvGetMat( const CvArr* array, CvMat* mat,
                 CV_Error( CV_StsBadFlag, "Pixel order should be used with coi == 0" );
 
             cvInitMatHeader( mat, img->height, img->width, type,
-                                      img->imageData, img->widthStep );
+                             img->imageData, img->widthStep );
         }
 
         result = mat;
@@ -2517,21 +2518,22 @@ cvReshapeMatND( const CvArr* arr,
     if( new_dims <= 2 )
     {
         CvMat* mat = (CvMat*)arr;
-        CvMat* header = (CvMat*)_header;
+        CvMat header;
         int* refcount = 0;
         int  hdr_refcount = 0;
         int  total_width, new_rows, cn;
 
-        if( sizeof_header != sizeof(CvMat))
-            CV_Error( CV_StsBadArg, "The header should be CvMat" );
+        if( sizeof_header != sizeof(CvMat) && sizeof_header != sizeof(CvMatND) )
+            CV_Error( CV_StsBadArg, "The output header should be CvMat or CvMatND" );
 
-        if( mat == header )
+        if( mat == (CvMat*)_header )
         {
             refcount = mat->refcount;
             hdr_refcount = mat->hdr_refcount;
         }
-        else if( !CV_IS_MAT( mat ))
-            mat = cvGetMat( mat, header, &coi, 1 );
+        
+        if( !CV_IS_MAT( mat ))
+            mat = cvGetMat( mat, &header, &coi, 1 );
 
         cn = CV_MAT_CN( mat->type );
         total_width = mat->cols * cn;
@@ -2565,31 +2567,41 @@ cvReshapeMatND( const CvArr* arr,
                                         "is not divisible by the new number of rows" );
         }
 
-        header->rows = new_rows;
-        header->cols = total_width / new_cn;
+        header.rows = new_rows;
+        header.cols = total_width / new_cn;
 
-        if( header->cols * new_cn != total_width ||
-            (new_sizes && header->cols != new_sizes[1]) )
+        if( header.cols * new_cn != total_width ||
+            (new_sizes && header.cols != new_sizes[1]) )
             CV_Error( CV_StsBadArg, "The total matrix width is not "
                             "divisible by the new number of columns" );
 
-        header->type = (mat->type & ~CV_MAT_TYPE_MASK) | CV_MAKETYPE(mat->type, new_cn);
-        header->step = header->cols * CV_ELEM_SIZE(mat->type);
-        header->step &= new_rows > 1 ? -1 : 0;
-        header->refcount = refcount;
-        header->hdr_refcount = hdr_refcount;
+        header.type = (mat->type & ~CV_MAT_TYPE_MASK) | CV_MAKETYPE(mat->type, new_cn);
+        header.step = header.cols * CV_ELEM_SIZE(mat->type);
+        header.step &= new_rows > 1 ? -1 : 0;
+        header.refcount = refcount;
+        header.hdr_refcount = hdr_refcount;
+        
+        if( sizeof_header == sizeof(CvMat) )
+            *(CvMat*)_header = header;
+        else
+        {
+            CvMatND* __header = (CvMatND*)_header;
+            cvGetMatND(&header, __header, 0);
+            if( new_dims > 0 )
+                __header->dims = new_dims;
+        }
     }
     else
     {
         CvMatND* header = (CvMatND*)_header;
 
         if( sizeof_header != sizeof(CvMatND))
-            CV_Error( CV_StsBadSize, "The header should be CvMatND" );
+            CV_Error( CV_StsBadSize, "The output header should be CvMatND" );
         
         if( !new_sizes )
         {
             if( !CV_IS_MATND( arr ))
-                CV_Error( CV_StsBadArg, "The source array must be CvMatND" );
+                CV_Error( CV_StsBadArg, "The input array must be CvMatND" );
 
             {
             CvMatND* mat = (CvMatND*)arr;
@@ -2670,7 +2682,7 @@ cvReshapeMatND( const CvArr* arr,
         }
     }
 
-    if( !coi )
+    if( coi )
         CV_Error( CV_BadCOI, "COI is not supported by this operation" );
 
     result = _header;
@@ -2981,29 +2993,22 @@ cvSetImageROI( IplImage* image, CvRect rect )
     if( !image )
         CV_Error( CV_HeaderIsNull, "" );
 
-    if( rect.x > image->width || rect.y > image->height )
-        CV_Error( CV_BadROISize, "" );
-
-    if( rect.x + rect.width < 0 || rect.y + rect.height < 0 )
-        CV_Error( CV_BadROISize, "" );
-
-    if( rect.x < 0 )
-    {
-        rect.width += rect.x;
-        rect.x = 0;
-    }
-
-    if( rect.y < 0 )
-    {
-        rect.height += rect.y;
-        rect.y = 0;
-    }
-
-    if( rect.x + rect.width > image->width )
-        rect.width = image->width - rect.x;
-
-    if( rect.y + rect.height > image->height )
-        rect.height = image->height - rect.y;
+    // allow zero ROI width or height
+    CV_Assert( rect.width >= 0 && rect.height >= 0 &&
+               rect.x < image->width && rect.y < image->height &&
+               rect.x + rect.width >= (int)(rect.width > 0) &&
+               rect.y + rect.height >= (int)(rect.height > 0) );
+    
+    rect.width += rect.x;
+    rect.height += rect.y;
+    
+    rect.x = std::max(rect.x, 0);
+    rect.y = std::max(rect.y, 0);
+    rect.width = std::min(rect.width, image->width);
+    rect.height = std::min(rect.height, image->height);
+    
+    rect.width -= rect.x;
+    rect.height -= rect.y;
 
     if( image->roi )
     {