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