Home | History | Annotate | Download | only in src
      1 /*M///////////////////////////////////////////////////////////////////////////////////////
      2 //
      3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
      4 //
      5 //  By downloading, copying, installing or using the software you agree to this license.
      6 //  If you do not agree to this license, do not download, install,
      7 //  copy or use the software.
      8 //
      9 //
     10 //                        Intel License Agreement
     11 //                For Open Source Computer Vision Library
     12 //
     13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
     14 // Third party copyrights are property of their respective owners.
     15 //
     16 // Redistribution and use in source and binary forms, with or without modification,
     17 // are permitted provided that the following conditions are met:
     18 //
     19 //   * Redistribution's of source code must retain the above copyright notice,
     20 //     this list of conditions and the following disclaimer.
     21 //
     22 //   * Redistribution's in binary form must reproduce the above copyright notice,
     23 //     this list of conditions and the following disclaimer in the documentation
     24 //     and/or other materials provided with the distribution.
     25 //
     26 //   * The name of Intel Corporation may not be used to endorse or promote products
     27 //     derived from this software without specific prior written permission.
     28 //
     29 // This software is provided by the copyright holders and contributors "as is" and
     30 // any express or implied warranties, including, but not limited to, the implied
     31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
     32 // In no event shall the Intel Corporation or contributors be liable for any direct,
     33 // indirect, incidental, special, exemplary, or consequential damages
     34 // (including, but not limited to, procurement of substitute goods or services;
     35 // loss of use, data, or profits; or business interruption) however caused
     36 // and on any theory of liability, whether in contract, strict liability,
     37 // or tort (including negligence or otherwise) arising in any way out of
     38 // the use of this software, even if advised of the possibility of such damage.
     39 //
     40 //M*/
     41 
     42 /* ////////////////////////////////////////////////////////////////////
     43 //
     44 //  CvMat, CvMatND, CvSparceMat and IplImage support functions
     45 //  (creation, deletion, copying, retrieving and setting elements etc.)
     46 //
     47 // */
     48 
     49 #include "precomp.hpp"
     50 
     51 #define  CV_ORIGIN_TL  0
     52 #define  CV_ORIGIN_BL  1
     53 
     54 /* default image row align (in bytes) */
     55 #define  CV_DEFAULT_IMAGE_ROW_ALIGN  4
     56 
     57 
     58 static struct
     59 {
     60     Cv_iplCreateImageHeader  createHeader;
     61     Cv_iplAllocateImageData  allocateData;
     62     Cv_iplDeallocate  deallocate;
     63     Cv_iplCreateROI  createROI;
     64     Cv_iplCloneImage  cloneImage;
     65 }
     66 CvIPL;
     67 
     68 // Makes the library use native IPL image allocators
     69 CV_IMPL void
     70 cvSetIPLAllocators( Cv_iplCreateImageHeader createHeader,
     71                     Cv_iplAllocateImageData allocateData,
     72                     Cv_iplDeallocate deallocate,
     73                     Cv_iplCreateROI createROI,
     74                     Cv_iplCloneImage cloneImage )
     75 {
     76     int count = (createHeader != 0) + (allocateData != 0) + (deallocate != 0) +
     77         (createROI != 0) + (cloneImage != 0);
     78 
     79     if( count != 0 && count != 5 )
     80         CV_Error( CV_StsBadArg, "Either all the pointers should be null or "
     81                                  "they all should be non-null" );
     82 
     83     CvIPL.createHeader = createHeader;
     84     CvIPL.allocateData = allocateData;
     85     CvIPL.deallocate = deallocate;
     86     CvIPL.createROI = createROI;
     87     CvIPL.cloneImage = cloneImage;
     88 }
     89 
     90 
     91 /****************************************************************************************\
     92 *                               CvMat creation and basic operations                      *
     93 \****************************************************************************************/
     94 
     95 // Creates CvMat and underlying data
     96 CV_IMPL CvMat*
     97 cvCreateMat( int height, int width, int type )
     98 {
     99     CvMat* arr = cvCreateMatHeader( height, width, type );
    100     cvCreateData( arr );
    101 
    102     return arr;
    103 }
    104 
    105 
    106 static void icvCheckHuge( CvMat* arr )
    107 {
    108     if( (int64)arr->step*arr->rows > INT_MAX )
    109         arr->type &= ~CV_MAT_CONT_FLAG;
    110 }
    111 
    112 // Creates CvMat header only
    113 CV_IMPL CvMat*
    114 cvCreateMatHeader( int rows, int cols, int type )
    115 {
    116     type = CV_MAT_TYPE(type);
    117 
    118     if( rows < 0 || cols <= 0 )
    119         CV_Error( CV_StsBadSize, "Non-positive width or height" );
    120 
    121     int min_step = CV_ELEM_SIZE(type)*cols;
    122     if( min_step <= 0 )
    123         CV_Error( CV_StsUnsupportedFormat, "Invalid matrix type" );
    124 
    125     CvMat* arr = (CvMat*)cvAlloc( sizeof(*arr));
    126 
    127     arr->step = min_step;
    128     arr->type = CV_MAT_MAGIC_VAL | type | CV_MAT_CONT_FLAG;
    129     arr->rows = rows;
    130     arr->cols = cols;
    131     arr->data.ptr = 0;
    132     arr->refcount = 0;
    133     arr->hdr_refcount = 1;
    134 
    135     icvCheckHuge( arr );
    136     return arr;
    137 }
    138 
    139 
    140 // Initializes CvMat header, allocated by the user
    141 CV_IMPL CvMat*
    142 cvInitMatHeader( CvMat* arr, int rows, int cols,
    143                  int type, void* data, int step )
    144 {
    145     if( !arr )
    146         CV_Error( CV_StsNullPtr, "" );
    147 
    148     if( (unsigned)CV_MAT_DEPTH(type) > CV_DEPTH_MAX )
    149         CV_Error( CV_BadNumChannels, "" );
    150 
    151     if( rows < 0 || cols <= 0 )
    152         CV_Error( CV_StsBadSize, "Non-positive cols or rows" );
    153 
    154     type = CV_MAT_TYPE( type );
    155     arr->type = type | CV_MAT_MAGIC_VAL;
    156     arr->rows = rows;
    157     arr->cols = cols;
    158     arr->data.ptr = (uchar*)data;
    159     arr->refcount = 0;
    160     arr->hdr_refcount = 0;
    161 
    162     int pix_size = CV_ELEM_SIZE(type);
    163     int min_step = arr->cols*pix_size;
    164 
    165     if( step != CV_AUTOSTEP && step != 0 )
    166     {
    167         if( step < min_step )
    168             CV_Error( CV_BadStep, "" );
    169         arr->step = step;
    170     }
    171     else
    172     {
    173         arr->step = min_step;
    174     }
    175 
    176     arr->type = CV_MAT_MAGIC_VAL | type |
    177         (arr->rows == 1 || arr->step == min_step ? CV_MAT_CONT_FLAG : 0);
    178 
    179     icvCheckHuge( arr );
    180     return arr;
    181 }
    182 
    183 
    184 // Deallocates the CvMat structure and underlying data
    185 CV_IMPL void
    186 cvReleaseMat( CvMat** array )
    187 {
    188     if( !array )
    189         CV_Error( CV_HeaderIsNull, "" );
    190 
    191     if( *array )
    192     {
    193         CvMat* arr = *array;
    194 
    195         if( !CV_IS_MAT_HDR_Z(arr) && !CV_IS_MATND_HDR(arr) )
    196             CV_Error( CV_StsBadFlag, "" );
    197 
    198         *array = 0;
    199 
    200         cvDecRefData( arr );
    201         cvFree( &arr );
    202     }
    203 }
    204 
    205 
    206 // Creates a copy of matrix
    207 CV_IMPL CvMat*
    208 cvCloneMat( const CvMat* src )
    209 {
    210     if( !CV_IS_MAT_HDR( src ))
    211         CV_Error( CV_StsBadArg, "Bad CvMat header" );
    212 
    213     CvMat* dst = cvCreateMatHeader( src->rows, src->cols, src->type );
    214 
    215     if( src->data.ptr )
    216     {
    217         cvCreateData( dst );
    218         cvCopy( src, dst );
    219     }
    220 
    221     return dst;
    222 }
    223 
    224 
    225 /****************************************************************************************\
    226 *                               CvMatND creation and basic operations                    *
    227 \****************************************************************************************/
    228 
    229 CV_IMPL CvMatND*
    230 cvInitMatNDHeader( CvMatND* mat, int dims, const int* sizes,
    231                    int type, void* data )
    232 {
    233     type = CV_MAT_TYPE(type);
    234     int64 step = CV_ELEM_SIZE(type);
    235 
    236     if( !mat )
    237         CV_Error( CV_StsNullPtr, "NULL matrix header pointer" );
    238 
    239     if( step == 0 )
    240         CV_Error( CV_StsUnsupportedFormat, "invalid array data type" );
    241 
    242     if( !sizes )
    243         CV_Error( CV_StsNullPtr, "NULL <sizes> pointer" );
    244 
    245     if( dims <= 0 || dims > CV_MAX_DIM )
    246         CV_Error( CV_StsOutOfRange,
    247         "non-positive or too large number of dimensions" );
    248 
    249     for( int i = dims - 1; i >= 0; i-- )
    250     {
    251         if( sizes[i] < 0 )
    252             CV_Error( CV_StsBadSize, "one of dimesion sizes is non-positive" );
    253         mat->dim[i].size = sizes[i];
    254         if( step > INT_MAX )
    255             CV_Error( CV_StsOutOfRange, "The array is too big" );
    256         mat->dim[i].step = (int)step;
    257         step *= sizes[i];
    258     }
    259 
    260     mat->type = CV_MATND_MAGIC_VAL | (step <= INT_MAX ? CV_MAT_CONT_FLAG : 0) | type;
    261     mat->dims = dims;
    262     mat->data.ptr = (uchar*)data;
    263     mat->refcount = 0;
    264     mat->hdr_refcount = 0;
    265     return mat;
    266 }
    267 
    268 
    269 // Creates CvMatND and underlying data
    270 CV_IMPL CvMatND*
    271 cvCreateMatND( int dims, const int* sizes, int type )
    272 {
    273     CvMatND* arr = cvCreateMatNDHeader( dims, sizes, type );
    274     cvCreateData( arr );
    275 
    276     return arr;
    277 }
    278 
    279 
    280 // Creates CvMatND header only
    281 CV_IMPL CvMatND*
    282 cvCreateMatNDHeader( int dims, const int* sizes, int type )
    283 {
    284     if( dims <= 0 || dims > CV_MAX_DIM )
    285         CV_Error( CV_StsOutOfRange,
    286         "non-positive or too large number of dimensions" );
    287 
    288     CvMatND* arr = (CvMatND*)cvAlloc( sizeof(*arr) );
    289 
    290     cvInitMatNDHeader( arr, dims, sizes, type, 0 );
    291     arr->hdr_refcount = 1;
    292     return arr;
    293 }
    294 
    295 
    296 // Creates a copy of nD array
    297 CV_IMPL CvMatND*
    298 cvCloneMatND( const CvMatND* src )
    299 {
    300     if( !CV_IS_MATND_HDR( src ))
    301         CV_Error( CV_StsBadArg, "Bad CvMatND header" );
    302 
    303     CV_Assert( src->dims <= CV_MAX_DIM );
    304     int sizes[CV_MAX_DIM];
    305 
    306     for( int i = 0; i < src->dims; i++ )
    307         sizes[i] = src->dim[i].size;
    308 
    309     CvMatND* dst = cvCreateMatNDHeader( src->dims, sizes, src->type );
    310 
    311     if( src->data.ptr )
    312     {
    313         cvCreateData( dst );
    314         cv::Mat _src = cv::cvarrToMat(src);
    315         cv::Mat _dst = cv::cvarrToMat(dst);
    316         uchar* data0 = dst->data.ptr;
    317         _src.copyTo(_dst);
    318         CV_Assert(_dst.data == data0);
    319         //cvCopy( src, dst );
    320     }
    321 
    322     return dst;
    323 }
    324 
    325 
    326 static CvMatND*
    327 cvGetMatND( const CvArr* arr, CvMatND* matnd, int* coi )
    328 {
    329     CvMatND* result = 0;
    330 
    331     if( coi )
    332         *coi = 0;
    333 
    334     if( !matnd || !arr )
    335         CV_Error( CV_StsNullPtr, "NULL array pointer is passed" );
    336 
    337     if( CV_IS_MATND_HDR(arr))
    338     {
    339         if( !((CvMatND*)arr)->data.ptr )
    340             CV_Error( CV_StsNullPtr, "The matrix has NULL data pointer" );
    341 
    342         result = (CvMatND*)arr;
    343     }
    344     else
    345     {
    346         CvMat stub, *mat = (CvMat*)arr;
    347 
    348         if( CV_IS_IMAGE_HDR( mat ))
    349             mat = cvGetMat( mat, &stub, coi );
    350 
    351         if( !CV_IS_MAT_HDR( mat ))
    352             CV_Error( CV_StsBadArg, "Unrecognized or unsupported array type" );
    353 
    354         if( !mat->data.ptr )
    355             CV_Error( CV_StsNullPtr, "Input array has NULL data pointer" );
    356 
    357         matnd->data.ptr = mat->data.ptr;
    358         matnd->refcount = 0;
    359         matnd->hdr_refcount = 0;
    360         matnd->type = mat->type;
    361         matnd->dims = 2;
    362         matnd->dim[0].size = mat->rows;
    363         matnd->dim[0].step = mat->step;
    364         matnd->dim[1].size = mat->cols;
    365         matnd->dim[1].step = CV_ELEM_SIZE(mat->type);
    366         result = matnd;
    367     }
    368 
    369     return result;
    370 }
    371 
    372 
    373 // returns number of dimensions to iterate.
    374 /*
    375 Checks whether <count> arrays have equal type, sizes (mask is optional array
    376 that needs to have the same size, but 8uC1 or 8sC1 type).
    377 Returns number of dimensions to iterate through:
    378 0 means that all arrays are continuous,
    379 1 means that all arrays are vectors of continuous arrays etc.
    380 and the size of largest common continuous part of the arrays
    381 */
    382 CV_IMPL int
    383 cvInitNArrayIterator( int count, CvArr** arrs,
    384                       const CvArr* mask, CvMatND* stubs,
    385                       CvNArrayIterator* iterator, int flags )
    386 {
    387     int dims = -1;
    388     int i, j, size, dim0 = -1;
    389     int64 step;
    390     CvMatND* hdr0 = 0;
    391 
    392     if( count < 1 || count > CV_MAX_ARR )
    393         CV_Error( CV_StsOutOfRange, "Incorrect number of arrays" );
    394 
    395     if( !arrs || !stubs )
    396         CV_Error( CV_StsNullPtr, "Some of required array pointers is NULL" );
    397 
    398     if( !iterator )
    399         CV_Error( CV_StsNullPtr, "Iterator pointer is NULL" );
    400 
    401     for( i = 0; i <= count; i++ )
    402     {
    403         const CvArr* arr = i < count ? arrs[i] : mask;
    404         CvMatND* hdr;
    405 
    406         if( !arr )
    407         {
    408             if( i < count )
    409                 CV_Error( CV_StsNullPtr, "Some of required array pointers is NULL" );
    410             break;
    411         }
    412 
    413         if( CV_IS_MATND( arr ))
    414             hdr = (CvMatND*)arr;
    415         else
    416         {
    417             int coi = 0;
    418             hdr = cvGetMatND( arr, stubs + i, &coi );
    419             if( coi != 0 )
    420                 CV_Error( CV_BadCOI, "COI set is not allowed here" );
    421         }
    422 
    423         iterator->hdr[i] = hdr;
    424 
    425         if( i > 0 )
    426         {
    427             if( hdr->dims != hdr0->dims )
    428                 CV_Error( CV_StsUnmatchedSizes,
    429                           "Number of dimensions is the same for all arrays" );
    430 
    431             if( i < count )
    432             {
    433                 switch( flags & (CV_NO_DEPTH_CHECK|CV_NO_CN_CHECK))
    434                 {
    435                 case 0:
    436                     if( !CV_ARE_TYPES_EQ( hdr, hdr0 ))
    437                         CV_Error( CV_StsUnmatchedFormats,
    438                                   "Data type is not the same for all arrays" );
    439                     break;
    440                 case CV_NO_DEPTH_CHECK:
    441                     if( !CV_ARE_CNS_EQ( hdr, hdr0 ))
    442                         CV_Error( CV_StsUnmatchedFormats,
    443                                   "Number of channels is not the same for all arrays" );
    444                     break;
    445                 case CV_NO_CN_CHECK:
    446                     if( !CV_ARE_CNS_EQ( hdr, hdr0 ))
    447                         CV_Error( CV_StsUnmatchedFormats,
    448                                   "Depth is not the same for all arrays" );
    449                     break;
    450                 }
    451             }
    452             else
    453             {
    454                 if( !CV_IS_MASK_ARR( hdr ))
    455                     CV_Error( CV_StsBadMask, "Mask should have 8uC1 or 8sC1 data type" );
    456             }
    457 
    458             if( !(flags & CV_NO_SIZE_CHECK) )
    459             {
    460                 for( j = 0; j < hdr->dims; j++ )
    461                     if( hdr->dim[j].size != hdr0->dim[j].size )
    462                         CV_Error( CV_StsUnmatchedSizes,
    463                                   "Dimension sizes are the same for all arrays" );
    464             }
    465         }
    466         else
    467             hdr0 = hdr;
    468 
    469         step = CV_ELEM_SIZE(hdr->type);
    470         for( j = hdr->dims - 1; j > dim0; j-- )
    471         {
    472             if( step != hdr->dim[j].step )
    473                 break;
    474             step *= hdr->dim[j].size;
    475         }
    476 
    477         if( j == dim0 && step > INT_MAX )
    478             j++;
    479 
    480         if( j > dim0 )
    481             dim0 = j;
    482 
    483         iterator->hdr[i] = (CvMatND*)hdr;
    484         iterator->ptr[i] = (uchar*)hdr->data.ptr;
    485     }
    486 
    487     size = 1;
    488     for( j = hdr0->dims - 1; j > dim0; j-- )
    489         size *= hdr0->dim[j].size;
    490 
    491     dims = dim0 + 1;
    492     iterator->dims = dims;
    493     iterator->count = count;
    494     iterator->size = cvSize(size,1);
    495 
    496     for( i = 0; i < dims; i++ )
    497         iterator->stack[i] = hdr0->dim[i].size;
    498 
    499     return dims;
    500 }
    501 
    502 
    503 // returns zero value if iteration is finished, non-zero otherwise
    504 CV_IMPL int cvNextNArraySlice( CvNArrayIterator* iterator )
    505 {
    506     assert( iterator != 0 );
    507     int i, dims;
    508 
    509     for( dims = iterator->dims; dims > 0; dims-- )
    510     {
    511         for( i = 0; i < iterator->count; i++ )
    512             iterator->ptr[i] += iterator->hdr[i]->dim[dims-1].step;
    513 
    514         if( --iterator->stack[dims-1] > 0 )
    515             break;
    516 
    517         const int size = iterator->hdr[0]->dim[dims-1].size;
    518 
    519         for( i = 0; i < iterator->count; i++ )
    520             iterator->ptr[i] -= (size_t)size*iterator->hdr[i]->dim[dims-1].step;
    521 
    522         iterator->stack[dims-1] = size;
    523     }
    524 
    525     return dims > 0;
    526 }
    527 
    528 
    529 /****************************************************************************************\
    530 *                            CvSparseMat creation and basic operations                   *
    531 \****************************************************************************************/
    532 
    533 
    534 // Creates CvMatND and underlying data
    535 CV_IMPL CvSparseMat*
    536 cvCreateSparseMat( int dims, const int* sizes, int type )
    537 {
    538     type = CV_MAT_TYPE( type );
    539     int pix_size1 = CV_ELEM_SIZE1(type);
    540     int pix_size = pix_size1*CV_MAT_CN(type);
    541     int i, size;
    542     CvMemStorage* storage;
    543 
    544     if( pix_size == 0 )
    545         CV_Error( CV_StsUnsupportedFormat, "invalid array data type" );
    546 
    547     if( dims <= 0 || dims > CV_MAX_DIM_HEAP )
    548         CV_Error( CV_StsOutOfRange, "bad number of dimensions" );
    549 
    550     if( !sizes )
    551         CV_Error( CV_StsNullPtr, "NULL <sizes> pointer" );
    552 
    553     for( i = 0; i < dims; i++ )
    554     {
    555         if( sizes[i] <= 0 )
    556             CV_Error( CV_StsBadSize, "one of dimesion sizes is non-positive" );
    557     }
    558 
    559     CvSparseMat* arr = (CvSparseMat*)cvAlloc(sizeof(*arr)+MAX(0,dims-CV_MAX_DIM)*sizeof(arr->size[0]));
    560 
    561     arr->type = CV_SPARSE_MAT_MAGIC_VAL | type;
    562     arr->dims = dims;
    563     arr->refcount = 0;
    564     arr->hdr_refcount = 1;
    565     memcpy( arr->size, sizes, dims*sizeof(sizes[0]));
    566 
    567     arr->valoffset = (int)cvAlign(sizeof(CvSparseNode), pix_size1);
    568     arr->idxoffset = (int)cvAlign(arr->valoffset + pix_size, sizeof(int));
    569     size = (int)cvAlign(arr->idxoffset + dims*sizeof(int), sizeof(CvSetElem));
    570 
    571     storage = cvCreateMemStorage( CV_SPARSE_MAT_BLOCK );
    572     arr->heap = cvCreateSet( 0, sizeof(CvSet), size, storage );
    573 
    574     arr->hashsize = CV_SPARSE_HASH_SIZE0;
    575     size = arr->hashsize*sizeof(arr->hashtable[0]);
    576 
    577     arr->hashtable = (void**)cvAlloc( size );
    578     memset( arr->hashtable, 0, size );
    579 
    580     return arr;
    581 }
    582 
    583 
    584 // Creates CvMatND and underlying data
    585 CV_IMPL void
    586 cvReleaseSparseMat( CvSparseMat** array )
    587 {
    588     if( !array )
    589         CV_Error( CV_HeaderIsNull, "" );
    590 
    591     if( *array )
    592     {
    593         CvSparseMat* arr = *array;
    594 
    595         if( !CV_IS_SPARSE_MAT_HDR(arr) )
    596             CV_Error( CV_StsBadFlag, "" );
    597 
    598         *array = 0;
    599 
    600         CvMemStorage* storage = arr->heap->storage;
    601         cvReleaseMemStorage( &storage );
    602         cvFree( &arr->hashtable );
    603         cvFree( &arr );
    604     }
    605 }
    606 
    607 
    608 // Creates CvMatND and underlying data
    609 CV_IMPL CvSparseMat*
    610 cvCloneSparseMat( const CvSparseMat* src )
    611 {
    612     if( !CV_IS_SPARSE_MAT_HDR(src) )
    613         CV_Error( CV_StsBadArg, "Invalid sparse array header" );
    614 
    615     CvSparseMat* dst = cvCreateSparseMat( src->dims, src->size, src->type );
    616     cvCopy( src, dst );
    617     return dst;
    618 }
    619 
    620 
    621 CvSparseNode*
    622 cvInitSparseMatIterator( const CvSparseMat* mat, CvSparseMatIterator* iterator )
    623 {
    624     CvSparseNode* node = 0;
    625     int idx;
    626 
    627     if( !CV_IS_SPARSE_MAT( mat ))
    628         CV_Error( CV_StsBadArg, "Invalid sparse matrix header" );
    629 
    630     if( !iterator )
    631         CV_Error( CV_StsNullPtr, "NULL iterator pointer" );
    632 
    633     iterator->mat = (CvSparseMat*)mat;
    634     iterator->node = 0;
    635 
    636     for( idx = 0; idx < mat->hashsize; idx++ )
    637         if( mat->hashtable[idx] )
    638         {
    639             node = iterator->node = (CvSparseNode*)mat->hashtable[idx];
    640             break;
    641         }
    642 
    643     iterator->curidx = idx;
    644     return node;
    645 }
    646 
    647 #define ICV_SPARSE_MAT_HASH_MULTIPLIER  cv::SparseMat::HASH_SCALE
    648 
    649 static uchar*
    650 icvGetNodePtr( CvSparseMat* mat, const int* idx, int* _type,
    651                int create_node, unsigned* precalc_hashval )
    652 {
    653     uchar* ptr = 0;
    654     int i, tabidx;
    655     unsigned hashval = 0;
    656     CvSparseNode *node;
    657     assert( CV_IS_SPARSE_MAT( mat ));
    658 
    659     if( !precalc_hashval )
    660     {
    661         for( i = 0; i < mat->dims; i++ )
    662         {
    663             int t = idx[i];
    664             if( (unsigned)t >= (unsigned)mat->size[i] )
    665                 CV_Error( CV_StsOutOfRange, "One of indices is out of range" );
    666             hashval = hashval*ICV_SPARSE_MAT_HASH_MULTIPLIER + t;
    667         }
    668     }
    669     else
    670     {
    671         hashval = *precalc_hashval;
    672     }
    673 
    674     tabidx = hashval & (mat->hashsize - 1);
    675     hashval &= INT_MAX;
    676 
    677     if( create_node >= -1 )
    678     {
    679         for( node = (CvSparseNode*)mat->hashtable[tabidx];
    680              node != 0; node = node->next )
    681         {
    682             if( node->hashval == hashval )
    683             {
    684                 int* nodeidx = CV_NODE_IDX(mat,node);
    685                 for( i = 0; i < mat->dims; i++ )
    686                     if( idx[i] != nodeidx[i] )
    687                         break;
    688                 if( i == mat->dims )
    689                 {
    690                     ptr = (uchar*)CV_NODE_VAL(mat,node);
    691                     break;
    692                 }
    693             }
    694         }
    695     }
    696 
    697     if( !ptr && create_node )
    698     {
    699         if( mat->heap->active_count >= mat->hashsize*CV_SPARSE_HASH_RATIO )
    700         {
    701             void** newtable;
    702             int newsize = MAX( mat->hashsize*2, CV_SPARSE_HASH_SIZE0);
    703             int newrawsize = newsize*sizeof(newtable[0]);
    704 
    705             CvSparseMatIterator iterator;
    706             assert( (newsize & (newsize - 1)) == 0 );
    707 
    708             // resize hash table
    709             newtable = (void**)cvAlloc( newrawsize );
    710             memset( newtable, 0, newrawsize );
    711 
    712             node = cvInitSparseMatIterator( mat, &iterator );
    713             while( node )
    714             {
    715                 CvSparseNode* next = cvGetNextSparseNode( &iterator );
    716                 int newidx = node->hashval & (newsize - 1);
    717                 node->next = (CvSparseNode*)newtable[newidx];
    718                 newtable[newidx] = node;
    719                 node = next;
    720             }
    721 
    722             cvFree( &mat->hashtable );
    723             mat->hashtable = newtable;
    724             mat->hashsize = newsize;
    725             tabidx = hashval & (newsize - 1);
    726         }
    727 
    728         node = (CvSparseNode*)cvSetNew( mat->heap );
    729         node->hashval = hashval;
    730         node->next = (CvSparseNode*)mat->hashtable[tabidx];
    731         mat->hashtable[tabidx] = node;
    732         memcpy(CV_NODE_IDX(mat,node), idx, mat->dims*sizeof(idx[0]));
    733         ptr = (uchar*)CV_NODE_VAL(mat,node);
    734         if( create_node > 0 )
    735             memset( ptr, 0, CV_ELEM_SIZE(mat->type));
    736     }
    737 
    738     if( _type )
    739         *_type = CV_MAT_TYPE(mat->type);
    740 
    741     return ptr;
    742 }
    743 
    744 
    745 static void
    746 icvDeleteNode( CvSparseMat* mat, const int* idx, unsigned* precalc_hashval )
    747 {
    748     int i, tabidx;
    749     unsigned hashval = 0;
    750     CvSparseNode *node, *prev = 0;
    751     assert( CV_IS_SPARSE_MAT( mat ));
    752 
    753     if( !precalc_hashval )
    754     {
    755         for( i = 0; i < mat->dims; i++ )
    756         {
    757             int t = idx[i];
    758             if( (unsigned)t >= (unsigned)mat->size[i] )
    759                 CV_Error( CV_StsOutOfRange, "One of indices is out of range" );
    760             hashval = hashval*ICV_SPARSE_MAT_HASH_MULTIPLIER + t;
    761         }
    762     }
    763     else
    764     {
    765         hashval = *precalc_hashval;
    766     }
    767 
    768     tabidx = hashval & (mat->hashsize - 1);
    769     hashval &= INT_MAX;
    770 
    771     for( node = (CvSparseNode*)mat->hashtable[tabidx];
    772          node != 0; prev = node, node = node->next )
    773     {
    774         if( node->hashval == hashval )
    775         {
    776             int* nodeidx = CV_NODE_IDX(mat,node);
    777             for( i = 0; i < mat->dims; i++ )
    778                 if( idx[i] != nodeidx[i] )
    779                     break;
    780             if( i == mat->dims )
    781                 break;
    782         }
    783     }
    784 
    785     if( node )
    786     {
    787         if( prev )
    788             prev->next = node->next;
    789         else
    790             mat->hashtable[tabidx] = node->next;
    791         cvSetRemoveByPtr( mat->heap, node );
    792     }
    793 }
    794 
    795 
    796 /****************************************************************************************\
    797 *                          Common for multiple array types operations                    *
    798 \****************************************************************************************/
    799 
    800 // Allocates underlying array data
    801 CV_IMPL void
    802 cvCreateData( CvArr* arr )
    803 {
    804     if( CV_IS_MAT_HDR_Z( arr ))
    805     {
    806         size_t step, total_size;
    807         CvMat* mat = (CvMat*)arr;
    808         step = mat->step;
    809 
    810         if( mat->rows == 0 || mat->cols == 0 )
    811             return;
    812 
    813         if( mat->data.ptr != 0 )
    814             CV_Error( CV_StsError, "Data is already allocated" );
    815 
    816         if( step == 0 )
    817             step = CV_ELEM_SIZE(mat->type)*mat->cols;
    818 
    819         int64 _total_size = (int64)step*mat->rows + sizeof(int) + CV_MALLOC_ALIGN;
    820         total_size = (size_t)_total_size;
    821         if(_total_size != (int64)total_size)
    822             CV_Error(CV_StsNoMem, "Too big buffer is allocated" );
    823         mat->refcount = (int*)cvAlloc( (size_t)total_size );
    824         mat->data.ptr = (uchar*)cvAlignPtr( mat->refcount + 1, CV_MALLOC_ALIGN );
    825         *mat->refcount = 1;
    826     }
    827     else if( CV_IS_IMAGE_HDR(arr))
    828     {
    829         IplImage* img = (IplImage*)arr;
    830 
    831         if( img->imageData != 0 )
    832             CV_Error( CV_StsError, "Data is already allocated" );
    833 
    834         if( !CvIPL.allocateData )
    835         {
    836             img->imageData = img->imageDataOrigin =
    837                         (char*)cvAlloc( (size_t)img->imageSize );
    838         }
    839         else
    840         {
    841             int depth = img->depth;
    842             int width = img->width;
    843 
    844             if( img->depth == IPL_DEPTH_32F || img->depth == IPL_DEPTH_64F )
    845             {
    846                 img->width *= img->depth == IPL_DEPTH_32F ? sizeof(float) : sizeof(double);
    847                 img->depth = IPL_DEPTH_8U;
    848             }
    849 
    850             CvIPL.allocateData( img, 0, 0 );
    851 
    852             img->width = width;
    853             img->depth = depth;
    854         }
    855     }
    856     else if( CV_IS_MATND_HDR( arr ))
    857     {
    858         CvMatND* mat = (CvMatND*)arr;
    859         size_t total_size = CV_ELEM_SIZE(mat->type);
    860 
    861         if( mat->dim[0].size == 0 )
    862             return;
    863 
    864         if( mat->data.ptr != 0 )
    865             CV_Error( CV_StsError, "Data is already allocated" );
    866 
    867         if( CV_IS_MAT_CONT( mat->type ))
    868         {
    869             total_size = (size_t)mat->dim[0].size*(mat->dim[0].step != 0 ?
    870                          (size_t)mat->dim[0].step : total_size);
    871         }
    872         else
    873         {
    874             int i;
    875             for( i = mat->dims - 1; i >= 0; i-- )
    876             {
    877                 size_t size = (size_t)mat->dim[i].step*mat->dim[i].size;
    878 
    879                 if( total_size < size )
    880                     total_size = size;
    881             }
    882         }
    883 
    884         mat->refcount = (int*)cvAlloc( total_size +
    885                                         sizeof(int) + CV_MALLOC_ALIGN );
    886         mat->data.ptr = (uchar*)cvAlignPtr( mat->refcount + 1, CV_MALLOC_ALIGN );
    887         *mat->refcount = 1;
    888     }
    889     else
    890         CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
    891 }
    892 
    893 
    894 // Assigns external data to array
    895 CV_IMPL void
    896 cvSetData( CvArr* arr, void* data, int step )
    897 {
    898     int pix_size, min_step;
    899 
    900     if( CV_IS_MAT_HDR(arr) || CV_IS_MATND_HDR(arr) )
    901         cvReleaseData( arr );
    902 
    903     if( CV_IS_MAT_HDR( arr ))
    904     {
    905         CvMat* mat = (CvMat*)arr;
    906 
    907         int type = CV_MAT_TYPE(mat->type);
    908         pix_size = CV_ELEM_SIZE(type);
    909         min_step = mat->cols*pix_size;
    910 
    911         if( step != CV_AUTOSTEP && step != 0 )
    912         {
    913             if( step < min_step && data != 0 )
    914                 CV_Error( CV_BadStep, "" );
    915             mat->step = step;
    916         }
    917         else
    918             mat->step = min_step;
    919 
    920         mat->data.ptr = (uchar*)data;
    921         mat->type = CV_MAT_MAGIC_VAL | type |
    922                     (mat->rows == 1 || mat->step == min_step ? CV_MAT_CONT_FLAG : 0);
    923         icvCheckHuge( mat );
    924     }
    925     else if( CV_IS_IMAGE_HDR( arr ))
    926     {
    927         IplImage* img = (IplImage*)arr;
    928 
    929         pix_size = ((img->depth & 255) >> 3)*img->nChannels;
    930         min_step = img->width*pix_size;
    931 
    932         if( step != CV_AUTOSTEP && img->height > 1 )
    933         {
    934             if( step < min_step && data != 0 )
    935                 CV_Error( CV_BadStep, "" );
    936             img->widthStep = step;
    937         }
    938         else
    939         {
    940             img->widthStep = min_step;
    941         }
    942 
    943         img->imageSize = img->widthStep * img->height;
    944         img->imageData = img->imageDataOrigin = (char*)data;
    945 
    946         if( (((int)(size_t)data | step) & 7) == 0 &&
    947             cvAlign(img->width * pix_size, 8) == step )
    948             img->align = 8;
    949         else
    950             img->align = 4;
    951     }
    952     else if( CV_IS_MATND_HDR( arr ))
    953     {
    954         CvMatND* mat = (CvMatND*)arr;
    955         int i;
    956         int64 cur_step;
    957 
    958         if( step != CV_AUTOSTEP )
    959             CV_Error( CV_BadStep,
    960             "For multidimensional array only CV_AUTOSTEP is allowed here" );
    961 
    962         mat->data.ptr = (uchar*)data;
    963         cur_step = CV_ELEM_SIZE(mat->type);
    964 
    965         for( i = mat->dims - 1; i >= 0; i-- )
    966         {
    967             if( cur_step > INT_MAX )
    968                 CV_Error( CV_StsOutOfRange, "The array is too big" );
    969             mat->dim[i].step = (int)cur_step;
    970             cur_step *= mat->dim[i].size;
    971         }
    972     }
    973     else
    974         CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
    975 }
    976 
    977 
    978 // Deallocates array's data
    979 CV_IMPL void
    980 cvReleaseData( CvArr* arr )
    981 {
    982     if( CV_IS_MAT_HDR( arr ) || CV_IS_MATND_HDR( arr ))
    983     {
    984         CvMat* mat = (CvMat*)arr;
    985         cvDecRefData( mat );
    986     }
    987     else if( CV_IS_IMAGE_HDR( arr ))
    988     {
    989         IplImage* img = (IplImage*)arr;
    990 
    991         if( !CvIPL.deallocate )
    992         {
    993             char* ptr = img->imageDataOrigin;
    994             img->imageData = img->imageDataOrigin = 0;
    995             cvFree( &ptr );
    996         }
    997         else
    998         {
    999             CvIPL.deallocate( img, IPL_IMAGE_DATA );
   1000         }
   1001     }
   1002     else
   1003         CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
   1004 }
   1005 
   1006 
   1007 // Retrieves essential information about image ROI or CvMat data
   1008 CV_IMPL void
   1009 cvGetRawData( const CvArr* arr, uchar** data, int* step, CvSize* roi_size )
   1010 {
   1011     if( CV_IS_MAT( arr ))
   1012     {
   1013         CvMat *mat = (CvMat*)arr;
   1014 
   1015         if( step )
   1016             *step = mat->step;
   1017 
   1018         if( data )
   1019             *data = mat->data.ptr;
   1020 
   1021         if( roi_size )
   1022             *roi_size = cvGetMatSize( mat );
   1023     }
   1024     else if( CV_IS_IMAGE( arr ))
   1025     {
   1026         IplImage* img = (IplImage*)arr;
   1027 
   1028         if( step )
   1029             *step = img->widthStep;
   1030 
   1031         if( data )
   1032             *data = cvPtr2D( img, 0, 0 );
   1033 
   1034         if( roi_size )
   1035         {
   1036             if( img->roi )
   1037             {
   1038                 *roi_size = cvSize( img->roi->width, img->roi->height );
   1039             }
   1040             else
   1041             {
   1042                 *roi_size = cvSize( img->width, img->height );
   1043             }
   1044         }
   1045     }
   1046     else if( CV_IS_MATND( arr ))
   1047     {
   1048         CvMatND* mat = (CvMatND*)arr;
   1049 
   1050         if( !CV_IS_MAT_CONT( mat->type ))
   1051             CV_Error( CV_StsBadArg, "Only continuous nD arrays are supported here" );
   1052 
   1053         if( data )
   1054             *data = mat->data.ptr;
   1055 
   1056         if( roi_size || step )
   1057         {
   1058             if( roi_size )
   1059             {
   1060                 int size1 = mat->dim[0].size, size2 = 1;
   1061 
   1062                 if( mat->dims > 2 )
   1063                 {
   1064                     int i;
   1065                     for( i = 1; i < mat->dims; i++ )
   1066                         size1 *= mat->dim[i].size;
   1067                 }
   1068                 else
   1069                     size2 = mat->dim[1].size;
   1070 
   1071                 roi_size->width = size2;
   1072                 roi_size->height = size1;
   1073             }
   1074 
   1075             if( step )
   1076                 *step = mat->dim[0].step;
   1077         }
   1078     }
   1079     else
   1080         CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
   1081 }
   1082 
   1083 
   1084 CV_IMPL int
   1085 cvGetElemType( const CvArr* arr )
   1086 {
   1087     int type = -1;
   1088     if( CV_IS_MAT_HDR(arr) || CV_IS_MATND_HDR(arr) || CV_IS_SPARSE_MAT_HDR(arr))
   1089         type = CV_MAT_TYPE( ((CvMat*)arr)->type );
   1090     else if( CV_IS_IMAGE(arr))
   1091     {
   1092         IplImage* img = (IplImage*)arr;
   1093         type = CV_MAKETYPE( IPL2CV_DEPTH(img->depth), img->nChannels );
   1094     }
   1095     else
   1096         CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
   1097 
   1098     return type;
   1099 }
   1100 
   1101 
   1102 // Returns a number of array dimensions
   1103 CV_IMPL int
   1104 cvGetDims( const CvArr* arr, int* sizes )
   1105 {
   1106     int dims = -1;
   1107     if( CV_IS_MAT_HDR( arr ))
   1108     {
   1109         CvMat* mat = (CvMat*)arr;
   1110 
   1111         dims = 2;
   1112         if( sizes )
   1113         {
   1114             sizes[0] = mat->rows;
   1115             sizes[1] = mat->cols;
   1116         }
   1117     }
   1118     else if( CV_IS_IMAGE( arr ))
   1119     {
   1120         IplImage* img = (IplImage*)arr;
   1121         dims = 2;
   1122 
   1123         if( sizes )
   1124         {
   1125             sizes[0] = img->height;
   1126             sizes[1] = img->width;
   1127         }
   1128     }
   1129     else if( CV_IS_MATND_HDR( arr ))
   1130     {
   1131         CvMatND* mat = (CvMatND*)arr;
   1132         dims = mat->dims;
   1133 
   1134         if( sizes )
   1135         {
   1136             int i;
   1137             for( i = 0; i < dims; i++ )
   1138                 sizes[i] = mat->dim[i].size;
   1139         }
   1140     }
   1141     else if( CV_IS_SPARSE_MAT_HDR( arr ))
   1142     {
   1143         CvSparseMat* mat = (CvSparseMat*)arr;
   1144         dims = mat->dims;
   1145 
   1146         if( sizes )
   1147             memcpy( sizes, mat->size, dims*sizeof(sizes[0]));
   1148     }
   1149     else
   1150         CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
   1151 
   1152     return dims;
   1153 }
   1154 
   1155 
   1156 // Returns the size of particular array dimension
   1157 CV_IMPL int
   1158 cvGetDimSize( const CvArr* arr, int index )
   1159 {
   1160     int size = -1;
   1161 
   1162     if( CV_IS_MAT( arr ))
   1163     {
   1164         CvMat *mat = (CvMat*)arr;
   1165 
   1166         switch( index )
   1167         {
   1168         case 0:
   1169             size = mat->rows;
   1170             break;
   1171         case 1:
   1172             size = mat->cols;
   1173             break;
   1174         default:
   1175             CV_Error( CV_StsOutOfRange, "bad dimension index" );
   1176         }
   1177     }
   1178     else if( CV_IS_IMAGE( arr ))
   1179     {
   1180         IplImage* img = (IplImage*)arr;
   1181 
   1182         switch( index )
   1183         {
   1184         case 0:
   1185             size = !img->roi ? img->height : img->roi->height;
   1186             break;
   1187         case 1:
   1188             size = !img->roi ? img->width : img->roi->width;
   1189             break;
   1190         default:
   1191             CV_Error( CV_StsOutOfRange, "bad dimension index" );
   1192         }
   1193     }
   1194     else if( CV_IS_MATND_HDR( arr ))
   1195     {
   1196         CvMatND* mat = (CvMatND*)arr;
   1197 
   1198         if( (unsigned)index >= (unsigned)mat->dims )
   1199             CV_Error( CV_StsOutOfRange, "bad dimension index" );
   1200 
   1201         size = mat->dim[index].size;
   1202     }
   1203     else if( CV_IS_SPARSE_MAT_HDR( arr ))
   1204     {
   1205         CvSparseMat* mat = (CvSparseMat*)arr;
   1206 
   1207         if( (unsigned)index >= (unsigned)mat->dims )
   1208             CV_Error( CV_StsOutOfRange, "bad dimension index" );
   1209 
   1210         size = mat->size[index];
   1211     }
   1212     else
   1213         CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
   1214 
   1215     return size;
   1216 }
   1217 
   1218 
   1219 // Returns the size of CvMat or IplImage
   1220 CV_IMPL CvSize
   1221 cvGetSize( const CvArr* arr )
   1222 {
   1223     CvSize size;
   1224 
   1225     if( CV_IS_MAT_HDR_Z( arr ))
   1226     {
   1227         CvMat *mat = (CvMat*)arr;
   1228 
   1229         size.width = mat->cols;
   1230         size.height = mat->rows;
   1231     }
   1232     else if( CV_IS_IMAGE_HDR( arr ))
   1233     {
   1234         IplImage* img = (IplImage*)arr;
   1235 
   1236         if( img->roi )
   1237         {
   1238             size.width = img->roi->width;
   1239             size.height = img->roi->height;
   1240         }
   1241         else
   1242         {
   1243             size.width = img->width;
   1244             size.height = img->height;
   1245         }
   1246     }
   1247     else
   1248         CV_Error( CV_StsBadArg, "Array should be CvMat or IplImage" );
   1249 
   1250     return size;
   1251 }
   1252 
   1253 
   1254 // Selects sub-array (no data is copied)
   1255 CV_IMPL  CvMat*
   1256 cvGetSubRect( const CvArr* arr, CvMat* submat, CvRect rect )
   1257 {
   1258     CvMat* res = 0;
   1259     CvMat stub, *mat = (CvMat*)arr;
   1260 
   1261     if( !CV_IS_MAT( mat ))
   1262         mat = cvGetMat( mat, &stub );
   1263 
   1264     if( !submat )
   1265         CV_Error( CV_StsNullPtr, "" );
   1266 
   1267     if( (rect.x|rect.y|rect.width|rect.height) < 0 )
   1268         CV_Error( CV_StsBadSize, "" );
   1269 
   1270     if( rect.x + rect.width > mat->cols ||
   1271         rect.y + rect.height > mat->rows )
   1272         CV_Error( CV_StsBadSize, "" );
   1273 
   1274     {
   1275     /*
   1276     int* refcount = mat->refcount;
   1277 
   1278     if( refcount )
   1279         ++*refcount;
   1280 
   1281     cvDecRefData( submat );
   1282     */
   1283     submat->data.ptr = mat->data.ptr + (size_t)rect.y*mat->step +
   1284                        rect.x*CV_ELEM_SIZE(mat->type);
   1285     submat->step = mat->step;
   1286     submat->type = (mat->type & (rect.width < mat->cols ? ~CV_MAT_CONT_FLAG : -1)) |
   1287                    (rect.height <= 1 ? CV_MAT_CONT_FLAG : 0);
   1288     submat->rows = rect.height;
   1289     submat->cols = rect.width;
   1290     submat->refcount = 0;
   1291     res = submat;
   1292     }
   1293 
   1294     return res;
   1295 }
   1296 
   1297 
   1298 // Selects array's row span.
   1299 CV_IMPL  CvMat*
   1300 cvGetRows( const CvArr* arr, CvMat* submat,
   1301            int start_row, int end_row, int delta_row )
   1302 {
   1303     CvMat* res = 0;
   1304     CvMat stub, *mat = (CvMat*)arr;
   1305 
   1306     if( !CV_IS_MAT( mat ))
   1307         mat = cvGetMat( mat, &stub );
   1308 
   1309     if( !submat )
   1310         CV_Error( CV_StsNullPtr, "" );
   1311 
   1312     if( (unsigned)start_row >= (unsigned)mat->rows ||
   1313         (unsigned)end_row > (unsigned)mat->rows || delta_row <= 0 )
   1314         CV_Error( CV_StsOutOfRange, "" );
   1315 
   1316     {
   1317     /*
   1318     int* refcount = mat->refcount;
   1319 
   1320     if( refcount )
   1321         ++*refcount;
   1322 
   1323     cvDecRefData( submat );
   1324     */
   1325     if( delta_row == 1 )
   1326     {
   1327         submat->rows = end_row - start_row;
   1328         submat->step = mat->step;
   1329     }
   1330     else
   1331     {
   1332         submat->rows = (end_row - start_row + delta_row - 1)/delta_row;
   1333         submat->step = mat->step * delta_row;
   1334     }
   1335 
   1336     submat->cols = mat->cols;
   1337     submat->step &= submat->rows > 1 ? -1 : 0;
   1338     submat->data.ptr = mat->data.ptr + (size_t)start_row*mat->step;
   1339     submat->type = (mat->type | (submat->rows == 1 ? CV_MAT_CONT_FLAG : 0)) &
   1340                    (delta_row != 1 && submat->rows > 1 ? ~CV_MAT_CONT_FLAG : -1);
   1341     submat->refcount = 0;
   1342     submat->hdr_refcount = 0;
   1343     res = submat;
   1344     }
   1345 
   1346     return res;
   1347 }
   1348 
   1349 
   1350 // Selects array's column span.
   1351 CV_IMPL  CvMat*
   1352 cvGetCols( const CvArr* arr, CvMat* submat, int start_col, int end_col )
   1353 {
   1354     CvMat* res = 0;
   1355     CvMat stub, *mat = (CvMat*)arr;
   1356     int cols;
   1357 
   1358     if( !CV_IS_MAT( mat ))
   1359         mat = cvGetMat( mat, &stub );
   1360 
   1361     if( !submat )
   1362         CV_Error( CV_StsNullPtr, "" );
   1363 
   1364     cols = mat->cols;
   1365     if( (unsigned)start_col >= (unsigned)cols ||
   1366         (unsigned)end_col > (unsigned)cols )
   1367         CV_Error( CV_StsOutOfRange, "" );
   1368 
   1369     {
   1370     /*
   1371     int* refcount = mat->refcount;
   1372 
   1373     if( refcount )
   1374         ++*refcount;
   1375 
   1376     cvDecRefData( submat );
   1377     */
   1378     submat->rows = mat->rows;
   1379     submat->cols = end_col - start_col;
   1380     submat->step = mat->step;
   1381     submat->data.ptr = mat->data.ptr + (size_t)start_col*CV_ELEM_SIZE(mat->type);
   1382     submat->type = mat->type & (submat->rows > 1 && submat->cols < cols ? ~CV_MAT_CONT_FLAG : -1);
   1383     submat->refcount = 0;
   1384     submat->hdr_refcount = 0;
   1385     res = submat;
   1386     }
   1387 
   1388     return res;
   1389 }
   1390 
   1391 
   1392 // Selects array diagonal
   1393 CV_IMPL  CvMat*
   1394 cvGetDiag( const CvArr* arr, CvMat* submat, int diag )
   1395 {
   1396     CvMat* res = 0;
   1397     CvMat stub, *mat = (CvMat*)arr;
   1398     int len, pix_size;
   1399 
   1400     if( !CV_IS_MAT( mat ))
   1401         mat = cvGetMat( mat, &stub );
   1402 
   1403     if( !submat )
   1404         CV_Error( CV_StsNullPtr, "" );
   1405 
   1406     pix_size = CV_ELEM_SIZE(mat->type);
   1407 
   1408     /*{
   1409     int* refcount = mat->refcount;
   1410 
   1411     if( refcount )
   1412         ++*refcount;
   1413 
   1414     cvDecRefData( submat );
   1415     }*/
   1416 
   1417     if( diag >= 0 )
   1418     {
   1419         len = mat->cols - diag;
   1420 
   1421         if( len <= 0 )
   1422             CV_Error( CV_StsOutOfRange, "" );
   1423 
   1424         len = CV_IMIN( len, mat->rows );
   1425         submat->data.ptr = mat->data.ptr + diag*pix_size;
   1426     }
   1427     else
   1428     {
   1429         len = mat->rows + diag;
   1430 
   1431         if( len <= 0 )
   1432             CV_Error( CV_StsOutOfRange, "" );
   1433 
   1434         len = CV_IMIN( len, mat->cols );
   1435         submat->data.ptr = mat->data.ptr - diag*mat->step;
   1436     }
   1437 
   1438     submat->rows = len;
   1439     submat->cols = 1;
   1440     submat->step = mat->step + (submat->rows > 1 ? pix_size : 0);
   1441     submat->type = mat->type;
   1442     if( submat->rows > 1 )
   1443         submat->type &= ~CV_MAT_CONT_FLAG;
   1444     else
   1445         submat->type |= CV_MAT_CONT_FLAG;
   1446     submat->refcount = 0;
   1447     submat->hdr_refcount = 0;
   1448     res = submat;
   1449 
   1450     return res;
   1451 }
   1452 
   1453 
   1454 /****************************************************************************************\
   1455 *                      Operations on CvScalar and accessing array elements               *
   1456 \****************************************************************************************/
   1457 
   1458 // Converts CvScalar to specified type
   1459 CV_IMPL void
   1460 cvScalarToRawData( const CvScalar* scalar, void* data, int type, int extend_to_12 )
   1461 {
   1462     type = CV_MAT_TYPE(type);
   1463     int cn = CV_MAT_CN( type );
   1464     int depth = type & CV_MAT_DEPTH_MASK;
   1465 
   1466     assert( scalar && data );
   1467     if( (unsigned)(cn - 1) >= 4 )
   1468         CV_Error( CV_StsOutOfRange, "The number of channels must be 1, 2, 3 or 4" );
   1469 
   1470     switch( depth )
   1471     {
   1472     case CV_8UC1:
   1473         while( cn-- )
   1474         {
   1475             int t = cvRound( scalar->val[cn] );
   1476             ((uchar*)data)[cn] = cv::saturate_cast<uchar>(t);
   1477         }
   1478         break;
   1479     case CV_8SC1:
   1480         while( cn-- )
   1481         {
   1482             int t = cvRound( scalar->val[cn] );
   1483             ((char*)data)[cn] = cv::saturate_cast<schar>(t);
   1484         }
   1485         break;
   1486     case CV_16UC1:
   1487         while( cn-- )
   1488         {
   1489             int t = cvRound( scalar->val[cn] );
   1490             ((ushort*)data)[cn] = cv::saturate_cast<ushort>(t);
   1491         }
   1492         break;
   1493     case CV_16SC1:
   1494         while( cn-- )
   1495         {
   1496             int t = cvRound( scalar->val[cn] );
   1497             ((short*)data)[cn] = cv::saturate_cast<short>(t);
   1498         }
   1499         break;
   1500     case CV_32SC1:
   1501         while( cn-- )
   1502             ((int*)data)[cn] = cvRound( scalar->val[cn] );
   1503         break;
   1504     case CV_32FC1:
   1505         while( cn-- )
   1506             ((float*)data)[cn] = (float)(scalar->val[cn]);
   1507         break;
   1508     case CV_64FC1:
   1509         while( cn-- )
   1510             ((double*)data)[cn] = (double)(scalar->val[cn]);
   1511         break;
   1512     default:
   1513         assert(0);
   1514         CV_Error( CV_BadDepth, "" );
   1515     }
   1516 
   1517     if( extend_to_12 )
   1518     {
   1519         int pix_size = CV_ELEM_SIZE(type);
   1520         int offset = CV_ELEM_SIZE1(depth)*12;
   1521 
   1522         do
   1523         {
   1524             offset -= pix_size;
   1525             memcpy((char*)data + offset, data, pix_size);
   1526         }
   1527         while( offset > pix_size );
   1528     }
   1529 }
   1530 
   1531 
   1532 // Converts data of specified type to CvScalar
   1533 CV_IMPL void
   1534 cvRawDataToScalar( const void* data, int flags, CvScalar* scalar )
   1535 {
   1536     int cn = CV_MAT_CN( flags );
   1537 
   1538     assert( scalar && data );
   1539 
   1540     if( (unsigned)(cn - 1) >= 4 )
   1541         CV_Error( CV_StsOutOfRange, "The number of channels must be 1, 2, 3 or 4" );
   1542 
   1543     memset( scalar->val, 0, sizeof(scalar->val));
   1544 
   1545     switch( CV_MAT_DEPTH( flags ))
   1546     {
   1547     case CV_8U:
   1548         while( cn-- )
   1549             scalar->val[cn] = CV_8TO32F(((uchar*)data)[cn]);
   1550         break;
   1551     case CV_8S:
   1552         while( cn-- )
   1553             scalar->val[cn] = CV_8TO32F(((char*)data)[cn]);
   1554         break;
   1555     case CV_16U:
   1556         while( cn-- )
   1557             scalar->val[cn] = ((ushort*)data)[cn];
   1558         break;
   1559     case CV_16S:
   1560         while( cn-- )
   1561             scalar->val[cn] = ((short*)data)[cn];
   1562         break;
   1563     case CV_32S:
   1564         while( cn-- )
   1565             scalar->val[cn] = ((int*)data)[cn];
   1566         break;
   1567     case CV_32F:
   1568         while( cn-- )
   1569             scalar->val[cn] = ((float*)data)[cn];
   1570         break;
   1571     case CV_64F:
   1572         while( cn-- )
   1573             scalar->val[cn] = ((double*)data)[cn];
   1574         break;
   1575     default:
   1576         assert(0);
   1577         CV_Error( CV_BadDepth, "" );
   1578     }
   1579 }
   1580 
   1581 
   1582 static double icvGetReal( const void* data, int type )
   1583 {
   1584     switch( type )
   1585     {
   1586     case CV_8U:
   1587         return *(uchar*)data;
   1588     case CV_8S:
   1589         return *(char*)data;
   1590     case CV_16U:
   1591         return *(ushort*)data;
   1592     case CV_16S:
   1593         return *(short*)data;
   1594     case CV_32S:
   1595         return *(int*)data;
   1596     case CV_32F:
   1597         return *(float*)data;
   1598     case CV_64F:
   1599         return *(double*)data;
   1600     }
   1601 
   1602     return 0;
   1603 }
   1604 
   1605 
   1606 static void icvSetReal( double value, const void* data, int type )
   1607 {
   1608     if( type < CV_32F )
   1609     {
   1610         int ivalue = cvRound(value);
   1611         switch( type )
   1612         {
   1613         case CV_8U:
   1614             *(uchar*)data = cv::saturate_cast<uchar>(ivalue);
   1615             break;
   1616         case CV_8S:
   1617             *(schar*)data = cv::saturate_cast<schar>(ivalue);
   1618             break;
   1619         case CV_16U:
   1620             *(ushort*)data = cv::saturate_cast<ushort>(ivalue);
   1621             break;
   1622         case CV_16S:
   1623             *(short*)data = cv::saturate_cast<short>(ivalue);
   1624             break;
   1625         case CV_32S:
   1626             *(int*)data = cv::saturate_cast<int>(ivalue);
   1627             break;
   1628         }
   1629     }
   1630     else
   1631     {
   1632         switch( type )
   1633         {
   1634         case CV_32F:
   1635             *(float*)data = (float)value;
   1636             break;
   1637         case CV_64F:
   1638             *(double*)data = value;
   1639             break;
   1640         }
   1641     }
   1642 }
   1643 
   1644 
   1645 // Returns pointer to specified element of array (linear index is used)
   1646 CV_IMPL  uchar*
   1647 cvPtr1D( const CvArr* arr, int idx, int* _type )
   1648 {
   1649     uchar* ptr = 0;
   1650     if( CV_IS_MAT( arr ))
   1651     {
   1652         CvMat* mat = (CvMat*)arr;
   1653 
   1654         int type = CV_MAT_TYPE(mat->type);
   1655         int pix_size = CV_ELEM_SIZE(type);
   1656 
   1657         if( _type )
   1658             *_type = type;
   1659 
   1660         // the first part is mul-free sufficient check
   1661         // that the index is within the matrix
   1662         if( (unsigned)idx >= (unsigned)(mat->rows + mat->cols - 1) &&
   1663             (unsigned)idx >= (unsigned)(mat->rows*mat->cols))
   1664             CV_Error( CV_StsOutOfRange, "index is out of range" );
   1665 
   1666         if( CV_IS_MAT_CONT(mat->type))
   1667         {
   1668             ptr = mat->data.ptr + (size_t)idx*pix_size;
   1669         }
   1670         else
   1671         {
   1672             int row, col;
   1673             if( mat->cols == 1 )
   1674                 row = idx, col = 0;
   1675             else
   1676                 row = idx/mat->cols, col = idx - row*mat->cols;
   1677             ptr = mat->data.ptr + (size_t)row*mat->step + col*pix_size;
   1678         }
   1679     }
   1680     else if( CV_IS_IMAGE_HDR( arr ))
   1681     {
   1682         IplImage* img = (IplImage*)arr;
   1683         int width = !img->roi ? img->width : img->roi->width;
   1684         int y = idx/width, x = idx - y*width;
   1685 
   1686         ptr = cvPtr2D( arr, y, x, _type );
   1687     }
   1688     else if( CV_IS_MATND( arr ))
   1689     {
   1690         CvMatND* mat = (CvMatND*)arr;
   1691         int j, type = CV_MAT_TYPE(mat->type);
   1692         size_t size = mat->dim[0].size;
   1693 
   1694         if( _type )
   1695             *_type = type;
   1696 
   1697         for( j = 1; j < mat->dims; j++ )
   1698             size *= mat->dim[j].size;
   1699 
   1700         if((unsigned)idx >= (unsigned)size )
   1701             CV_Error( CV_StsOutOfRange, "index is out of range" );
   1702 
   1703         if( CV_IS_MAT_CONT(mat->type))
   1704         {
   1705             int pix_size = CV_ELEM_SIZE(type);
   1706             ptr = mat->data.ptr + (size_t)idx*pix_size;
   1707         }
   1708         else
   1709         {
   1710             ptr = mat->data.ptr;
   1711             for( j = mat->dims - 1; j >= 0; j-- )
   1712             {
   1713                 int sz = mat->dim[j].size;
   1714                 if( sz )
   1715                 {
   1716                     int t = idx/sz;
   1717                     ptr += (idx - t*sz)*mat->dim[j].step;
   1718                     idx = t;
   1719                 }
   1720             }
   1721         }
   1722     }
   1723     else if( CV_IS_SPARSE_MAT( arr ))
   1724     {
   1725         CvSparseMat* m = (CvSparseMat*)arr;
   1726         if( m->dims == 1 )
   1727             ptr = icvGetNodePtr( (CvSparseMat*)arr, &idx, _type, 1, 0 );
   1728         else
   1729         {
   1730             int i, n = m->dims;
   1731             CV_DbgAssert( n <= CV_MAX_DIM_HEAP );
   1732             int _idx[CV_MAX_DIM_HEAP];
   1733 
   1734             for( i = n - 1; i >= 0; i-- )
   1735             {
   1736                 int t = idx / m->size[i];
   1737                 _idx[i] = idx - t*m->size[i];
   1738                 idx = t;
   1739             }
   1740             ptr = icvGetNodePtr( (CvSparseMat*)arr, _idx, _type, 1, 0 );
   1741         }
   1742     }
   1743     else
   1744     {
   1745         CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
   1746     }
   1747 
   1748     return ptr;
   1749 }
   1750 
   1751 
   1752 // Returns pointer to specified element of 2d array
   1753 CV_IMPL  uchar*
   1754 cvPtr2D( const CvArr* arr, int y, int x, int* _type )
   1755 {
   1756     uchar* ptr = 0;
   1757     if( CV_IS_MAT( arr ))
   1758     {
   1759         CvMat* mat = (CvMat*)arr;
   1760         int type;
   1761 
   1762         if( (unsigned)y >= (unsigned)(mat->rows) ||
   1763             (unsigned)x >= (unsigned)(mat->cols) )
   1764             CV_Error( CV_StsOutOfRange, "index is out of range" );
   1765 
   1766         type = CV_MAT_TYPE(mat->type);
   1767         if( _type )
   1768             *_type = type;
   1769 
   1770         ptr = mat->data.ptr + (size_t)y*mat->step + x*CV_ELEM_SIZE(type);
   1771     }
   1772     else if( CV_IS_IMAGE( arr ))
   1773     {
   1774         IplImage* img = (IplImage*)arr;
   1775         int pix_size = (img->depth & 255) >> 3;
   1776         int width, height;
   1777         ptr = (uchar*)img->imageData;
   1778 
   1779         if( img->dataOrder == 0 )
   1780             pix_size *= img->nChannels;
   1781 
   1782         if( img->roi )
   1783         {
   1784             width = img->roi->width;
   1785             height = img->roi->height;
   1786 
   1787             ptr += img->roi->yOffset*img->widthStep +
   1788                    img->roi->xOffset*pix_size;
   1789 
   1790             if( img->dataOrder )
   1791             {
   1792                 int coi = img->roi->coi;
   1793                 if( !coi )
   1794                     CV_Error( CV_BadCOI,
   1795                         "COI must be non-null in case of planar images" );
   1796                 ptr += (coi - 1)*img->imageSize;
   1797             }
   1798         }
   1799         else
   1800         {
   1801             width = img->width;
   1802             height = img->height;
   1803         }
   1804 
   1805         if( (unsigned)y >= (unsigned)height ||
   1806             (unsigned)x >= (unsigned)width )
   1807             CV_Error( CV_StsOutOfRange, "index is out of range" );
   1808 
   1809         ptr += y*img->widthStep + x*pix_size;
   1810 
   1811         if( _type )
   1812         {
   1813             int type = IPL2CV_DEPTH(img->depth);
   1814             if( type < 0 || (unsigned)(img->nChannels - 1) > 3 )
   1815                 CV_Error( CV_StsUnsupportedFormat, "" );
   1816 
   1817             *_type = CV_MAKETYPE( type, img->nChannels );
   1818         }
   1819     }
   1820     else if( CV_IS_MATND( arr ))
   1821     {
   1822         CvMatND* mat = (CvMatND*)arr;
   1823 
   1824         if( mat->dims != 2 ||
   1825             (unsigned)y >= (unsigned)(mat->dim[0].size) ||
   1826             (unsigned)x >= (unsigned)(mat->dim[1].size) )
   1827             CV_Error( CV_StsOutOfRange, "index is out of range" );
   1828 
   1829         ptr = mat->data.ptr + (size_t)y*mat->dim[0].step + x*mat->dim[1].step;
   1830         if( _type )
   1831             *_type = CV_MAT_TYPE(mat->type);
   1832     }
   1833     else if( CV_IS_SPARSE_MAT( arr ))
   1834     {
   1835         int idx[] = { y, x };
   1836         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, _type, 1, 0 );
   1837     }
   1838     else
   1839     {
   1840         CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
   1841     }
   1842 
   1843     return ptr;
   1844 }
   1845 
   1846 
   1847 // Returns pointer to specified element of 3d array
   1848 CV_IMPL  uchar*
   1849 cvPtr3D( const CvArr* arr, int z, int y, int x, int* _type )
   1850 {
   1851     uchar* ptr = 0;
   1852     if( CV_IS_MATND( arr ))
   1853     {
   1854         CvMatND* mat = (CvMatND*)arr;
   1855 
   1856         if( mat->dims != 3 ||
   1857             (unsigned)z >= (unsigned)(mat->dim[0].size) ||
   1858             (unsigned)y >= (unsigned)(mat->dim[1].size) ||
   1859             (unsigned)x >= (unsigned)(mat->dim[2].size) )
   1860             CV_Error( CV_StsOutOfRange, "index is out of range" );
   1861 
   1862         ptr = mat->data.ptr + (size_t)z*mat->dim[0].step +
   1863               (size_t)y*mat->dim[1].step + x*mat->dim[2].step;
   1864 
   1865         if( _type )
   1866             *_type = CV_MAT_TYPE(mat->type);
   1867     }
   1868     else if( CV_IS_SPARSE_MAT( arr ))
   1869     {
   1870         int idx[] = { z, y, x };
   1871         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, _type, 1, 0 );
   1872     }
   1873     else
   1874     {
   1875         CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
   1876     }
   1877 
   1878     return ptr;
   1879 }
   1880 
   1881 
   1882 // Returns pointer to specified element of n-d array
   1883 CV_IMPL  uchar*
   1884 cvPtrND( const CvArr* arr, const int* idx, int* _type,
   1885          int create_node, unsigned* precalc_hashval )
   1886 {
   1887     uchar* ptr = 0;
   1888     if( !idx )
   1889         CV_Error( CV_StsNullPtr, "NULL pointer to indices" );
   1890 
   1891     if( CV_IS_SPARSE_MAT( arr ))
   1892         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx,
   1893                              _type, create_node, precalc_hashval );
   1894     else if( CV_IS_MATND( arr ))
   1895     {
   1896         CvMatND* mat = (CvMatND*)arr;
   1897         int i;
   1898         ptr = mat->data.ptr;
   1899 
   1900         for( i = 0; i < mat->dims; i++ )
   1901         {
   1902             if( (unsigned)idx[i] >= (unsigned)(mat->dim[i].size) )
   1903                 CV_Error( CV_StsOutOfRange, "index is out of range" );
   1904             ptr += (size_t)idx[i]*mat->dim[i].step;
   1905         }
   1906 
   1907         if( _type )
   1908             *_type = CV_MAT_TYPE(mat->type);
   1909     }
   1910     else if( CV_IS_MAT_HDR(arr) || CV_IS_IMAGE_HDR(arr) )
   1911         ptr = cvPtr2D( arr, idx[0], idx[1], _type );
   1912     else
   1913         CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
   1914 
   1915     return ptr;
   1916 }
   1917 
   1918 
   1919 // Returns specifed element of n-D array given linear index
   1920 CV_IMPL  CvScalar
   1921 cvGet1D( const CvArr* arr, int idx )
   1922 {
   1923     CvScalar scalar(0);
   1924     int type = 0;
   1925     uchar* ptr;
   1926 
   1927     if( CV_IS_MAT( arr ) && CV_IS_MAT_CONT( ((CvMat*)arr)->type ))
   1928     {
   1929         CvMat* mat = (CvMat*)arr;
   1930 
   1931         type = CV_MAT_TYPE(mat->type);
   1932         int pix_size = CV_ELEM_SIZE(type);
   1933 
   1934         // the first part is mul-free sufficient check
   1935         // that the index is within the matrix
   1936         if( (unsigned)idx >= (unsigned)(mat->rows + mat->cols - 1) &&
   1937             (unsigned)idx >= (unsigned)(mat->rows*mat->cols))
   1938             CV_Error( CV_StsOutOfRange, "index is out of range" );
   1939 
   1940         ptr = mat->data.ptr + (size_t)idx*pix_size;
   1941     }
   1942     else if( !CV_IS_SPARSE_MAT( arr ) || ((CvSparseMat*)arr)->dims > 1 )
   1943         ptr = cvPtr1D( arr, idx, &type );
   1944     else
   1945         ptr = icvGetNodePtr( (CvSparseMat*)arr, &idx, &type, 0, 0 );
   1946 
   1947     if( ptr )
   1948         cvRawDataToScalar( ptr, type, &scalar );
   1949 
   1950     return scalar;
   1951 }
   1952 
   1953 
   1954 // Returns specifed element of 2D array
   1955 CV_IMPL  CvScalar
   1956 cvGet2D( const CvArr* arr, int y, int x )
   1957 {
   1958     CvScalar scalar(0);
   1959     int type = 0;
   1960     uchar* ptr;
   1961 
   1962     if( CV_IS_MAT( arr ))
   1963     {
   1964         CvMat* mat = (CvMat*)arr;
   1965 
   1966         if( (unsigned)y >= (unsigned)(mat->rows) ||
   1967             (unsigned)x >= (unsigned)(mat->cols) )
   1968             CV_Error( CV_StsOutOfRange, "index is out of range" );
   1969 
   1970         type = CV_MAT_TYPE(mat->type);
   1971         ptr = mat->data.ptr + (size_t)y*mat->step + x*CV_ELEM_SIZE(type);
   1972     }
   1973     else if( !CV_IS_SPARSE_MAT( arr ))
   1974         ptr = cvPtr2D( arr, y, x, &type );
   1975     else
   1976     {
   1977         int idx[] = { y, x };
   1978         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, 0, 0 );
   1979     }
   1980 
   1981     if( ptr )
   1982         cvRawDataToScalar( ptr, type, &scalar );
   1983 
   1984     return scalar;
   1985 }
   1986 
   1987 
   1988 // Returns specifed element of 3D array
   1989 CV_IMPL  CvScalar
   1990 cvGet3D( const CvArr* arr, int z, int y, int x )
   1991 {
   1992     CvScalar scalar(0);
   1993     int type = 0;
   1994     uchar* ptr;
   1995 
   1996     if( !CV_IS_SPARSE_MAT( arr ))
   1997         ptr = cvPtr3D( arr, z, y, x, &type );
   1998     else
   1999     {
   2000         int idx[] = { z, y, x };
   2001         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, 0, 0 );
   2002     }
   2003 
   2004     if( ptr )
   2005         cvRawDataToScalar( ptr, type, &scalar );
   2006     return scalar;
   2007 }
   2008 
   2009 
   2010 // Returns specifed element of nD array
   2011 CV_IMPL  CvScalar
   2012 cvGetND( const CvArr* arr, const int* idx )
   2013 {
   2014     CvScalar scalar(0);
   2015     int type = 0;
   2016     uchar* ptr;
   2017 
   2018     if( !CV_IS_SPARSE_MAT( arr ))
   2019         ptr = cvPtrND( arr, idx, &type );
   2020     else
   2021         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, 0, 0 );
   2022 
   2023     if( ptr )
   2024         cvRawDataToScalar( ptr, type, &scalar );
   2025 
   2026     return scalar;
   2027 }
   2028 
   2029 
   2030 // Returns specifed element of n-D array given linear index
   2031 CV_IMPL  double
   2032 cvGetReal1D( const CvArr* arr, int idx )
   2033 {
   2034     double value = 0;
   2035     int type = 0;
   2036     uchar* ptr;
   2037 
   2038     if( CV_IS_MAT( arr ) && CV_IS_MAT_CONT( ((CvMat*)arr)->type ))
   2039     {
   2040         CvMat* mat = (CvMat*)arr;
   2041 
   2042         type = CV_MAT_TYPE(mat->type);
   2043         int pix_size = CV_ELEM_SIZE(type);
   2044 
   2045         // the first part is mul-free sufficient check
   2046         // that the index is within the matrix
   2047         if( (unsigned)idx >= (unsigned)(mat->rows + mat->cols - 1) &&
   2048             (unsigned)idx >= (unsigned)(mat->rows*mat->cols))
   2049             CV_Error( CV_StsOutOfRange, "index is out of range" );
   2050 
   2051         ptr = mat->data.ptr + (size_t)idx*pix_size;
   2052     }
   2053     else if( !CV_IS_SPARSE_MAT( arr ) || ((CvSparseMat*)arr)->dims > 1 )
   2054         ptr = cvPtr1D( arr, idx, &type );
   2055     else
   2056         ptr = icvGetNodePtr( (CvSparseMat*)arr, &idx, &type, 0, 0 );
   2057 
   2058     if( ptr )
   2059     {
   2060         if( CV_MAT_CN( type ) > 1 )
   2061             CV_Error( CV_BadNumChannels, "cvGetReal* support only single-channel arrays" );
   2062 
   2063         value = icvGetReal( ptr, type );
   2064     }
   2065     return value;
   2066 }
   2067 
   2068 
   2069 // Returns specifed element of 2D array
   2070 CV_IMPL  double
   2071 cvGetReal2D( const CvArr* arr, int y, int x )
   2072 {
   2073     double value = 0;
   2074     int type = 0;
   2075     uchar* ptr;
   2076 
   2077     if( CV_IS_MAT( arr ))
   2078     {
   2079         CvMat* mat = (CvMat*)arr;
   2080 
   2081         if( (unsigned)y >= (unsigned)(mat->rows) ||
   2082             (unsigned)x >= (unsigned)(mat->cols) )
   2083             CV_Error( CV_StsOutOfRange, "index is out of range" );
   2084 
   2085         type = CV_MAT_TYPE(mat->type);
   2086         ptr = mat->data.ptr + (size_t)y*mat->step + x*CV_ELEM_SIZE(type);
   2087     }
   2088     else if( !CV_IS_SPARSE_MAT( arr ))
   2089         ptr = cvPtr2D( arr, y, x, &type );
   2090     else
   2091     {
   2092         int idx[] = { y, x };
   2093         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, 0, 0 );
   2094     }
   2095 
   2096     if( ptr )
   2097     {
   2098         if( CV_MAT_CN( type ) > 1 )
   2099             CV_Error( CV_BadNumChannels, "cvGetReal* support only single-channel arrays" );
   2100 
   2101         value = icvGetReal( ptr, type );
   2102     }
   2103 
   2104     return value;
   2105 }
   2106 
   2107 
   2108 // Returns specifed element of 3D array
   2109 CV_IMPL  double
   2110 cvGetReal3D( const CvArr* arr, int z, int y, int x )
   2111 {
   2112     double value = 0;
   2113     int type = 0;
   2114     uchar* ptr;
   2115 
   2116     if( !CV_IS_SPARSE_MAT( arr ))
   2117         ptr = cvPtr3D( arr, z, y, x, &type );
   2118     else
   2119     {
   2120         int idx[] = { z, y, x };
   2121         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, 0, 0 );
   2122     }
   2123 
   2124     if( ptr )
   2125     {
   2126         if( CV_MAT_CN( type ) > 1 )
   2127             CV_Error( CV_BadNumChannels, "cvGetReal* support only single-channel arrays" );
   2128 
   2129         value = icvGetReal( ptr, type );
   2130     }
   2131 
   2132     return value;
   2133 }
   2134 
   2135 
   2136 // Returns specifed element of nD array
   2137 CV_IMPL  double
   2138 cvGetRealND( const CvArr* arr, const int* idx )
   2139 {
   2140     double value = 0;
   2141     int type = 0;
   2142     uchar* ptr;
   2143 
   2144     if( !CV_IS_SPARSE_MAT( arr ))
   2145         ptr = cvPtrND( arr, idx, &type );
   2146     else
   2147         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, 0, 0 );
   2148 
   2149     if( ptr )
   2150     {
   2151         if( CV_MAT_CN( type ) > 1 )
   2152             CV_Error( CV_BadNumChannels, "cvGetReal* support only single-channel arrays" );
   2153 
   2154         value = icvGetReal( ptr, type );
   2155     }
   2156 
   2157     return value;
   2158 }
   2159 
   2160 
   2161 // Assigns new value to specifed element of nD array given linear index
   2162 CV_IMPL  void
   2163 cvSet1D( CvArr* arr, int idx, CvScalar scalar )
   2164 {
   2165     int type = 0;
   2166     uchar* ptr;
   2167 
   2168     if( CV_IS_MAT( arr ) && CV_IS_MAT_CONT( ((CvMat*)arr)->type ))
   2169     {
   2170         CvMat* mat = (CvMat*)arr;
   2171 
   2172         type = CV_MAT_TYPE(mat->type);
   2173         int pix_size = CV_ELEM_SIZE(type);
   2174 
   2175         // the first part is mul-free sufficient check
   2176         // that the index is within the matrix
   2177         if( (unsigned)idx >= (unsigned)(mat->rows + mat->cols - 1) &&
   2178             (unsigned)idx >= (unsigned)(mat->rows*mat->cols))
   2179             CV_Error( CV_StsOutOfRange, "index is out of range" );
   2180 
   2181         ptr = mat->data.ptr + (size_t)idx*pix_size;
   2182     }
   2183     else if( !CV_IS_SPARSE_MAT( arr ) || ((CvSparseMat*)arr)->dims > 1 )
   2184         ptr = cvPtr1D( arr, idx, &type );
   2185     else
   2186         ptr = icvGetNodePtr( (CvSparseMat*)arr, &idx, &type, -1, 0 );
   2187 
   2188     cvScalarToRawData( &scalar, ptr, type );
   2189 }
   2190 
   2191 
   2192 // Assigns new value to specifed element of 2D array
   2193 CV_IMPL  void
   2194 cvSet2D( CvArr* arr, int y, int x, CvScalar scalar )
   2195 {
   2196     int type = 0;
   2197     uchar* ptr;
   2198 
   2199     if( CV_IS_MAT( arr ))
   2200     {
   2201         CvMat* mat = (CvMat*)arr;
   2202 
   2203         if( (unsigned)y >= (unsigned)(mat->rows) ||
   2204             (unsigned)x >= (unsigned)(mat->cols) )
   2205             CV_Error( CV_StsOutOfRange, "index is out of range" );
   2206 
   2207         type = CV_MAT_TYPE(mat->type);
   2208         ptr = mat->data.ptr + (size_t)y*mat->step + x*CV_ELEM_SIZE(type);
   2209     }
   2210     else if( !CV_IS_SPARSE_MAT( arr ))
   2211         ptr = cvPtr2D( arr, y, x, &type );
   2212     else
   2213     {
   2214         int idx[] = { y, x };
   2215         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, -1, 0 );
   2216     }
   2217     cvScalarToRawData( &scalar, ptr, type );
   2218 }
   2219 
   2220 
   2221 // Assigns new value to specifed element of 3D array
   2222 CV_IMPL  void
   2223 cvSet3D( CvArr* arr, int z, int y, int x, CvScalar scalar )
   2224 {
   2225     int type = 0;
   2226     uchar* ptr;
   2227 
   2228     if( !CV_IS_SPARSE_MAT( arr ))
   2229         ptr = cvPtr3D( arr, z, y, x, &type );
   2230     else
   2231     {
   2232         int idx[] = { z, y, x };
   2233         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, -1, 0 );
   2234     }
   2235     cvScalarToRawData( &scalar, ptr, type );
   2236 }
   2237 
   2238 
   2239 // Assigns new value to specifed element of nD array
   2240 CV_IMPL  void
   2241 cvSetND( CvArr* arr, const int* idx, CvScalar scalar )
   2242 {
   2243     int type = 0;
   2244     uchar* ptr;
   2245 
   2246     if( !CV_IS_SPARSE_MAT( arr ))
   2247         ptr = cvPtrND( arr, idx, &type );
   2248     else
   2249         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, -1, 0 );
   2250     cvScalarToRawData( &scalar, ptr, type );
   2251 }
   2252 
   2253 
   2254 CV_IMPL  void
   2255 cvSetReal1D( CvArr* arr, int idx, double value )
   2256 {
   2257     int type = 0;
   2258     uchar* ptr;
   2259 
   2260     if( CV_IS_MAT( arr ) && CV_IS_MAT_CONT( ((CvMat*)arr)->type ))
   2261     {
   2262         CvMat* mat = (CvMat*)arr;
   2263 
   2264         type = CV_MAT_TYPE(mat->type);
   2265         int pix_size = CV_ELEM_SIZE(type);
   2266 
   2267         // the first part is mul-free sufficient check
   2268         // that the index is within the matrix
   2269         if( (unsigned)idx >= (unsigned)(mat->rows + mat->cols - 1) &&
   2270             (unsigned)idx >= (unsigned)(mat->rows*mat->cols))
   2271             CV_Error( CV_StsOutOfRange, "index is out of range" );
   2272 
   2273         ptr = mat->data.ptr + (size_t)idx*pix_size;
   2274     }
   2275     else if( !CV_IS_SPARSE_MAT( arr ) || ((CvSparseMat*)arr)->dims > 1 )
   2276         ptr = cvPtr1D( arr, idx, &type );
   2277     else
   2278         ptr = icvGetNodePtr( (CvSparseMat*)arr, &idx, &type, -1, 0 );
   2279 
   2280     if( CV_MAT_CN( type ) > 1 )
   2281         CV_Error( CV_BadNumChannels, "cvSetReal* support only single-channel arrays" );
   2282 
   2283     if( ptr )
   2284         icvSetReal( value, ptr, type );
   2285 }
   2286 
   2287 
   2288 CV_IMPL  void
   2289 cvSetReal2D( CvArr* arr, int y, int x, double value )
   2290 {
   2291     int type = 0;
   2292     uchar* ptr;
   2293 
   2294     if( CV_IS_MAT( arr ))
   2295     {
   2296         CvMat* mat = (CvMat*)arr;
   2297 
   2298         if( (unsigned)y >= (unsigned)(mat->rows) ||
   2299             (unsigned)x >= (unsigned)(mat->cols) )
   2300             CV_Error( CV_StsOutOfRange, "index is out of range" );
   2301 
   2302         type = CV_MAT_TYPE(mat->type);
   2303         ptr = mat->data.ptr + (size_t)y*mat->step + x*CV_ELEM_SIZE(type);
   2304     }
   2305     else if( !CV_IS_SPARSE_MAT( arr ))
   2306     {
   2307         ptr = cvPtr2D( arr, y, x, &type );
   2308     }
   2309     else
   2310     {
   2311         int idx[] = { y, x };
   2312         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, -1, 0 );
   2313     }
   2314     if( CV_MAT_CN( type ) > 1 )
   2315         CV_Error( CV_BadNumChannels, "cvSetReal* support only single-channel arrays" );
   2316 
   2317     if( ptr )
   2318         icvSetReal( value, ptr, type );
   2319 }
   2320 
   2321 
   2322 CV_IMPL  void
   2323 cvSetReal3D( CvArr* arr, int z, int y, int x, double value )
   2324 {
   2325     int type = 0;
   2326     uchar* ptr;
   2327 
   2328     if( !CV_IS_SPARSE_MAT( arr ))
   2329         ptr = cvPtr3D( arr, z, y, x, &type );
   2330     else
   2331     {
   2332         int idx[] = { z, y, x };
   2333         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, -1, 0 );
   2334     }
   2335     if( CV_MAT_CN( type ) > 1 )
   2336         CV_Error( CV_BadNumChannels, "cvSetReal* support only single-channel arrays" );
   2337 
   2338     if( ptr )
   2339         icvSetReal( value, ptr, type );
   2340 }
   2341 
   2342 
   2343 CV_IMPL  void
   2344 cvSetRealND( CvArr* arr, const int* idx, double value )
   2345 {
   2346     int type = 0;
   2347     uchar* ptr;
   2348 
   2349     if( !CV_IS_SPARSE_MAT( arr ))
   2350         ptr = cvPtrND( arr, idx, &type );
   2351     else
   2352         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, -1, 0 );
   2353 
   2354     if( CV_MAT_CN( type ) > 1 )
   2355         CV_Error( CV_BadNumChannels, "cvSetReal* support only single-channel arrays" );
   2356 
   2357     if( ptr )
   2358         icvSetReal( value, ptr, type );
   2359 }
   2360 
   2361 
   2362 CV_IMPL void
   2363 cvClearND( CvArr* arr, const int* idx )
   2364 {
   2365     if( !CV_IS_SPARSE_MAT( arr ))
   2366     {
   2367         int type;
   2368         uchar* ptr;
   2369         ptr = cvPtrND( arr, idx, &type );
   2370         if( ptr )
   2371             memset( ptr, 0, CV_ELEM_SIZE(type) );
   2372     }
   2373     else
   2374         icvDeleteNode( (CvSparseMat*)arr, idx, 0 );
   2375 }
   2376 
   2377 
   2378 /****************************************************************************************\
   2379 *                             Conversion to CvMat or IplImage                            *
   2380 \****************************************************************************************/
   2381 
   2382 // convert array (CvMat or IplImage) to CvMat
   2383 CV_IMPL CvMat*
   2384 cvGetMat( const CvArr* array, CvMat* mat,
   2385           int* pCOI, int allowND )
   2386 {
   2387     CvMat* result = 0;
   2388     CvMat* src = (CvMat*)array;
   2389     int coi = 0;
   2390 
   2391     if( !mat || !src )
   2392         CV_Error( CV_StsNullPtr, "NULL array pointer is passed" );
   2393 
   2394     if( CV_IS_MAT_HDR(src))
   2395     {
   2396         if( !src->data.ptr )
   2397             CV_Error( CV_StsNullPtr, "The matrix has NULL data pointer" );
   2398 
   2399         result = (CvMat*)src;
   2400     }
   2401     else if( CV_IS_IMAGE_HDR(src) )
   2402     {
   2403         const IplImage* img = (const IplImage*)src;
   2404         int depth, order;
   2405 
   2406         if( img->imageData == 0 )
   2407             CV_Error( CV_StsNullPtr, "The image has NULL data pointer" );
   2408 
   2409         depth = IPL2CV_DEPTH( img->depth );
   2410         if( depth < 0 )
   2411             CV_Error( CV_BadDepth, "" );
   2412 
   2413         order = img->dataOrder & (img->nChannels > 1 ? -1 : 0);
   2414 
   2415         if( img->roi )
   2416         {
   2417             if( order == IPL_DATA_ORDER_PLANE )
   2418             {
   2419                 int type = depth;
   2420 
   2421                 if( img->roi->coi == 0 )
   2422                     CV_Error( CV_StsBadFlag,
   2423                     "Images with planar data layout should be used with COI selected" );
   2424 
   2425                 cvInitMatHeader( mat, img->roi->height,
   2426                                 img->roi->width, type,
   2427                                 img->imageData + (img->roi->coi-1)*img->imageSize +
   2428                                 img->roi->yOffset*img->widthStep +
   2429                                 img->roi->xOffset*CV_ELEM_SIZE(type),
   2430                                 img->widthStep );
   2431             }
   2432             else /* pixel order */
   2433             {
   2434                 int type = CV_MAKETYPE( depth, img->nChannels );
   2435                 coi = img->roi->coi;
   2436 
   2437                 if( img->nChannels > CV_CN_MAX )
   2438                     CV_Error( CV_BadNumChannels,
   2439                         "The image is interleaved and has over CV_CN_MAX channels" );
   2440 
   2441                 cvInitMatHeader( mat, img->roi->height, img->roi->width,
   2442                                  type, img->imageData +
   2443                                  img->roi->yOffset*img->widthStep +
   2444                                  img->roi->xOffset*CV_ELEM_SIZE(type),
   2445                                  img->widthStep );
   2446             }
   2447         }
   2448         else
   2449         {
   2450             int type = CV_MAKETYPE( depth, img->nChannels );
   2451 
   2452             if( order != IPL_DATA_ORDER_PIXEL )
   2453                 CV_Error( CV_StsBadFlag, "Pixel order should be used with coi == 0" );
   2454 
   2455             cvInitMatHeader( mat, img->height, img->width, type,
   2456                              img->imageData, img->widthStep );
   2457         }
   2458 
   2459         result = mat;
   2460     }
   2461     else if( allowND && CV_IS_MATND_HDR(src) )
   2462     {
   2463         CvMatND* matnd = (CvMatND*)src;
   2464         int size1 = matnd->dim[0].size, size2 = 1;
   2465 
   2466         if( !src->data.ptr )
   2467             CV_Error( CV_StsNullPtr, "Input array has NULL data pointer" );
   2468 
   2469         if( !CV_IS_MAT_CONT( matnd->type ))
   2470             CV_Error( CV_StsBadArg, "Only continuous nD arrays are supported here" );
   2471 
   2472         if( matnd->dims > 2 )
   2473         {
   2474             int i;
   2475             for( i = 1; i < matnd->dims; i++ )
   2476                 size2 *= matnd->dim[i].size;
   2477         }
   2478         else
   2479             size2 = matnd->dims == 1 ? 1 : matnd->dim[1].size;
   2480 
   2481         mat->refcount = 0;
   2482         mat->hdr_refcount = 0;
   2483         mat->data.ptr = matnd->data.ptr;
   2484         mat->rows = size1;
   2485         mat->cols = size2;
   2486         mat->type = CV_MAT_TYPE(matnd->type) | CV_MAT_MAGIC_VAL | CV_MAT_CONT_FLAG;
   2487         mat->step = size2*CV_ELEM_SIZE(matnd->type);
   2488         mat->step &= size1 > 1 ? -1 : 0;
   2489 
   2490         icvCheckHuge( mat );
   2491         result = mat;
   2492     }
   2493     else
   2494         CV_Error( CV_StsBadFlag, "Unrecognized or unsupported array type" );
   2495 
   2496     if( pCOI )
   2497         *pCOI = coi;
   2498 
   2499     return result;
   2500 }
   2501 
   2502 
   2503 CV_IMPL CvArr*
   2504 cvReshapeMatND( const CvArr* arr,
   2505                 int sizeof_header, CvArr* _header,
   2506                 int new_cn, int new_dims, int* new_sizes )
   2507 {
   2508     CvArr* result = 0;
   2509     int dims, coi = 0;
   2510 
   2511     if( !arr || !_header )
   2512         CV_Error( CV_StsNullPtr, "NULL pointer to array or destination header" );
   2513 
   2514     if( new_cn == 0 && new_dims == 0 )
   2515         CV_Error( CV_StsBadArg, "None of array parameters is changed: dummy call?" );
   2516 
   2517     dims = cvGetDims( arr );
   2518 
   2519     if( new_dims == 0 )
   2520     {
   2521         new_sizes = 0;
   2522         new_dims = dims;
   2523     }
   2524     else if( new_dims == 1 )
   2525     {
   2526         new_sizes = 0;
   2527     }
   2528     else
   2529     {
   2530         if( new_dims <= 0 || new_dims > CV_MAX_DIM )
   2531             CV_Error( CV_StsOutOfRange, "Non-positive or too large number of dimensions" );
   2532         if( !new_sizes )
   2533             CV_Error( CV_StsNullPtr, "New dimension sizes are not specified" );
   2534     }
   2535 
   2536     if( new_dims <= 2 )
   2537     {
   2538         CvMat* mat = (CvMat*)arr;
   2539         CvMat header;
   2540         int* refcount = 0;
   2541         int  hdr_refcount = 0;
   2542         int  total_width, new_rows, cn;
   2543 
   2544         if( sizeof_header != sizeof(CvMat) && sizeof_header != sizeof(CvMatND) )
   2545             CV_Error( CV_StsBadArg, "The output header should be CvMat or CvMatND" );
   2546 
   2547         if( mat == (CvMat*)_header )
   2548         {
   2549             refcount = mat->refcount;
   2550             hdr_refcount = mat->hdr_refcount;
   2551         }
   2552 
   2553         if( !CV_IS_MAT( mat ))
   2554             mat = cvGetMat( mat, &header, &coi, 1 );
   2555 
   2556         cn = CV_MAT_CN( mat->type );
   2557         total_width = mat->cols * cn;
   2558 
   2559         if( new_cn == 0 )
   2560             new_cn = cn;
   2561 
   2562         if( new_sizes )
   2563             new_rows = new_sizes[0];
   2564         else if( new_dims == 1 )
   2565             new_rows = total_width*mat->rows/new_cn;
   2566         else
   2567         {
   2568             new_rows = mat->rows;
   2569             if( new_cn > total_width )
   2570                 new_rows = mat->rows * total_width / new_cn;
   2571         }
   2572 
   2573         if( new_rows != mat->rows )
   2574         {
   2575             int total_size = total_width * mat->rows;
   2576 
   2577             if( !CV_IS_MAT_CONT( mat->type ))
   2578                 CV_Error( CV_BadStep,
   2579                 "The matrix is not continuous so the number of rows can not be changed" );
   2580 
   2581             total_width = total_size / new_rows;
   2582 
   2583             if( total_width * new_rows != total_size )
   2584                 CV_Error( CV_StsBadArg, "The total number of matrix elements "
   2585                                         "is not divisible by the new number of rows" );
   2586         }
   2587 
   2588         header.rows = new_rows;
   2589         header.cols = total_width / new_cn;
   2590 
   2591         if( header.cols * new_cn != total_width ||
   2592             (new_sizes && header.cols != new_sizes[1]) )
   2593             CV_Error( CV_StsBadArg, "The total matrix width is not "
   2594                             "divisible by the new number of columns" );
   2595 
   2596         header.type = (mat->type & ~CV_MAT_TYPE_MASK) | CV_MAKETYPE(mat->type, new_cn);
   2597         header.step = header.cols * CV_ELEM_SIZE(mat->type);
   2598         header.step &= new_rows > 1 ? -1 : 0;
   2599         header.refcount = refcount;
   2600         header.hdr_refcount = hdr_refcount;
   2601 
   2602         if( sizeof_header == sizeof(CvMat) )
   2603             *(CvMat*)_header = header;
   2604         else
   2605         {
   2606             CvMatND* __header = (CvMatND*)_header;
   2607             cvGetMatND(&header, __header, 0);
   2608             if( new_dims > 0 )
   2609                 __header->dims = new_dims;
   2610         }
   2611     }
   2612     else
   2613     {
   2614         CvMatND* header = (CvMatND*)_header;
   2615 
   2616         if( sizeof_header != sizeof(CvMatND))
   2617             CV_Error( CV_StsBadSize, "The output header should be CvMatND" );
   2618 
   2619         if( !new_sizes )
   2620         {
   2621             if( !CV_IS_MATND( arr ))
   2622                 CV_Error( CV_StsBadArg, "The input array must be CvMatND" );
   2623 
   2624             {
   2625             CvMatND* mat = (CvMatND*)arr;
   2626             assert( new_cn > 0 );
   2627             int last_dim_size = mat->dim[mat->dims-1].size*CV_MAT_CN(mat->type);
   2628             int new_size = last_dim_size/new_cn;
   2629 
   2630             if( new_size*new_cn != last_dim_size )
   2631                 CV_Error( CV_StsBadArg,
   2632                 "The last dimension full size is not divisible by new number of channels");
   2633 
   2634             if( mat != header )
   2635             {
   2636                 memcpy( header, mat, sizeof(*header));
   2637                 header->refcount = 0;
   2638                 header->hdr_refcount = 0;
   2639             }
   2640 
   2641             header->dim[header->dims-1].size = new_size;
   2642             header->type = (header->type & ~CV_MAT_TYPE_MASK) | CV_MAKETYPE(header->type, new_cn);
   2643             }
   2644         }
   2645         else
   2646         {
   2647             CvMatND stub;
   2648             CvMatND* mat = (CvMatND*)arr;
   2649             int i, size1, size2;
   2650             int step;
   2651 
   2652             if( new_cn != 0 )
   2653                 CV_Error( CV_StsBadArg,
   2654                 "Simultaneous change of shape and number of channels is not supported. "
   2655                 "Do it by 2 separate calls" );
   2656 
   2657             if( !CV_IS_MATND( mat ))
   2658             {
   2659                 cvGetMatND( mat, &stub, &coi );
   2660                 mat = &stub;
   2661             }
   2662 
   2663             if( CV_IS_MAT_CONT( mat->type ))
   2664                 CV_Error( CV_StsBadArg, "Non-continuous nD arrays are not supported" );
   2665 
   2666             size1 = mat->dim[0].size;
   2667             for( i = 1; i < dims; i++ )
   2668                 size1 *= mat->dim[i].size;
   2669 
   2670             size2 = 1;
   2671             for( i = 0; i < new_dims; i++ )
   2672             {
   2673                 if( new_sizes[i] <= 0 )
   2674                     CV_Error( CV_StsBadSize,
   2675                     "One of new dimension sizes is non-positive" );
   2676                 size2 *= new_sizes[i];
   2677             }
   2678 
   2679             if( size1 != size2 )
   2680                 CV_Error( CV_StsBadSize,
   2681                 "Number of elements in the original and reshaped array is different" );
   2682 
   2683             if( header != mat )
   2684             {
   2685                 header->refcount = 0;
   2686                 header->hdr_refcount = 0;
   2687             }
   2688 
   2689             header->dims = new_dims;
   2690             header->type = mat->type;
   2691             header->data.ptr = mat->data.ptr;
   2692             step = CV_ELEM_SIZE(header->type);
   2693 
   2694             for( i = new_dims - 1; i >= 0; i-- )
   2695             {
   2696                 header->dim[i].size = new_sizes[i];
   2697                 header->dim[i].step = step;
   2698                 step *= new_sizes[i];
   2699             }
   2700         }
   2701     }
   2702 
   2703     if( coi )
   2704         CV_Error( CV_BadCOI, "COI is not supported by this operation" );
   2705 
   2706     result = _header;
   2707     return result;
   2708 }
   2709 
   2710 
   2711 CV_IMPL CvMat*
   2712 cvReshape( const CvArr* array, CvMat* header,
   2713            int new_cn, int new_rows )
   2714 {
   2715     CvMat* result = 0;
   2716     CvMat *mat = (CvMat*)array;
   2717     int total_width, new_width;
   2718 
   2719     if( !header )
   2720         CV_Error( CV_StsNullPtr, "" );
   2721 
   2722     if( !CV_IS_MAT( mat ))
   2723     {
   2724         int coi = 0;
   2725         mat = cvGetMat( mat, header, &coi, 1 );
   2726         if( coi )
   2727             CV_Error( CV_BadCOI, "COI is not supported" );
   2728     }
   2729 
   2730     if( new_cn == 0 )
   2731         new_cn = CV_MAT_CN(mat->type);
   2732     else if( (unsigned)(new_cn - 1) > 3 )
   2733         CV_Error( CV_BadNumChannels, "" );
   2734 
   2735     if( mat != header )
   2736     {
   2737         int hdr_refcount = header->hdr_refcount;
   2738         *header = *mat;
   2739         header->refcount = 0;
   2740         header->hdr_refcount = hdr_refcount;
   2741     }
   2742 
   2743     total_width = mat->cols * CV_MAT_CN( mat->type );
   2744 
   2745     if( (new_cn > total_width || total_width % new_cn != 0) && new_rows == 0 )
   2746         new_rows = mat->rows * total_width / new_cn;
   2747 
   2748     if( new_rows == 0 || new_rows == mat->rows )
   2749     {
   2750         header->rows = mat->rows;
   2751         header->step = mat->step;
   2752     }
   2753     else
   2754     {
   2755         int total_size = total_width * mat->rows;
   2756         if( !CV_IS_MAT_CONT( mat->type ))
   2757             CV_Error( CV_BadStep,
   2758             "The matrix is not continuous, thus its number of rows can not be changed" );
   2759 
   2760         if( (unsigned)new_rows > (unsigned)total_size )
   2761             CV_Error( CV_StsOutOfRange, "Bad new number of rows" );
   2762 
   2763         total_width = total_size / new_rows;
   2764 
   2765         if( total_width * new_rows != total_size )
   2766             CV_Error( CV_StsBadArg, "The total number of matrix elements "
   2767                                     "is not divisible by the new number of rows" );
   2768 
   2769         header->rows = new_rows;
   2770         header->step = total_width * CV_ELEM_SIZE1(mat->type);
   2771     }
   2772 
   2773     new_width = total_width / new_cn;
   2774 
   2775     if( new_width * new_cn != total_width )
   2776         CV_Error( CV_BadNumChannels,
   2777         "The total width is not divisible by the new number of channels" );
   2778 
   2779     header->cols = new_width;
   2780     header->type = (mat->type  & ~CV_MAT_TYPE_MASK) | CV_MAKETYPE(mat->type, new_cn);
   2781 
   2782     result = header;
   2783     return  result;
   2784 }
   2785 
   2786 
   2787 // convert array (CvMat or IplImage) to IplImage
   2788 CV_IMPL IplImage*
   2789 cvGetImage( const CvArr* array, IplImage* img )
   2790 {
   2791     IplImage* result = 0;
   2792     const IplImage* src = (const IplImage*)array;
   2793 
   2794     if( !img )
   2795         CV_Error( CV_StsNullPtr, "" );
   2796 
   2797     if( !CV_IS_IMAGE_HDR(src) )
   2798     {
   2799         const CvMat* mat = (const CvMat*)src;
   2800 
   2801         if( !CV_IS_MAT_HDR(mat))
   2802             CV_Error( CV_StsBadFlag, "" );
   2803 
   2804         if( mat->data.ptr == 0 )
   2805             CV_Error( CV_StsNullPtr, "" );
   2806 
   2807         int depth = cvIplDepth(mat->type);
   2808 
   2809         cvInitImageHeader( img, cvSize(mat->cols, mat->rows),
   2810                            depth, CV_MAT_CN(mat->type) );
   2811         cvSetData( img, mat->data.ptr, mat->step );
   2812 
   2813         result = img;
   2814     }
   2815     else
   2816     {
   2817         result = (IplImage*)src;
   2818     }
   2819 
   2820     return result;
   2821 }
   2822 
   2823 
   2824 /****************************************************************************************\
   2825 *                               IplImage-specific functions                              *
   2826 \****************************************************************************************/
   2827 
   2828 static IplROI* icvCreateROI( int coi, int xOffset, int yOffset, int width, int height )
   2829 {
   2830     IplROI *roi = 0;
   2831     if( !CvIPL.createROI )
   2832     {
   2833         roi = (IplROI*)cvAlloc( sizeof(*roi));
   2834 
   2835         roi->coi = coi;
   2836         roi->xOffset = xOffset;
   2837         roi->yOffset = yOffset;
   2838         roi->width = width;
   2839         roi->height = height;
   2840     }
   2841     else
   2842     {
   2843         roi = CvIPL.createROI( coi, xOffset, yOffset, width, height );
   2844     }
   2845 
   2846     return roi;
   2847 }
   2848 
   2849 static  void
   2850 icvGetColorModel( int nchannels, const char** colorModel, const char** channelSeq )
   2851 {
   2852     static const char* tab[][2] =
   2853     {
   2854         {"GRAY", "GRAY"},
   2855         {"",""},
   2856         {"RGB","BGR"},
   2857         {"RGB","BGRA"}
   2858     };
   2859 
   2860     nchannels--;
   2861     *colorModel = *channelSeq = "";
   2862 
   2863     if( (unsigned)nchannels <= 3 )
   2864     {
   2865         *colorModel = tab[nchannels][0];
   2866         *channelSeq = tab[nchannels][1];
   2867     }
   2868 }
   2869 
   2870 
   2871 // create IplImage header
   2872 CV_IMPL IplImage *
   2873 cvCreateImageHeader( CvSize size, int depth, int channels )
   2874 {
   2875     IplImage *img = 0;
   2876 
   2877     if( !CvIPL.createHeader )
   2878     {
   2879         img = (IplImage *)cvAlloc( sizeof( *img ));
   2880         cvInitImageHeader( img, size, depth, channels, IPL_ORIGIN_TL,
   2881                                     CV_DEFAULT_IMAGE_ROW_ALIGN );
   2882     }
   2883     else
   2884     {
   2885         const char *colorModel, *channelSeq;
   2886 
   2887         icvGetColorModel( channels, &colorModel, &channelSeq );
   2888 
   2889         img = CvIPL.createHeader( channels, 0, depth, (char*)colorModel, (char*)channelSeq,
   2890                                   IPL_DATA_ORDER_PIXEL, IPL_ORIGIN_TL,
   2891                                   CV_DEFAULT_IMAGE_ROW_ALIGN,
   2892                                   size.width, size.height, 0, 0, 0, 0 );
   2893     }
   2894 
   2895     return img;
   2896 }
   2897 
   2898 
   2899 // create IplImage header and allocate underlying data
   2900 CV_IMPL IplImage *
   2901 cvCreateImage( CvSize size, int depth, int channels )
   2902 {
   2903     IplImage *img = cvCreateImageHeader( size, depth, channels );
   2904     assert( img );
   2905     cvCreateData( img );
   2906 
   2907     return img;
   2908 }
   2909 
   2910 
   2911 // initialize IplImage header, allocated by the user
   2912 CV_IMPL IplImage*
   2913 cvInitImageHeader( IplImage * image, CvSize size, int depth,
   2914                    int channels, int origin, int align )
   2915 {
   2916     const char *colorModel, *channelSeq;
   2917 
   2918     if( !image )
   2919         CV_Error( CV_HeaderIsNull, "null pointer to header" );
   2920 
   2921     memset( image, 0, sizeof( *image ));
   2922     image->nSize = sizeof( *image );
   2923 
   2924     icvGetColorModel( channels, &colorModel, &channelSeq );
   2925     strncpy( image->colorModel, colorModel, 4 );
   2926     strncpy( image->channelSeq, channelSeq, 4 );
   2927 
   2928     if( size.width < 0 || size.height < 0 )
   2929         CV_Error( CV_BadROISize, "Bad input roi" );
   2930 
   2931     if( (depth != (int)IPL_DEPTH_1U && depth != (int)IPL_DEPTH_8U &&
   2932          depth != (int)IPL_DEPTH_8S && depth != (int)IPL_DEPTH_16U &&
   2933          depth != (int)IPL_DEPTH_16S && depth != (int)IPL_DEPTH_32S &&
   2934          depth != (int)IPL_DEPTH_32F && depth != (int)IPL_DEPTH_64F) ||
   2935          channels < 0 )
   2936         CV_Error( CV_BadDepth, "Unsupported format" );
   2937     if( origin != CV_ORIGIN_BL && origin != CV_ORIGIN_TL )
   2938         CV_Error( CV_BadOrigin, "Bad input origin" );
   2939 
   2940     if( align != 4 && align != 8 )
   2941         CV_Error( CV_BadAlign, "Bad input align" );
   2942 
   2943     image->width = size.width;
   2944     image->height = size.height;
   2945 
   2946     if( image->roi )
   2947     {
   2948         image->roi->coi = 0;
   2949         image->roi->xOffset = image->roi->yOffset = 0;
   2950         image->roi->width = size.width;
   2951         image->roi->height = size.height;
   2952     }
   2953 
   2954     image->nChannels = MAX( channels, 1 );
   2955     image->depth = depth;
   2956     image->align = align;
   2957     image->widthStep = (((image->width * image->nChannels *
   2958          (image->depth & ~IPL_DEPTH_SIGN) + 7)/8)+ align - 1) & (~(align - 1));
   2959     image->origin = origin;
   2960     image->imageSize = image->widthStep * image->height;
   2961 
   2962     return image;
   2963 }
   2964 
   2965 
   2966 CV_IMPL void
   2967 cvReleaseImageHeader( IplImage** image )
   2968 {
   2969     if( !image )
   2970         CV_Error( CV_StsNullPtr, "" );
   2971 
   2972     if( *image )
   2973     {
   2974         IplImage* img = *image;
   2975         *image = 0;
   2976 
   2977         if( !CvIPL.deallocate )
   2978         {
   2979             cvFree( &img->roi );
   2980             cvFree( &img );
   2981         }
   2982         else
   2983         {
   2984             CvIPL.deallocate( img, IPL_IMAGE_HEADER | IPL_IMAGE_ROI );
   2985         }
   2986     }
   2987 }
   2988 
   2989 
   2990 CV_IMPL void
   2991 cvReleaseImage( IplImage ** image )
   2992 {
   2993     if( !image )
   2994         CV_Error( CV_StsNullPtr, "" );
   2995 
   2996     if( *image )
   2997     {
   2998         IplImage* img = *image;
   2999         *image = 0;
   3000 
   3001         cvReleaseData( img );
   3002         cvReleaseImageHeader( &img );
   3003     }
   3004 }
   3005 
   3006 
   3007 CV_IMPL void
   3008 cvSetImageROI( IplImage* image, CvRect rect )
   3009 {
   3010     if( !image )
   3011         CV_Error( CV_HeaderIsNull, "" );
   3012 
   3013     // allow zero ROI width or height
   3014     CV_Assert( rect.width >= 0 && rect.height >= 0 &&
   3015                rect.x < image->width && rect.y < image->height &&
   3016                rect.x + rect.width >= (int)(rect.width > 0) &&
   3017                rect.y + rect.height >= (int)(rect.height > 0) );
   3018 
   3019     rect.width += rect.x;
   3020     rect.height += rect.y;
   3021 
   3022     rect.x = std::max(rect.x, 0);
   3023     rect.y = std::max(rect.y, 0);
   3024     rect.width = std::min(rect.width, image->width);
   3025     rect.height = std::min(rect.height, image->height);
   3026 
   3027     rect.width -= rect.x;
   3028     rect.height -= rect.y;
   3029 
   3030     if( image->roi )
   3031     {
   3032         image->roi->xOffset = rect.x;
   3033         image->roi->yOffset = rect.y;
   3034         image->roi->width = rect.width;
   3035         image->roi->height = rect.height;
   3036     }
   3037     else
   3038         image->roi = icvCreateROI( 0, rect.x, rect.y, rect.width, rect.height );
   3039 }
   3040 
   3041 
   3042 CV_IMPL void
   3043 cvResetImageROI( IplImage* image )
   3044 {
   3045     if( !image )
   3046         CV_Error( CV_HeaderIsNull, "" );
   3047 
   3048     if( image->roi )
   3049     {
   3050         if( !CvIPL.deallocate )
   3051         {
   3052             cvFree( &image->roi );
   3053         }
   3054         else
   3055         {
   3056             CvIPL.deallocate( image, IPL_IMAGE_ROI );
   3057             image->roi = 0;
   3058         }
   3059     }
   3060 }
   3061 
   3062 
   3063 CV_IMPL CvRect
   3064 cvGetImageROI( const IplImage* img )
   3065 {
   3066     CvRect rect;
   3067     if( !img )
   3068         CV_Error( CV_StsNullPtr, "Null pointer to image" );
   3069 
   3070     if( img->roi )
   3071         rect = cvRect( img->roi->xOffset, img->roi->yOffset,
   3072                        img->roi->width, img->roi->height );
   3073     else
   3074         rect = cvRect( 0, 0, img->width, img->height );
   3075 
   3076     return rect;
   3077 }
   3078 
   3079 
   3080 CV_IMPL void
   3081 cvSetImageCOI( IplImage* image, int coi )
   3082 {
   3083     if( !image )
   3084         CV_Error( CV_HeaderIsNull, "" );
   3085 
   3086     if( (unsigned)coi > (unsigned)(image->nChannels) )
   3087         CV_Error( CV_BadCOI, "" );
   3088 
   3089     if( image->roi || coi != 0 )
   3090     {
   3091         if( image->roi )
   3092         {
   3093             image->roi->coi = coi;
   3094         }
   3095         else
   3096         {
   3097             image->roi = icvCreateROI( coi, 0, 0, image->width, image->height );
   3098         }
   3099     }
   3100 }
   3101 
   3102 
   3103 CV_IMPL int
   3104 cvGetImageCOI( const IplImage* image )
   3105 {
   3106     if( !image )
   3107         CV_Error( CV_HeaderIsNull, "" );
   3108 
   3109     return image->roi ? image->roi->coi : 0;
   3110 }
   3111 
   3112 
   3113 CV_IMPL IplImage*
   3114 cvCloneImage( const IplImage* src )
   3115 {
   3116     IplImage* dst = 0;
   3117 
   3118     if( !CV_IS_IMAGE_HDR( src ))
   3119         CV_Error( CV_StsBadArg, "Bad image header" );
   3120 
   3121     if( !CvIPL.cloneImage )
   3122     {
   3123         dst = (IplImage*)cvAlloc( sizeof(*dst));
   3124 
   3125         memcpy( dst, src, sizeof(*src));
   3126         dst->imageData = dst->imageDataOrigin = 0;
   3127         dst->roi = 0;
   3128 
   3129         if( src->roi )
   3130         {
   3131             dst->roi = icvCreateROI( src->roi->coi, src->roi->xOffset,
   3132                           src->roi->yOffset, src->roi->width, src->roi->height );
   3133         }
   3134 
   3135         if( src->imageData )
   3136         {
   3137             int size = src->imageSize;
   3138             cvCreateData( dst );
   3139             memcpy( dst->imageData, src->imageData, size );
   3140         }
   3141     }
   3142     else
   3143         dst = CvIPL.cloneImage( src );
   3144 
   3145     return dst;
   3146 }
   3147 
   3148 
   3149 /****************************************************************************************\
   3150 *                            Additional operations on CvTermCriteria                     *
   3151 \****************************************************************************************/
   3152 
   3153 CV_IMPL CvTermCriteria
   3154 cvCheckTermCriteria( CvTermCriteria criteria, double default_eps,
   3155                      int default_max_iters )
   3156 {
   3157     CvTermCriteria crit;
   3158 
   3159     crit.type = CV_TERMCRIT_ITER|CV_TERMCRIT_EPS;
   3160     crit.max_iter = default_max_iters;
   3161     crit.epsilon = (float)default_eps;
   3162 
   3163     if( (criteria.type & ~(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER)) != 0 )
   3164         CV_Error( CV_StsBadArg,
   3165                   "Unknown type of term criteria" );
   3166 
   3167     if( (criteria.type & CV_TERMCRIT_ITER) != 0 )
   3168     {
   3169         if( criteria.max_iter <= 0 )
   3170             CV_Error( CV_StsBadArg,
   3171                   "Iterations flag is set and maximum number of iterations is <= 0" );
   3172         crit.max_iter = criteria.max_iter;
   3173     }
   3174 
   3175     if( (criteria.type & CV_TERMCRIT_EPS) != 0 )
   3176     {
   3177         if( criteria.epsilon < 0 )
   3178             CV_Error( CV_StsBadArg, "Accuracy flag is set and epsilon is < 0" );
   3179 
   3180         crit.epsilon = criteria.epsilon;
   3181     }
   3182 
   3183     if( (criteria.type & (CV_TERMCRIT_EPS | CV_TERMCRIT_ITER)) == 0 )
   3184         CV_Error( CV_StsBadArg,
   3185                   "Neither accuracy nor maximum iterations "
   3186                   "number flags are set in criteria type" );
   3187 
   3188     crit.epsilon = (float)MAX( 0, crit.epsilon );
   3189     crit.max_iter = MAX( 1, crit.max_iter );
   3190 
   3191     return crit;
   3192 }
   3193 
   3194 namespace cv
   3195 {
   3196 
   3197 template<> void DefaultDeleter<CvMat>::operator ()(CvMat* obj) const
   3198 { cvReleaseMat(&obj); }
   3199 
   3200 template<> void DefaultDeleter<IplImage>::operator ()(IplImage* obj) const
   3201 { cvReleaseImage(&obj); }
   3202 
   3203 template<> void DefaultDeleter<CvMatND>::operator ()(CvMatND* obj) const
   3204 { cvReleaseMatND(&obj); }
   3205 
   3206 template<> void DefaultDeleter<CvSparseMat>::operator ()(CvSparseMat* obj) const
   3207 { cvReleaseSparseMat(&obj); }
   3208 
   3209 template<> void DefaultDeleter<CvMemStorage>::operator ()(CvMemStorage* obj) const
   3210 { cvReleaseMemStorage(&obj); }
   3211 
   3212 template<> void DefaultDeleter<CvFileStorage>::operator ()(CvFileStorage* obj) const
   3213 { cvReleaseFileStorage(&obj); }
   3214 
   3215 }
   3216 
   3217 /* End of file. */
   3218