Renesas GR-PEACH OpenCV Development / gr-peach-opencv-project-sd-card_update

Fork of gr-peach-opencv-project-sd-card by the do

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers array.cpp Source File

array.cpp

00001 /*M///////////////////////////////////////////////////////////////////////////////////////
00002 //
00003 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
00004 //
00005 //  By downloading, copying, installing or using the software you agree to this license.
00006 //  If you do not agree to this license, do not download, install,
00007 //  copy or use the software.
00008 //
00009 //
00010 //                        Intel License Agreement
00011 //                For Open Source Computer Vision Library
00012 //
00013 // Copyright (C) 2000, Intel Corporation, all rights reserved.
00014 // Third party copyrights are property of their respective owners.
00015 //
00016 // Redistribution and use in source and binary forms, with or without modification,
00017 // are permitted provided that the following conditions are met:
00018 //
00019 //   * Redistribution's of source code must retain the above copyright notice,
00020 //     this list of conditions and the following disclaimer.
00021 //
00022 //   * Redistribution's in binary form must reproduce the above copyright notice,
00023 //     this list of conditions and the following disclaimer in the documentation
00024 //     and/or other materials provided with the distribution.
00025 //
00026 //   * The name of Intel Corporation may not be used to endorse or promote products
00027 //     derived from this software without specific prior written permission.
00028 //
00029 // This software is provided by the copyright holders and contributors "as is" and
00030 // any express or implied warranties, including, but not limited to, the implied
00031 // warranties of merchantability and fitness for a particular purpose are disclaimed.
00032 // In no event shall the Intel Corporation or contributors be liable for any direct,
00033 // indirect, incidental, special, exemplary, or consequential damages
00034 // (including, but not limited to, procurement of substitute goods or services;
00035 // loss of use, data, or profits; or business interruption) however caused
00036 // and on any theory of liability, whether in contract, strict liability,
00037 // or tort (including negligence or otherwise) arising in any way out of
00038 // the use of this software, even if advised of the possibility of such damage.
00039 //
00040 //M*/
00041 
00042 /* ////////////////////////////////////////////////////////////////////
00043 //
00044 //  CvMat, CvMatND, CvSparceMat and IplImage support functions
00045 //  (creation, deletion, copying, retrieving and setting elements etc.)
00046 //
00047 // */
00048 
00049 #include "precomp.hpp"
00050 
00051 #define  CV_ORIGIN_TL  0
00052 #define  CV_ORIGIN_BL  1
00053 
00054 /* default image row align (in bytes) */
00055 #define  CV_DEFAULT_IMAGE_ROW_ALIGN  4
00056 
00057 
00058 static struct
00059 {
00060     Cv_iplCreateImageHeader  createHeader;
00061     Cv_iplAllocateImageData  allocateData;
00062     Cv_iplDeallocate  deallocate;
00063     Cv_iplCreateROI  createROI;
00064     Cv_iplCloneImage  cloneImage;
00065 }
00066 CvIPL;
00067 
00068 // Makes the library use native IPL image allocators
00069 CV_IMPL void
00070 cvSetIPLAllocators( Cv_iplCreateImageHeader createHeader,
00071                     Cv_iplAllocateImageData allocateData,
00072                     Cv_iplDeallocate deallocate,
00073                     Cv_iplCreateROI createROI,
00074                     Cv_iplCloneImage cloneImage )
00075 {
00076     int count = (createHeader != 0) + (allocateData != 0) + (deallocate != 0) +
00077         (createROI != 0) + (cloneImage != 0);
00078 
00079     if( count != 0 && count != 5 )
00080         CV_Error( CV_StsBadArg, "Either all the pointers should be null or "
00081                                  "they all should be non-null" );
00082 
00083     CvIPL.createHeader = createHeader;
00084     CvIPL.allocateData = allocateData;
00085     CvIPL.deallocate = deallocate;
00086     CvIPL.createROI = createROI;
00087     CvIPL.cloneImage = cloneImage;
00088 }
00089 
00090 
00091 /****************************************************************************************\
00092 *                               CvMat creation and basic operations                      *
00093 \****************************************************************************************/
00094 
00095 // Creates CvMat and underlying data
00096 CV_IMPL CvMat*
00097 cvCreateMat( int height, int width, int type )
00098 {
00099     CvMat* arr = cvCreateMatHeader( height, width, type );
00100     cvCreateData( arr );
00101 
00102     return arr;
00103 }
00104 
00105 
00106 static void icvCheckHuge( CvMat* arr )
00107 {
00108     if( (int64)arr->step*arr->rows > INT_MAX )
00109         arr->type &= ~CV_MAT_CONT_FLAG;
00110 }
00111 
00112 // Creates CvMat header only
00113 CV_IMPL CvMat*
00114 cvCreateMatHeader( int rows, int cols, int type )
00115 {
00116     type = CV_MAT_TYPE(type);
00117 
00118     if( rows < 0 || cols <= 0 )
00119         CV_Error( CV_StsBadSize, "Non-positive width or height" );
00120 
00121     int min_step = CV_ELEM_SIZE(type)*cols;
00122     if( min_step <= 0 )
00123         CV_Error( CV_StsUnsupportedFormat, "Invalid matrix type" );
00124 
00125     CvMat* arr = (CvMat*)cvAlloc( sizeof(*arr));
00126 
00127     arr->step = min_step;
00128     arr->type = CV_MAT_MAGIC_VAL | type | CV_MAT_CONT_FLAG;
00129     arr->rows = rows;
00130     arr->cols = cols;
00131     arr->data.ptr = 0;
00132     arr->refcount = 0;
00133     arr->hdr_refcount = 1;
00134 
00135     icvCheckHuge( arr );
00136     return arr;
00137 }
00138 
00139 
00140 // Initializes CvMat header, allocated by the user
00141 CV_IMPL CvMat*
00142 cvInitMatHeader( CvMat* arr, int rows, int cols,
00143                  int type, void* data, int step )
00144 {
00145     if( !arr )
00146         CV_Error( CV_StsNullPtr, "" );
00147 
00148     if( (unsigned)CV_MAT_DEPTH(type) > CV_DEPTH_MAX )
00149         CV_Error( CV_BadNumChannels, "" );
00150 
00151     if( rows < 0 || cols <= 0 )
00152         CV_Error( CV_StsBadSize, "Non-positive cols or rows" );
00153 
00154     type = CV_MAT_TYPE( type );
00155     arr->type = type | CV_MAT_MAGIC_VAL;
00156     arr->rows = rows;
00157     arr->cols = cols;
00158     arr->data.ptr = (uchar*)data;
00159     arr->refcount = 0;
00160     arr->hdr_refcount = 0;
00161 
00162     int pix_size = CV_ELEM_SIZE(type);
00163     int min_step = arr->cols*pix_size;
00164 
00165     if( step != CV_AUTOSTEP && step != 0 )
00166     {
00167         if( step < min_step )
00168             CV_Error( CV_BadStep, "" );
00169         arr->step = step;
00170     }
00171     else
00172     {
00173         arr->step = min_step;
00174     }
00175 
00176     arr->type = CV_MAT_MAGIC_VAL | type |
00177         (arr->rows == 1 || arr->step == min_step ? CV_MAT_CONT_FLAG : 0);
00178 
00179     icvCheckHuge( arr );
00180     return arr;
00181 }
00182 
00183 
00184 // Deallocates the CvMat structure and underlying data
00185 CV_IMPL void
00186 cvReleaseMat( CvMat** array )
00187 {
00188     if( !array )
00189         CV_Error( CV_HeaderIsNull, "" );
00190 
00191     if( *array )
00192     {
00193         CvMat* arr = *array;
00194 
00195         if( !CV_IS_MAT_HDR_Z(arr) && !CV_IS_MATND_HDR(arr) )
00196             CV_Error( CV_StsBadFlag, "" );
00197 
00198         *array = 0;
00199 
00200         cvDecRefData( arr );
00201         cvFree( &arr );
00202     }
00203 }
00204 
00205 
00206 // Creates a copy of matrix
00207 CV_IMPL CvMat*
00208 cvCloneMat( const CvMat* src )
00209 {
00210     if( !CV_IS_MAT_HDR( src ))
00211         CV_Error( CV_StsBadArg, "Bad CvMat header" );
00212 
00213     CvMat* dst = cvCreateMatHeader( src->rows, src->cols, src->type );
00214 
00215     if( src->data.ptr )
00216     {
00217         cvCreateData( dst );
00218         cvCopy( src, dst );
00219     }
00220 
00221     return dst;
00222 }
00223 
00224 
00225 /****************************************************************************************\
00226 *                               CvMatND creation and basic operations                    *
00227 \****************************************************************************************/
00228 
00229 CV_IMPL CvMatND *
00230 cvInitMatNDHeader( CvMatND * mat, int dims, const int* sizes,
00231                    int type, void* data )
00232 {
00233     type = CV_MAT_TYPE(type);
00234     int64 step = CV_ELEM_SIZE(type);
00235 
00236     if( !mat )
00237         CV_Error( CV_StsNullPtr, "NULL matrix header pointer" );
00238 
00239     if( step == 0 )
00240         CV_Error( CV_StsUnsupportedFormat, "invalid array data type" );
00241 
00242     if( !sizes )
00243         CV_Error( CV_StsNullPtr, "NULL <sizes> pointer" );
00244 
00245     if( dims <= 0 || dims > CV_MAX_DIM )
00246         CV_Error( CV_StsOutOfRange,
00247         "non-positive or too large number of dimensions" );
00248 
00249     for( int i = dims - 1; i >= 0; i-- )
00250     {
00251         if( sizes[i] < 0 )
00252             CV_Error( CV_StsBadSize, "one of dimesion sizes is non-positive" );
00253         mat->dim[i].size = sizes[i];
00254         if( step > INT_MAX )
00255             CV_Error( CV_StsOutOfRange, "The array is too big" );
00256         mat->dim[i].step = (int)step;
00257         step *= sizes[i];
00258     }
00259 
00260     mat->type = CV_MATND_MAGIC_VAL | (step <= INT_MAX ? CV_MAT_CONT_FLAG : 0) | type;
00261     mat->dims = dims;
00262     mat->data.ptr = (uchar*)data;
00263     mat->refcount = 0;
00264     mat->hdr_refcount = 0;
00265     return mat;
00266 }
00267 
00268 
00269 // Creates CvMatND and underlying data
00270 CV_IMPL CvMatND *
00271 cvCreateMatND( int dims, const int* sizes, int type )
00272 {
00273     CvMatND * arr = cvCreateMatNDHeader( dims, sizes, type );
00274     cvCreateData( arr );
00275 
00276     return arr;
00277 }
00278 
00279 
00280 // Creates CvMatND header only
00281 CV_IMPL CvMatND *
00282 cvCreateMatNDHeader( int dims, const int* sizes, int type )
00283 {
00284     if( dims <= 0 || dims > CV_MAX_DIM )
00285         CV_Error( CV_StsOutOfRange,
00286         "non-positive or too large number of dimensions" );
00287 
00288     CvMatND * arr = (CvMatND *)cvAlloc( sizeof(*arr) );
00289 
00290     cvInitMatNDHeader( arr, dims, sizes, type, 0 );
00291     arr->hdr_refcount = 1;
00292     return arr;
00293 }
00294 
00295 
00296 // Creates a copy of nD array
00297 CV_IMPL CvMatND *
00298 cvCloneMatND( const CvMatND * src )
00299 {
00300     if( !CV_IS_MATND_HDR( src ))
00301         CV_Error( CV_StsBadArg, "Bad CvMatND header" );
00302 
00303     CV_Assert( src->dims <= CV_MAX_DIM );
00304     int sizes[CV_MAX_DIM];
00305 
00306     for( int i = 0; i < src->dims; i++ )
00307         sizes[i] = src->dim[i].size;
00308 
00309     CvMatND * dst = cvCreateMatNDHeader( src->dims, sizes, src->type );
00310 
00311     if( src->data.ptr )
00312     {
00313         cvCreateData( dst );
00314         cv::Mat _src = cv::cvarrToMat(src);
00315         cv::Mat _dst = cv::cvarrToMat(dst);
00316         uchar* data0 = dst->data.ptr;
00317         _src.copyTo(_dst);
00318         CV_Assert(_dst.data == data0);
00319         //cvCopy( src, dst );
00320     }
00321 
00322     return dst;
00323 }
00324 
00325 
00326 static CvMatND *
00327 cvGetMatND( const CvArr* arr, CvMatND * matnd, int* coi )
00328 {
00329     CvMatND * result = 0;
00330 
00331     if( coi )
00332         *coi = 0;
00333 
00334     if( !matnd || !arr )
00335         CV_Error( CV_StsNullPtr, "NULL array pointer is passed" );
00336 
00337     if( CV_IS_MATND_HDR(arr))
00338     {
00339         if( !((CvMatND *)arr)->data.ptr )
00340             CV_Error( CV_StsNullPtr, "The matrix has NULL data pointer" );
00341 
00342         result = (CvMatND *)arr;
00343     }
00344     else
00345     {
00346         CvMat stub, *mat = (CvMat*)arr;
00347 
00348         if( CV_IS_IMAGE_HDR( mat ))
00349             mat = cvGetMat( mat, &stub, coi );
00350 
00351         if( !CV_IS_MAT_HDR( mat ))
00352             CV_Error( CV_StsBadArg, "Unrecognized or unsupported array type" );
00353 
00354         if( !mat->data.ptr )
00355             CV_Error( CV_StsNullPtr, "Input array has NULL data pointer" );
00356 
00357         matnd->data.ptr = mat->data.ptr;
00358         matnd->refcount = 0;
00359         matnd->hdr_refcount = 0;
00360         matnd->type = mat->type;
00361         matnd->dims = 2;
00362         matnd->dim[0].size = mat->rows;
00363         matnd->dim[0].step = mat->step;
00364         matnd->dim[1].size = mat->cols;
00365         matnd->dim[1].step = CV_ELEM_SIZE(mat->type);
00366         result = matnd;
00367     }
00368 
00369     return result;
00370 }
00371 
00372 
00373 // returns number of dimensions to iterate.
00374 /*
00375 Checks whether <count> arrays have equal type, sizes (mask is optional array
00376 that needs to have the same size, but 8uC1 or 8sC1 type).
00377 Returns number of dimensions to iterate through:
00378 0 means that all arrays are continuous,
00379 1 means that all arrays are vectors of continuous arrays etc.
00380 and the size of largest common continuous part of the arrays
00381 */
00382 CV_IMPL int
00383 cvInitNArrayIterator( int count, CvArr** arrs,
00384                       const CvArr* mask, CvMatND * stubs,
00385                       CvNArrayIterator* iterator, int flags )
00386 {
00387     int dims = -1;
00388     int i, j, size, dim0 = -1;
00389     int64 step;
00390     CvMatND * hdr0 = 0;
00391 
00392     if( count < 1 || count > CV_MAX_ARR )
00393         CV_Error( CV_StsOutOfRange, "Incorrect number of arrays" );
00394 
00395     if( !arrs || !stubs )
00396         CV_Error( CV_StsNullPtr, "Some of required array pointers is NULL" );
00397 
00398     if( !iterator )
00399         CV_Error( CV_StsNullPtr, "Iterator pointer is NULL" );
00400 
00401     for( i = 0; i <= count; i++ )
00402     {
00403         const CvArr* arr = i < count ? arrs[i] : mask;
00404         CvMatND * hdr;
00405 
00406         if( !arr )
00407         {
00408             if( i < count )
00409                 CV_Error( CV_StsNullPtr, "Some of required array pointers is NULL" );
00410             break;
00411         }
00412 
00413         if( CV_IS_MATND( arr ))
00414             hdr = (CvMatND *)arr;
00415         else
00416         {
00417             int coi = 0;
00418             hdr = cvGetMatND( arr, stubs + i, &coi );
00419             if( coi != 0 )
00420                 CV_Error( CV_BadCOI, "COI set is not allowed here" );
00421         }
00422 
00423         iterator->hdr[i] = hdr;
00424 
00425         if( i > 0 )
00426         {
00427             if( hdr->dims != hdr0->dims )
00428                 CV_Error( CV_StsUnmatchedSizes,
00429                           "Number of dimensions is the same for all arrays" );
00430 
00431             if( i < count )
00432             {
00433                 switch( flags & (CV_NO_DEPTH_CHECK|CV_NO_CN_CHECK))
00434                 {
00435                 case 0:
00436                     if( !CV_ARE_TYPES_EQ( hdr, hdr0 ))
00437                         CV_Error( CV_StsUnmatchedFormats,
00438                                   "Data type is not the same for all arrays" );
00439                     break;
00440                 case CV_NO_DEPTH_CHECK:
00441                     if( !CV_ARE_CNS_EQ( hdr, hdr0 ))
00442                         CV_Error( CV_StsUnmatchedFormats,
00443                                   "Number of channels is not the same for all arrays" );
00444                     break;
00445                 case CV_NO_CN_CHECK:
00446                     if( !CV_ARE_CNS_EQ( hdr, hdr0 ))
00447                         CV_Error( CV_StsUnmatchedFormats,
00448                                   "Depth is not the same for all arrays" );
00449                     break;
00450                 }
00451             }
00452             else
00453             {
00454                 if( !CV_IS_MASK_ARR( hdr ))
00455                     CV_Error( CV_StsBadMask, "Mask should have 8uC1 or 8sC1 data type" );
00456             }
00457 
00458             if( !(flags & CV_NO_SIZE_CHECK) )
00459             {
00460                 for( j = 0; j < hdr->dims; j++ )
00461                     if( hdr->dim[j].size != hdr0->dim[j].size )
00462                         CV_Error( CV_StsUnmatchedSizes,
00463                                   "Dimension sizes are the same for all arrays" );
00464             }
00465         }
00466         else
00467             hdr0 = hdr;
00468 
00469         step = CV_ELEM_SIZE(hdr->type);
00470         for( j = hdr->dims - 1; j > dim0; j-- )
00471         {
00472             if( step != hdr->dim[j].step )
00473                 break;
00474             step *= hdr->dim[j].size;
00475         }
00476 
00477         if( j == dim0 && step > INT_MAX )
00478             j++;
00479 
00480         if( j > dim0 )
00481             dim0 = j;
00482 
00483         iterator->hdr[i] = (CvMatND *)hdr;
00484         iterator->ptr[i] = (uchar*)hdr->data.ptr;
00485     }
00486 
00487     size = 1;
00488     for( j = hdr0->dims - 1; j > dim0; j-- )
00489         size *= hdr0->dim[j].size;
00490 
00491     dims = dim0 + 1;
00492     iterator->dims = dims;
00493     iterator->count = count;
00494     iterator->size = cvSize(size,1);
00495 
00496     for( i = 0; i < dims; i++ )
00497         iterator->stack[i] = hdr0->dim[i].size;
00498 
00499     return dims;
00500 }
00501 
00502 
00503 // returns zero value if iteration is finished, non-zero otherwise
00504 CV_IMPL int cvNextNArraySlice( CvNArrayIterator* iterator )
00505 {
00506     assert( iterator != 0 );
00507     int i, dims;
00508 
00509     for( dims = iterator->dims; dims > 0; dims-- )
00510     {
00511         for( i = 0; i < iterator->count; i++ )
00512             iterator->ptr[i] += iterator->hdr[i]->dim[dims-1].step;
00513 
00514         if( --iterator->stack[dims-1] > 0 )
00515             break;
00516 
00517         const int size = iterator->hdr[0]->dim[dims-1].size;
00518 
00519         for( i = 0; i < iterator->count; i++ )
00520             iterator->ptr[i] -= (size_t)size*iterator->hdr[i]->dim[dims-1].step;
00521 
00522         iterator->stack[dims-1] = size;
00523     }
00524 
00525     return dims > 0;
00526 }
00527 
00528 
00529 /****************************************************************************************\
00530 *                            CvSparseMat creation and basic operations                   *
00531 \****************************************************************************************/
00532 
00533 
00534 // Creates CvMatND and underlying data
00535 CV_IMPL CvSparseMat*
00536 cvCreateSparseMat( int dims, const int* sizes, int type )
00537 {
00538     type = CV_MAT_TYPE( type );
00539     int pix_size1 = CV_ELEM_SIZE1(type);
00540     int pix_size = pix_size1*CV_MAT_CN(type);
00541     int i, size;
00542     CvMemStorage* storage;
00543 
00544     if( pix_size == 0 )
00545         CV_Error( CV_StsUnsupportedFormat, "invalid array data type" );
00546 
00547     if( dims <= 0 || dims > CV_MAX_DIM_HEAP )
00548         CV_Error( CV_StsOutOfRange, "bad number of dimensions" );
00549 
00550     if( !sizes )
00551         CV_Error( CV_StsNullPtr, "NULL <sizes> pointer" );
00552 
00553     for( i = 0; i < dims; i++ )
00554     {
00555         if( sizes[i] <= 0 )
00556             CV_Error( CV_StsBadSize, "one of dimesion sizes is non-positive" );
00557     }
00558 
00559     CvSparseMat* arr = (CvSparseMat*)cvAlloc(sizeof(*arr)+MAX(0,dims-CV_MAX_DIM)*sizeof(arr->size[0]));
00560 
00561     arr->type = CV_SPARSE_MAT_MAGIC_VAL | type;
00562     arr->dims = dims;
00563     arr->refcount = 0;
00564     arr->hdr_refcount = 1;
00565     memcpy( arr->size, sizes, dims*sizeof(sizes[0]));
00566 
00567     arr->valoffset = (int)cvAlign(sizeof(CvSparseNode), pix_size1);
00568     arr->idxoffset = (int)cvAlign(arr->valoffset + pix_size, sizeof(int));
00569     size = (int)cvAlign(arr->idxoffset + dims*sizeof(int), sizeof(CvSetElem));
00570 
00571     storage = cvCreateMemStorage( CV_SPARSE_MAT_BLOCK );
00572     arr->heap = cvCreateSet( 0, sizeof(CvSet), size, storage );
00573 
00574     arr->hashsize = CV_SPARSE_HASH_SIZE0;
00575     size = arr->hashsize*sizeof(arr->hashtable[0]);
00576 
00577     arr->hashtable = (void**)cvAlloc( size );
00578     memset( arr->hashtable, 0, size );
00579 
00580     return arr;
00581 }
00582 
00583 
00584 // Creates CvMatND and underlying data
00585 CV_IMPL void
00586 cvReleaseSparseMat( CvSparseMat** array )
00587 {
00588     if( !array )
00589         CV_Error( CV_HeaderIsNull, "" );
00590 
00591     if( *array )
00592     {
00593         CvSparseMat* arr = *array;
00594 
00595         if( !CV_IS_SPARSE_MAT_HDR(arr) )
00596             CV_Error( CV_StsBadFlag, "" );
00597 
00598         *array = 0;
00599 
00600         CvMemStorage* storage = arr->heap->storage;
00601         cvReleaseMemStorage( &storage );
00602         cvFree( &arr->hashtable );
00603         cvFree( &arr );
00604     }
00605 }
00606 
00607 
00608 // Creates CvMatND and underlying data
00609 CV_IMPL CvSparseMat*
00610 cvCloneSparseMat( const CvSparseMat* src )
00611 {
00612     if( !CV_IS_SPARSE_MAT_HDR(src) )
00613         CV_Error( CV_StsBadArg, "Invalid sparse array header" );
00614 
00615     CvSparseMat* dst = cvCreateSparseMat( src->dims, src->size, src->type );
00616     cvCopy( src, dst );
00617     return dst;
00618 }
00619 
00620 
00621 CvSparseNode*
00622 cvInitSparseMatIterator( const CvSparseMat* mat, CvSparseMatIterator* iterator )
00623 {
00624     CvSparseNode* node = 0;
00625     int idx;
00626 
00627     if( !CV_IS_SPARSE_MAT( mat ))
00628         CV_Error( CV_StsBadArg, "Invalid sparse matrix header" );
00629 
00630     if( !iterator )
00631         CV_Error( CV_StsNullPtr, "NULL iterator pointer" );
00632 
00633     iterator->mat = (CvSparseMat*)mat;
00634     iterator->node = 0;
00635 
00636     for( idx = 0; idx < mat->hashsize; idx++ )
00637         if( mat->hashtable[idx] )
00638         {
00639             node = iterator->node = (CvSparseNode*)mat->hashtable[idx];
00640             break;
00641         }
00642 
00643     iterator->curidx = idx;
00644     return node;
00645 }
00646 
00647 #define ICV_SPARSE_MAT_HASH_MULTIPLIER  cv::SparseMat::HASH_SCALE
00648 
00649 static uchar*
00650 icvGetNodePtr( CvSparseMat* mat, const int* idx, int* _type,
00651                int create_node, unsigned* precalc_hashval )
00652 {
00653     uchar* ptr = 0;
00654     int i, tabidx;
00655     unsigned hashval = 0;
00656     CvSparseNode *node;
00657     assert( CV_IS_SPARSE_MAT( mat ));
00658 
00659     if( !precalc_hashval )
00660     {
00661         for( i = 0; i < mat->dims; i++ )
00662         {
00663             int t = idx[i];
00664             if( (unsigned)t >= (unsigned)mat->size[i] )
00665                 CV_Error( CV_StsOutOfRange, "One of indices is out of range" );
00666             hashval = hashval*ICV_SPARSE_MAT_HASH_MULTIPLIER + t;
00667         }
00668     }
00669     else
00670     {
00671         hashval = *precalc_hashval;
00672     }
00673 
00674     tabidx = hashval & (mat->hashsize - 1);
00675     hashval &= INT_MAX;
00676 
00677     if( create_node >= -1 )
00678     {
00679         for( node = (CvSparseNode*)mat->hashtable[tabidx];
00680              node != 0; node = node->next )
00681         {
00682             if( node->hashval == hashval )
00683             {
00684                 int* nodeidx = CV_NODE_IDX(mat,node);
00685                 for( i = 0; i < mat->dims; i++ )
00686                     if( idx[i] != nodeidx[i] )
00687                         break;
00688                 if( i == mat->dims )
00689                 {
00690                     ptr = (uchar*)CV_NODE_VAL(mat,node);
00691                     break;
00692                 }
00693             }
00694         }
00695     }
00696 
00697     if( !ptr && create_node )
00698     {
00699         if( mat->heap->active_count >= mat->hashsize*CV_SPARSE_HASH_RATIO )
00700         {
00701             void** newtable;
00702             int newsize = MAX( mat->hashsize*2, CV_SPARSE_HASH_SIZE0);
00703             int newrawsize = newsize*sizeof(newtable[0]);
00704 
00705             CvSparseMatIterator iterator;
00706             assert( (newsize & (newsize - 1)) == 0 );
00707 
00708             // resize hash table
00709             newtable = (void**)cvAlloc( newrawsize );
00710             memset( newtable, 0, newrawsize );
00711 
00712             node = cvInitSparseMatIterator( mat, &iterator );
00713             while( node )
00714             {
00715                 CvSparseNode* next = cvGetNextSparseNode( &iterator );
00716                 int newidx = node->hashval & (newsize - 1);
00717                 node->next = (CvSparseNode*)newtable[newidx];
00718                 newtable[newidx] = node;
00719                 node = next;
00720             }
00721 
00722             cvFree( &mat->hashtable );
00723             mat->hashtable = newtable;
00724             mat->hashsize = newsize;
00725             tabidx = hashval & (newsize - 1);
00726         }
00727 
00728         node = (CvSparseNode*)cvSetNew( mat->heap );
00729         node->hashval = hashval;
00730         node->next = (CvSparseNode*)mat->hashtable[tabidx];
00731         mat->hashtable[tabidx] = node;
00732         memcpy(CV_NODE_IDX(mat,node), idx, mat->dims*sizeof(idx[0]));
00733         ptr = (uchar*)CV_NODE_VAL(mat,node);
00734         if( create_node > 0 )
00735             memset( ptr, 0, CV_ELEM_SIZE(mat->type));
00736     }
00737 
00738     if( _type )
00739         *_type = CV_MAT_TYPE(mat->type);
00740 
00741     return ptr;
00742 }
00743 
00744 
00745 static void
00746 icvDeleteNode( CvSparseMat* mat, const int* idx, unsigned* precalc_hashval )
00747 {
00748     int i, tabidx;
00749     unsigned hashval = 0;
00750     CvSparseNode *node, *prev = 0;
00751     assert( CV_IS_SPARSE_MAT( mat ));
00752 
00753     if( !precalc_hashval )
00754     {
00755         for( i = 0; i < mat->dims; i++ )
00756         {
00757             int t = idx[i];
00758             if( (unsigned)t >= (unsigned)mat->size[i] )
00759                 CV_Error( CV_StsOutOfRange, "One of indices is out of range" );
00760             hashval = hashval*ICV_SPARSE_MAT_HASH_MULTIPLIER + t;
00761         }
00762     }
00763     else
00764     {
00765         hashval = *precalc_hashval;
00766     }
00767 
00768     tabidx = hashval & (mat->hashsize - 1);
00769     hashval &= INT_MAX;
00770 
00771     for( node = (CvSparseNode*)mat->hashtable[tabidx];
00772          node != 0; prev = node, node = node->next )
00773     {
00774         if( node->hashval == hashval )
00775         {
00776             int* nodeidx = CV_NODE_IDX(mat,node);
00777             for( i = 0; i < mat->dims; i++ )
00778                 if( idx[i] != nodeidx[i] )
00779                     break;
00780             if( i == mat->dims )
00781                 break;
00782         }
00783     }
00784 
00785     if( node )
00786     {
00787         if( prev )
00788             prev->next = node->next;
00789         else
00790             mat->hashtable[tabidx] = node->next;
00791         cvSetRemoveByPtr( mat->heap, node );
00792     }
00793 }
00794 
00795 
00796 /****************************************************************************************\
00797 *                          Common for multiple array types operations                    *
00798 \****************************************************************************************/
00799 
00800 // Allocates underlying array data
00801 CV_IMPL void
00802 cvCreateData( CvArr* arr )
00803 {
00804     if( CV_IS_MAT_HDR_Z( arr ))
00805     {
00806         size_t step, total_size;
00807         CvMat* mat = (CvMat*)arr;
00808         step = mat->step;
00809 
00810         if( mat->rows == 0 || mat->cols == 0 )
00811             return;
00812 
00813         if( mat->data.ptr != 0 )
00814             CV_Error( CV_StsError, "Data is already allocated" );
00815 
00816         if( step == 0 )
00817             step = CV_ELEM_SIZE(mat->type)*mat->cols;
00818 
00819         int64 _total_size = (int64)step*mat->rows + sizeof(int) + CV_MALLOC_ALIGN;
00820         total_size = (size_t)_total_size;
00821         if(_total_size != (int64)total_size)
00822             CV_Error(CV_StsNoMem, "Too big buffer is allocated" );
00823         mat->refcount = (int*)cvAlloc( (size_t)total_size );
00824         mat->data.ptr = (uchar*)cvAlignPtr( mat->refcount + 1, CV_MALLOC_ALIGN );
00825         *mat->refcount = 1;
00826     }
00827     else if( CV_IS_IMAGE_HDR(arr))
00828     {
00829         IplImage* img = (IplImage*)arr;
00830 
00831         if( img->imageData != 0 )
00832             CV_Error( CV_StsError, "Data is already allocated" );
00833 
00834         if( !CvIPL.allocateData )
00835         {
00836             img->imageData = img->imageDataOrigin =
00837                         (char*)cvAlloc( (size_t)img->imageSize );
00838         }
00839         else
00840         {
00841             int depth = img->depth;
00842             int width = img->width;
00843 
00844             if( img->depth == IPL_DEPTH_32F || img->depth == IPL_DEPTH_64F )
00845             {
00846                 img->width *= img->depth == IPL_DEPTH_32F ? sizeof(float) : sizeof(double);
00847                 img->depth = IPL_DEPTH_8U;
00848             }
00849 
00850             CvIPL.allocateData( img, 0, 0 );
00851 
00852             img->width = width;
00853             img->depth = depth;
00854         }
00855     }
00856     else if( CV_IS_MATND_HDR( arr ))
00857     {
00858         CvMatND * mat = (CvMatND *)arr;
00859         size_t total_size = CV_ELEM_SIZE(mat->type);
00860 
00861         if( mat->dim[0].size == 0 )
00862             return;
00863 
00864         if( mat->data.ptr != 0 )
00865             CV_Error( CV_StsError, "Data is already allocated" );
00866 
00867         if( CV_IS_MAT_CONT( mat->type ))
00868         {
00869             total_size = (size_t)mat->dim[0].size*(mat->dim[0].step != 0 ?
00870                          (size_t)mat->dim[0].step : total_size);
00871         }
00872         else
00873         {
00874             int i;
00875             for( i = mat->dims - 1; i >= 0; i-- )
00876             {
00877                 size_t size = (size_t)mat->dim[i].step*mat->dim[i].size;
00878 
00879                 if( total_size < size )
00880                     total_size = size;
00881             }
00882         }
00883 
00884         mat->refcount = (int*)cvAlloc( total_size +
00885                                         sizeof(int) + CV_MALLOC_ALIGN );
00886         mat->data.ptr = (uchar*)cvAlignPtr( mat->refcount + 1, CV_MALLOC_ALIGN );
00887         *mat->refcount = 1;
00888     }
00889     else
00890         CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
00891 }
00892 
00893 
00894 // Assigns external data to array
00895 CV_IMPL void
00896 cvSetData( CvArr* arr, void* data, int step )
00897 {
00898     int pix_size, min_step;
00899 
00900     if( CV_IS_MAT_HDR(arr) || CV_IS_MATND_HDR(arr) )
00901         cvReleaseData( arr );
00902 
00903     if( CV_IS_MAT_HDR( arr ))
00904     {
00905         CvMat* mat = (CvMat*)arr;
00906 
00907         int type = CV_MAT_TYPE(mat->type);
00908         pix_size = CV_ELEM_SIZE(type);
00909         min_step = mat->cols*pix_size;
00910 
00911         if( step != CV_AUTOSTEP && step != 0 )
00912         {
00913             if( step < min_step && data != 0 )
00914                 CV_Error( CV_BadStep, "" );
00915             mat->step = step;
00916         }
00917         else
00918             mat->step = min_step;
00919 
00920         mat->data.ptr = (uchar*)data;
00921         mat->type = CV_MAT_MAGIC_VAL | type |
00922                     (mat->rows == 1 || mat->step == min_step ? CV_MAT_CONT_FLAG : 0);
00923         icvCheckHuge( mat );
00924     }
00925     else if( CV_IS_IMAGE_HDR( arr ))
00926     {
00927         IplImage* img = (IplImage*)arr;
00928 
00929         pix_size = ((img->depth & 255) >> 3)*img->nChannels;
00930         min_step = img->width*pix_size;
00931 
00932         if( step != CV_AUTOSTEP && img->height > 1 )
00933         {
00934             if( step < min_step && data != 0 )
00935                 CV_Error( CV_BadStep, "" );
00936             img->widthStep = step;
00937         }
00938         else
00939         {
00940             img->widthStep = min_step;
00941         }
00942 
00943         img->imageSize = img->widthStep * img->height;
00944         img->imageData = img->imageDataOrigin = (char*)data;
00945 
00946         if( (((int)(size_t)data | step) & 7) == 0 &&
00947             cvAlign(img->width * pix_size, 8) == step )
00948             img->align = 8;
00949         else
00950             img->align = 4;
00951     }
00952     else if( CV_IS_MATND_HDR( arr ))
00953     {
00954         CvMatND * mat = (CvMatND *)arr;
00955         int i;
00956         int64 cur_step;
00957 
00958         if( step != CV_AUTOSTEP )
00959             CV_Error( CV_BadStep,
00960             "For multidimensional array only CV_AUTOSTEP is allowed here" );
00961 
00962         mat->data.ptr = (uchar*)data;
00963         cur_step = CV_ELEM_SIZE(mat->type);
00964 
00965         for( i = mat->dims - 1; i >= 0; i-- )
00966         {
00967             if( cur_step > INT_MAX )
00968                 CV_Error( CV_StsOutOfRange, "The array is too big" );
00969             mat->dim[i].step = (int)cur_step;
00970             cur_step *= mat->dim[i].size;
00971         }
00972     }
00973     else
00974         CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
00975 }
00976 
00977 
00978 // Deallocates array's data
00979 CV_IMPL void
00980 cvReleaseData( CvArr* arr )
00981 {
00982     if( CV_IS_MAT_HDR( arr ) || CV_IS_MATND_HDR( arr ))
00983     {
00984         CvMat* mat = (CvMat*)arr;
00985         cvDecRefData( mat );
00986     }
00987     else if( CV_IS_IMAGE_HDR( arr ))
00988     {
00989         IplImage* img = (IplImage*)arr;
00990 
00991         if( !CvIPL.deallocate )
00992         {
00993             char* ptr = img->imageDataOrigin;
00994             img->imageData = img->imageDataOrigin = 0;
00995             cvFree( &ptr );
00996         }
00997         else
00998         {
00999             CvIPL.deallocate( img, IPL_IMAGE_DATA );
01000         }
01001     }
01002     else
01003         CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
01004 }
01005 
01006 
01007 // Retrieves essential information about image ROI or CvMat data
01008 CV_IMPL void
01009 cvGetRawData( const CvArr* arr, uchar** data, int* step, CvSize* roi_size )
01010 {
01011     if( CV_IS_MAT( arr ))
01012     {
01013         CvMat *mat = (CvMat*)arr;
01014 
01015         if( step )
01016             *step = mat->step;
01017 
01018         if( data )
01019             *data = mat->data.ptr;
01020 
01021         if( roi_size )
01022             *roi_size = cvGetMatSize( mat );
01023     }
01024     else if( CV_IS_IMAGE( arr ))
01025     {
01026         IplImage* img = (IplImage*)arr;
01027 
01028         if( step )
01029             *step = img->widthStep;
01030 
01031         if( data )
01032             *data = cvPtr2D( img, 0, 0 );
01033 
01034         if( roi_size )
01035         {
01036             if( img->roi )
01037             {
01038                 *roi_size = cvSize( img->roi->width, img->roi->height );
01039             }
01040             else
01041             {
01042                 *roi_size = cvSize( img->width, img->height );
01043             }
01044         }
01045     }
01046     else if( CV_IS_MATND( arr ))
01047     {
01048         CvMatND * mat = (CvMatND *)arr;
01049 
01050         if( !CV_IS_MAT_CONT( mat->type ))
01051             CV_Error( CV_StsBadArg, "Only continuous nD arrays are supported here" );
01052 
01053         if( data )
01054             *data = mat->data.ptr;
01055 
01056         if( roi_size || step )
01057         {
01058             if( roi_size )
01059             {
01060                 int size1 = mat->dim[0].size, size2 = 1;
01061 
01062                 if( mat->dims > 2 )
01063                 {
01064                     int i;
01065                     for( i = 1; i < mat->dims; i++ )
01066                         size1 *= mat->dim[i].size;
01067                 }
01068                 else
01069                     size2 = mat->dim[1].size;
01070 
01071                 roi_size->width = size2;
01072                 roi_size->height = size1;
01073             }
01074 
01075             if( step )
01076                 *step = mat->dim[0].step;
01077         }
01078     }
01079     else
01080         CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
01081 }
01082 
01083 
01084 CV_IMPL int
01085 cvGetElemType( const CvArr* arr )
01086 {
01087     int type = -1;
01088     if( CV_IS_MAT_HDR(arr) || CV_IS_MATND_HDR(arr) || CV_IS_SPARSE_MAT_HDR(arr))
01089         type = CV_MAT_TYPE( ((CvMat*)arr)->type );
01090     else if( CV_IS_IMAGE(arr))
01091     {
01092         IplImage* img = (IplImage*)arr;
01093         type = CV_MAKETYPE( IPL2CV_DEPTH(img->depth), img->nChannels );
01094     }
01095     else
01096         CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
01097 
01098     return type;
01099 }
01100 
01101 
01102 // Returns a number of array dimensions
01103 CV_IMPL int
01104 cvGetDims( const CvArr* arr, int* sizes )
01105 {
01106     int dims = -1;
01107     if( CV_IS_MAT_HDR( arr ))
01108     {
01109         CvMat* mat = (CvMat*)arr;
01110 
01111         dims = 2;
01112         if( sizes )
01113         {
01114             sizes[0] = mat->rows;
01115             sizes[1] = mat->cols;
01116         }
01117     }
01118     else if( CV_IS_IMAGE( arr ))
01119     {
01120         IplImage* img = (IplImage*)arr;
01121         dims = 2;
01122 
01123         if( sizes )
01124         {
01125             sizes[0] = img->height;
01126             sizes[1] = img->width;
01127         }
01128     }
01129     else if( CV_IS_MATND_HDR( arr ))
01130     {
01131         CvMatND * mat = (CvMatND *)arr;
01132         dims = mat->dims;
01133 
01134         if( sizes )
01135         {
01136             int i;
01137             for( i = 0; i < dims; i++ )
01138                 sizes[i] = mat->dim[i].size;
01139         }
01140     }
01141     else if( CV_IS_SPARSE_MAT_HDR( arr ))
01142     {
01143         CvSparseMat* mat = (CvSparseMat*)arr;
01144         dims = mat->dims;
01145 
01146         if( sizes )
01147             memcpy( sizes, mat->size, dims*sizeof(sizes[0]));
01148     }
01149     else
01150         CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
01151 
01152     return dims;
01153 }
01154 
01155 
01156 // Returns the size of particular array dimension
01157 CV_IMPL int
01158 cvGetDimSize( const CvArr* arr, int index )
01159 {
01160     int size = -1;
01161 
01162     if( CV_IS_MAT( arr ))
01163     {
01164         CvMat *mat = (CvMat*)arr;
01165 
01166         switch( index )
01167         {
01168         case 0:
01169             size = mat->rows;
01170             break;
01171         case 1:
01172             size = mat->cols;
01173             break;
01174         default:
01175             CV_Error( CV_StsOutOfRange, "bad dimension index" );
01176         }
01177     }
01178     else if( CV_IS_IMAGE( arr ))
01179     {
01180         IplImage* img = (IplImage*)arr;
01181 
01182         switch( index )
01183         {
01184         case 0:
01185             size = !img->roi ? img->height : img->roi->height;
01186             break;
01187         case 1:
01188             size = !img->roi ? img->width : img->roi->width;
01189             break;
01190         default:
01191             CV_Error( CV_StsOutOfRange, "bad dimension index" );
01192         }
01193     }
01194     else if( CV_IS_MATND_HDR( arr ))
01195     {
01196         CvMatND * mat = (CvMatND *)arr;
01197 
01198         if( (unsigned)index >= (unsigned)mat->dims )
01199             CV_Error( CV_StsOutOfRange, "bad dimension index" );
01200 
01201         size = mat->dim[index].size;
01202     }
01203     else if( CV_IS_SPARSE_MAT_HDR( arr ))
01204     {
01205         CvSparseMat* mat = (CvSparseMat*)arr;
01206 
01207         if( (unsigned)index >= (unsigned)mat->dims )
01208             CV_Error( CV_StsOutOfRange, "bad dimension index" );
01209 
01210         size = mat->size[index];
01211     }
01212     else
01213         CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
01214 
01215     return size;
01216 }
01217 
01218 
01219 // Returns the size of CvMat or IplImage
01220 CV_IMPL CvSize
01221 cvGetSize( const CvArr* arr )
01222 {
01223     CvSize size;
01224 
01225     if( CV_IS_MAT_HDR_Z( arr ))
01226     {
01227         CvMat *mat = (CvMat*)arr;
01228 
01229         size.width = mat->cols;
01230         size.height = mat->rows;
01231     }
01232     else if( CV_IS_IMAGE_HDR( arr ))
01233     {
01234         IplImage* img = (IplImage*)arr;
01235 
01236         if( img->roi )
01237         {
01238             size.width = img->roi->width;
01239             size.height = img->roi->height;
01240         }
01241         else
01242         {
01243             size.width = img->width;
01244             size.height = img->height;
01245         }
01246     }
01247     else
01248         CV_Error( CV_StsBadArg, "Array should be CvMat or IplImage" );
01249 
01250     return size;
01251 }
01252 
01253 
01254 // Selects sub-array (no data is copied)
01255 CV_IMPL  CvMat*
01256 cvGetSubRect( const CvArr* arr, CvMat* submat, CvRect  rect )
01257 {
01258     CvMat* res = 0;
01259     CvMat stub, *mat = (CvMat*)arr;
01260 
01261     if( !CV_IS_MAT( mat ))
01262         mat = cvGetMat( mat, &stub );
01263 
01264     if( !submat )
01265         CV_Error( CV_StsNullPtr, "" );
01266 
01267     if( (rect.x|rect.y|rect.width|rect.height) < 0 )
01268         CV_Error( CV_StsBadSize, "" );
01269 
01270     if( rect.x + rect.width > mat->cols ||
01271         rect.y + rect.height > mat->rows )
01272         CV_Error( CV_StsBadSize, "" );
01273 
01274     {
01275     /*
01276     int* refcount = mat->refcount;
01277 
01278     if( refcount )
01279         ++*refcount;
01280 
01281     cvDecRefData( submat );
01282     */
01283     submat->data.ptr = mat->data.ptr + (size_t)rect.y*mat->step +
01284                        rect.x*CV_ELEM_SIZE(mat->type);
01285     submat->step = mat->step;
01286     submat->type = (mat->type & (rect.width < mat->cols ? ~CV_MAT_CONT_FLAG : -1)) |
01287                    (rect.height <= 1 ? CV_MAT_CONT_FLAG : 0);
01288     submat->rows = rect.height;
01289     submat->cols = rect.width;
01290     submat->refcount = 0;
01291     res = submat;
01292     }
01293 
01294     return res;
01295 }
01296 
01297 
01298 // Selects array's row span.
01299 CV_IMPL  CvMat*
01300 cvGetRows( const CvArr* arr, CvMat* submat,
01301            int start_row, int end_row, int delta_row )
01302 {
01303     CvMat* res = 0;
01304     CvMat stub, *mat = (CvMat*)arr;
01305 
01306     if( !CV_IS_MAT( mat ))
01307         mat = cvGetMat( mat, &stub );
01308 
01309     if( !submat )
01310         CV_Error( CV_StsNullPtr, "" );
01311 
01312     if( (unsigned)start_row >= (unsigned)mat->rows ||
01313         (unsigned)end_row > (unsigned)mat->rows || delta_row <= 0 )
01314         CV_Error( CV_StsOutOfRange, "" );
01315 
01316     {
01317     /*
01318     int* refcount = mat->refcount;
01319 
01320     if( refcount )
01321         ++*refcount;
01322 
01323     cvDecRefData( submat );
01324     */
01325     if( delta_row == 1 )
01326     {
01327         submat->rows = end_row - start_row;
01328         submat->step = mat->step;
01329     }
01330     else
01331     {
01332         submat->rows = (end_row - start_row + delta_row - 1)/delta_row;
01333         submat->step = mat->step * delta_row;
01334     }
01335 
01336     submat->cols = mat->cols;
01337     submat->step &= submat->rows > 1 ? -1 : 0;
01338     submat->data.ptr = mat->data.ptr + (size_t)start_row*mat->step;
01339     submat->type = (mat->type | (submat->rows == 1 ? CV_MAT_CONT_FLAG : 0)) &
01340                    (delta_row != 1 && submat->rows > 1 ? ~CV_MAT_CONT_FLAG : -1);
01341     submat->refcount = 0;
01342     submat->hdr_refcount = 0;
01343     res = submat;
01344     }
01345 
01346     return res;
01347 }
01348 
01349 
01350 // Selects array's column span.
01351 CV_IMPL  CvMat*
01352 cvGetCols( const CvArr* arr, CvMat* submat, int start_col, int end_col )
01353 {
01354     CvMat* res = 0;
01355     CvMat stub, *mat = (CvMat*)arr;
01356     int cols;
01357 
01358     if( !CV_IS_MAT( mat ))
01359         mat = cvGetMat( mat, &stub );
01360 
01361     if( !submat )
01362         CV_Error( CV_StsNullPtr, "" );
01363 
01364     cols = mat->cols;
01365     if( (unsigned)start_col >= (unsigned)cols ||
01366         (unsigned)end_col > (unsigned)cols )
01367         CV_Error( CV_StsOutOfRange, "" );
01368 
01369     {
01370     /*
01371     int* refcount = mat->refcount;
01372 
01373     if( refcount )
01374         ++*refcount;
01375 
01376     cvDecRefData( submat );
01377     */
01378     submat->rows = mat->rows;
01379     submat->cols = end_col - start_col;
01380     submat->step = mat->step;
01381     submat->data.ptr = mat->data.ptr + (size_t)start_col*CV_ELEM_SIZE(mat->type);
01382     submat->type = mat->type & (submat->rows > 1 && submat->cols < cols ? ~CV_MAT_CONT_FLAG : -1);
01383     submat->refcount = 0;
01384     submat->hdr_refcount = 0;
01385     res = submat;
01386     }
01387 
01388     return res;
01389 }
01390 
01391 
01392 // Selects array diagonal
01393 CV_IMPL  CvMat*
01394 cvGetDiag( const CvArr* arr, CvMat* submat, int diag )
01395 {
01396     CvMat* res = 0;
01397     CvMat stub, *mat = (CvMat*)arr;
01398     int len, pix_size;
01399 
01400     if( !CV_IS_MAT( mat ))
01401         mat = cvGetMat( mat, &stub );
01402 
01403     if( !submat )
01404         CV_Error( CV_StsNullPtr, "" );
01405 
01406     pix_size = CV_ELEM_SIZE(mat->type);
01407 
01408     /*{
01409     int* refcount = mat->refcount;
01410 
01411     if( refcount )
01412         ++*refcount;
01413 
01414     cvDecRefData( submat );
01415     }*/
01416 
01417     if( diag >= 0 )
01418     {
01419         len = mat->cols - diag;
01420 
01421         if( len <= 0 )
01422             CV_Error( CV_StsOutOfRange, "" );
01423 
01424         len = CV_IMIN( len, mat->rows );
01425         submat->data.ptr = mat->data.ptr + diag*pix_size;
01426     }
01427     else
01428     {
01429         len = mat->rows + diag;
01430 
01431         if( len <= 0 )
01432             CV_Error( CV_StsOutOfRange, "" );
01433 
01434         len = CV_IMIN( len, mat->cols );
01435         submat->data.ptr = mat->data.ptr - diag*mat->step;
01436     }
01437 
01438     submat->rows = len;
01439     submat->cols = 1;
01440     submat->step = mat->step + (submat->rows > 1 ? pix_size : 0);
01441     submat->type = mat->type;
01442     if( submat->rows > 1 )
01443         submat->type &= ~CV_MAT_CONT_FLAG;
01444     else
01445         submat->type |= CV_MAT_CONT_FLAG;
01446     submat->refcount = 0;
01447     submat->hdr_refcount = 0;
01448     res = submat;
01449 
01450     return res;
01451 }
01452 
01453 
01454 /****************************************************************************************\
01455 *                      Operations on CvScalar and accessing array elements               *
01456 \****************************************************************************************/
01457 
01458 // Converts CvScalar to specified type
01459 CV_IMPL void
01460 cvScalarToRawData( const CvScalar * scalar, void* data, int type, int extend_to_12 )
01461 {
01462     type = CV_MAT_TYPE(type);
01463     int cn = CV_MAT_CN( type );
01464     int depth = type & CV_MAT_DEPTH_MASK;
01465 
01466     assert( scalar && data );
01467     if( (unsigned)(cn - 1) >= 4 )
01468         CV_Error( CV_StsOutOfRange, "The number of channels must be 1, 2, 3 or 4" );
01469 
01470     switch( depth )
01471     {
01472     case CV_8UC1:
01473         while( cn-- )
01474         {
01475             int t = cvRound( scalar->val[cn] );
01476             ((uchar*)data)[cn] = cv::saturate_cast<uchar>(t);
01477         }
01478         break;
01479     case CV_8SC1:
01480         while( cn-- )
01481         {
01482             int t = cvRound( scalar->val[cn] );
01483             ((char*)data)[cn] = cv::saturate_cast<schar>(t);
01484         }
01485         break;
01486     case CV_16UC1:
01487         while( cn-- )
01488         {
01489             int t = cvRound( scalar->val[cn] );
01490             ((ushort*)data)[cn] = cv::saturate_cast<ushort>(t);
01491         }
01492         break;
01493     case CV_16SC1:
01494         while( cn-- )
01495         {
01496             int t = cvRound( scalar->val[cn] );
01497             ((short*)data)[cn] = cv::saturate_cast<short>(t);
01498         }
01499         break;
01500     case CV_32SC1:
01501         while( cn-- )
01502             ((int*)data)[cn] = cvRound( scalar->val[cn] );
01503         break;
01504     case CV_32FC1:
01505         while( cn-- )
01506             ((float*)data)[cn] = (float)(scalar->val[cn]);
01507         break;
01508     case CV_64FC1:
01509         while( cn-- )
01510             ((double*)data)[cn] = (double)(scalar->val[cn]);
01511         break;
01512     default:
01513         assert(0);
01514         CV_Error( CV_BadDepth, "" );
01515     }
01516 
01517     if( extend_to_12 )
01518     {
01519         int pix_size = CV_ELEM_SIZE(type);
01520         int offset = CV_ELEM_SIZE1(depth)*12;
01521 
01522         do
01523         {
01524             offset -= pix_size;
01525             memcpy((char*)data + offset, data, pix_size);
01526         }
01527         while( offset > pix_size );
01528     }
01529 }
01530 
01531 
01532 // Converts data of specified type to CvScalar
01533 CV_IMPL void
01534 cvRawDataToScalar( const void* data, int flags, CvScalar * scalar )
01535 {
01536     int cn = CV_MAT_CN( flags );
01537 
01538     assert( scalar && data );
01539 
01540     if( (unsigned)(cn - 1) >= 4 )
01541         CV_Error( CV_StsOutOfRange, "The number of channels must be 1, 2, 3 or 4" );
01542 
01543     memset( scalar->val, 0, sizeof(scalar->val));
01544 
01545     switch( CV_MAT_DEPTH( flags ))
01546     {
01547     case CV_8U:
01548         while( cn-- )
01549             scalar->val[cn] = CV_8TO32F(((uchar*)data)[cn]);
01550         break;
01551     case CV_8S:
01552         while( cn-- )
01553             scalar->val[cn] = CV_8TO32F(((char*)data)[cn]);
01554         break;
01555     case CV_16U:
01556         while( cn-- )
01557             scalar->val[cn] = ((ushort*)data)[cn];
01558         break;
01559     case CV_16S:
01560         while( cn-- )
01561             scalar->val[cn] = ((short*)data)[cn];
01562         break;
01563     case CV_32S:
01564         while( cn-- )
01565             scalar->val[cn] = ((int*)data)[cn];
01566         break;
01567     case CV_32F:
01568         while( cn-- )
01569             scalar->val[cn] = ((float*)data)[cn];
01570         break;
01571     case CV_64F:
01572         while( cn-- )
01573             scalar->val[cn] = ((double*)data)[cn];
01574         break;
01575     default:
01576         assert(0);
01577         CV_Error( CV_BadDepth, "" );
01578     }
01579 }
01580 
01581 
01582 static double icvGetReal( const void* data, int type )
01583 {
01584     switch( type )
01585     {
01586     case CV_8U:
01587         return *(uchar*)data;
01588     case CV_8S:
01589         return *(char*)data;
01590     case CV_16U:
01591         return *(ushort*)data;
01592     case CV_16S:
01593         return *(short*)data;
01594     case CV_32S:
01595         return *(int*)data;
01596     case CV_32F:
01597         return *(float*)data;
01598     case CV_64F:
01599         return *(double*)data;
01600     }
01601 
01602     return 0;
01603 }
01604 
01605 
01606 static void icvSetReal( double value, const void* data, int type )
01607 {
01608     if( type < CV_32F )
01609     {
01610         int ivalue = cvRound(value);
01611         switch( type )
01612         {
01613         case CV_8U:
01614             *(uchar*)data = cv::saturate_cast<uchar>(ivalue);
01615             break;
01616         case CV_8S:
01617             *(schar*)data = cv::saturate_cast<schar>(ivalue);
01618             break;
01619         case CV_16U:
01620             *(ushort*)data = cv::saturate_cast<ushort>(ivalue);
01621             break;
01622         case CV_16S:
01623             *(short*)data = cv::saturate_cast<short>(ivalue);
01624             break;
01625         case CV_32S:
01626             *(int*)data = cv::saturate_cast<int>(ivalue);
01627             break;
01628         }
01629     }
01630     else
01631     {
01632         switch( type )
01633         {
01634         case CV_32F:
01635             *(float*)data = (float)value;
01636             break;
01637         case CV_64F:
01638             *(double*)data = value;
01639             break;
01640         }
01641     }
01642 }
01643 
01644 
01645 // Returns pointer to specified element of array (linear index is used)
01646 CV_IMPL  uchar*
01647 cvPtr1D( const CvArr* arr, int idx, int* _type )
01648 {
01649     uchar* ptr = 0;
01650     if( CV_IS_MAT( arr ))
01651     {
01652         CvMat* mat = (CvMat*)arr;
01653 
01654         int type = CV_MAT_TYPE(mat->type);
01655         int pix_size = CV_ELEM_SIZE(type);
01656 
01657         if( _type )
01658             *_type = type;
01659 
01660         // the first part is mul-free sufficient check
01661         // that the index is within the matrix
01662         if( (unsigned)idx >= (unsigned)(mat->rows + mat->cols - 1) &&
01663             (unsigned)idx >= (unsigned)(mat->rows*mat->cols))
01664             CV_Error( CV_StsOutOfRange, "index is out of range" );
01665 
01666         if( CV_IS_MAT_CONT(mat->type))
01667         {
01668             ptr = mat->data.ptr + (size_t)idx*pix_size;
01669         }
01670         else
01671         {
01672             int row, col;
01673             if( mat->cols == 1 )
01674                 row = idx, col = 0;
01675             else
01676                 row = idx/mat->cols, col = idx - row*mat->cols;
01677             ptr = mat->data.ptr + (size_t)row*mat->step + col*pix_size;
01678         }
01679     }
01680     else if( CV_IS_IMAGE_HDR( arr ))
01681     {
01682         IplImage* img = (IplImage*)arr;
01683         int width = !img->roi ? img->width : img->roi->width;
01684         int y = idx/width, x = idx - y*width;
01685 
01686         ptr = cvPtr2D( arr, y, x, _type );
01687     }
01688     else if( CV_IS_MATND( arr ))
01689     {
01690         CvMatND * mat = (CvMatND *)arr;
01691         int j, type = CV_MAT_TYPE(mat->type);
01692         size_t size = mat->dim[0].size;
01693 
01694         if( _type )
01695             *_type = type;
01696 
01697         for( j = 1; j < mat->dims; j++ )
01698             size *= mat->dim[j].size;
01699 
01700         if((unsigned)idx >= (unsigned)size )
01701             CV_Error( CV_StsOutOfRange, "index is out of range" );
01702 
01703         if( CV_IS_MAT_CONT(mat->type))
01704         {
01705             int pix_size = CV_ELEM_SIZE(type);
01706             ptr = mat->data.ptr + (size_t)idx*pix_size;
01707         }
01708         else
01709         {
01710             ptr = mat->data.ptr;
01711             for( j = mat->dims - 1; j >= 0; j-- )
01712             {
01713                 int sz = mat->dim[j].size;
01714                 if( sz )
01715                 {
01716                     int t = idx/sz;
01717                     ptr += (idx - t*sz)*mat->dim[j].step;
01718                     idx = t;
01719                 }
01720             }
01721         }
01722     }
01723     else if( CV_IS_SPARSE_MAT( arr ))
01724     {
01725         CvSparseMat* m = (CvSparseMat*)arr;
01726         if( m->dims == 1 )
01727             ptr = icvGetNodePtr( (CvSparseMat*)arr, &idx, _type, 1, 0 );
01728         else
01729         {
01730             int i, n = m->dims;
01731             CV_DbgAssert( n <= CV_MAX_DIM_HEAP );
01732             int _idx[CV_MAX_DIM_HEAP];
01733 
01734             for( i = n - 1; i >= 0; i-- )
01735             {
01736                 int t = idx / m->size[i];
01737                 _idx[i] = idx - t*m->size[i];
01738                 idx = t;
01739             }
01740             ptr = icvGetNodePtr( (CvSparseMat*)arr, _idx, _type, 1, 0 );
01741         }
01742     }
01743     else
01744     {
01745         CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
01746     }
01747 
01748     return ptr;
01749 }
01750 
01751 
01752 // Returns pointer to specified element of 2d array
01753 CV_IMPL  uchar*
01754 cvPtr2D( const CvArr* arr, int y, int x, int* _type )
01755 {
01756     uchar* ptr = 0;
01757     if( CV_IS_MAT( arr ))
01758     {
01759         CvMat* mat = (CvMat*)arr;
01760         int type;
01761 
01762         if( (unsigned)y >= (unsigned)(mat->rows) ||
01763             (unsigned)x >= (unsigned)(mat->cols) )
01764             CV_Error( CV_StsOutOfRange, "index is out of range" );
01765 
01766         type = CV_MAT_TYPE(mat->type);
01767         if( _type )
01768             *_type = type;
01769 
01770         ptr = mat->data.ptr + (size_t)y*mat->step + x*CV_ELEM_SIZE(type);
01771     }
01772     else if( CV_IS_IMAGE( arr ))
01773     {
01774         IplImage* img = (IplImage*)arr;
01775         int pix_size = (img->depth & 255) >> 3;
01776         int width, height;
01777         ptr = (uchar*)img->imageData;
01778 
01779         if( img->dataOrder == 0 )
01780             pix_size *= img->nChannels;
01781 
01782         if( img->roi )
01783         {
01784             width = img->roi->width;
01785             height = img->roi->height;
01786 
01787             ptr += img->roi->yOffset*img->widthStep +
01788                    img->roi->xOffset*pix_size;
01789 
01790             if( img->dataOrder )
01791             {
01792                 int coi = img->roi->coi;
01793                 if( !coi )
01794                     CV_Error( CV_BadCOI,
01795                         "COI must be non-null in case of planar images" );
01796                 ptr += (coi - 1)*img->imageSize;
01797             }
01798         }
01799         else
01800         {
01801             width = img->width;
01802             height = img->height;
01803         }
01804 
01805         if( (unsigned)y >= (unsigned)height ||
01806             (unsigned)x >= (unsigned)width )
01807             CV_Error( CV_StsOutOfRange, "index is out of range" );
01808 
01809         ptr += y*img->widthStep + x*pix_size;
01810 
01811         if( _type )
01812         {
01813             int type = IPL2CV_DEPTH(img->depth);
01814             if( type < 0 || (unsigned)(img->nChannels - 1) > 3 )
01815                 CV_Error( CV_StsUnsupportedFormat, "" );
01816 
01817             *_type = CV_MAKETYPE( type, img->nChannels );
01818         }
01819     }
01820     else if( CV_IS_MATND( arr ))
01821     {
01822         CvMatND * mat = (CvMatND *)arr;
01823 
01824         if( mat->dims != 2 ||
01825             (unsigned)y >= (unsigned)(mat->dim[0].size) ||
01826             (unsigned)x >= (unsigned)(mat->dim[1].size) )
01827             CV_Error( CV_StsOutOfRange, "index is out of range" );
01828 
01829         ptr = mat->data.ptr + (size_t)y*mat->dim[0].step + x*mat->dim[1].step;
01830         if( _type )
01831             *_type = CV_MAT_TYPE(mat->type);
01832     }
01833     else if( CV_IS_SPARSE_MAT( arr ))
01834     {
01835         int idx[] = { y, x };
01836         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, _type, 1, 0 );
01837     }
01838     else
01839     {
01840         CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
01841     }
01842 
01843     return ptr;
01844 }
01845 
01846 
01847 // Returns pointer to specified element of 3d array
01848 CV_IMPL  uchar*
01849 cvPtr3D( const CvArr* arr, int z, int y, int x, int* _type )
01850 {
01851     uchar* ptr = 0;
01852     if( CV_IS_MATND( arr ))
01853     {
01854         CvMatND * mat = (CvMatND *)arr;
01855 
01856         if( mat->dims != 3 ||
01857             (unsigned)z >= (unsigned)(mat->dim[0].size) ||
01858             (unsigned)y >= (unsigned)(mat->dim[1].size) ||
01859             (unsigned)x >= (unsigned)(mat->dim[2].size) )
01860             CV_Error( CV_StsOutOfRange, "index is out of range" );
01861 
01862         ptr = mat->data.ptr + (size_t)z*mat->dim[0].step +
01863               (size_t)y*mat->dim[1].step + x*mat->dim[2].step;
01864 
01865         if( _type )
01866             *_type = CV_MAT_TYPE(mat->type);
01867     }
01868     else if( CV_IS_SPARSE_MAT( arr ))
01869     {
01870         int idx[] = { z, y, x };
01871         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, _type, 1, 0 );
01872     }
01873     else
01874     {
01875         CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
01876     }
01877 
01878     return ptr;
01879 }
01880 
01881 
01882 // Returns pointer to specified element of n-d array
01883 CV_IMPL  uchar*
01884 cvPtrND( const CvArr* arr, const int* idx, int* _type,
01885          int create_node, unsigned* precalc_hashval )
01886 {
01887     uchar* ptr = 0;
01888     if( !idx )
01889         CV_Error( CV_StsNullPtr, "NULL pointer to indices" );
01890 
01891     if( CV_IS_SPARSE_MAT( arr ))
01892         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx,
01893                              _type, create_node, precalc_hashval );
01894     else if( CV_IS_MATND( arr ))
01895     {
01896         CvMatND * mat = (CvMatND *)arr;
01897         int i;
01898         ptr = mat->data.ptr;
01899 
01900         for( i = 0; i < mat->dims; i++ )
01901         {
01902             if( (unsigned)idx[i] >= (unsigned)(mat->dim[i].size) )
01903                 CV_Error( CV_StsOutOfRange, "index is out of range" );
01904             ptr += (size_t)idx[i]*mat->dim[i].step;
01905         }
01906 
01907         if( _type )
01908             *_type = CV_MAT_TYPE(mat->type);
01909     }
01910     else if( CV_IS_MAT_HDR(arr) || CV_IS_IMAGE_HDR(arr) )
01911         ptr = cvPtr2D( arr, idx[0], idx[1], _type );
01912     else
01913         CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
01914 
01915     return ptr;
01916 }
01917 
01918 
01919 // Returns specifed element of n-D array given linear index
01920 CV_IMPL  CvScalar 
01921 cvGet1D( const CvArr* arr, int idx )
01922 {
01923     CvScalar  scalar(0);
01924     int type = 0;
01925     uchar* ptr;
01926 
01927     if( CV_IS_MAT( arr ) && CV_IS_MAT_CONT( ((CvMat*)arr)->type ))
01928     {
01929         CvMat* mat = (CvMat*)arr;
01930 
01931         type = CV_MAT_TYPE(mat->type);
01932         int pix_size = CV_ELEM_SIZE(type);
01933 
01934         // the first part is mul-free sufficient check
01935         // that the index is within the matrix
01936         if( (unsigned)idx >= (unsigned)(mat->rows + mat->cols - 1) &&
01937             (unsigned)idx >= (unsigned)(mat->rows*mat->cols))
01938             CV_Error( CV_StsOutOfRange, "index is out of range" );
01939 
01940         ptr = mat->data.ptr + (size_t)idx*pix_size;
01941     }
01942     else if( !CV_IS_SPARSE_MAT( arr ) || ((CvSparseMat*)arr)->dims > 1 )
01943         ptr = cvPtr1D( arr, idx, &type );
01944     else
01945         ptr = icvGetNodePtr( (CvSparseMat*)arr, &idx, &type, 0, 0 );
01946 
01947     if( ptr )
01948         cvRawDataToScalar( ptr, type, &scalar );
01949 
01950     return scalar;
01951 }
01952 
01953 
01954 // Returns specifed element of 2D array
01955 CV_IMPL  CvScalar 
01956 cvGet2D( const CvArr* arr, int y, int x )
01957 {
01958     CvScalar  scalar(0);
01959     int type = 0;
01960     uchar* ptr;
01961 
01962     if( CV_IS_MAT( arr ))
01963     {
01964         CvMat* mat = (CvMat*)arr;
01965 
01966         if( (unsigned)y >= (unsigned)(mat->rows) ||
01967             (unsigned)x >= (unsigned)(mat->cols) )
01968             CV_Error( CV_StsOutOfRange, "index is out of range" );
01969 
01970         type = CV_MAT_TYPE(mat->type);
01971         ptr = mat->data.ptr + (size_t)y*mat->step + x*CV_ELEM_SIZE(type);
01972     }
01973     else if( !CV_IS_SPARSE_MAT( arr ))
01974         ptr = cvPtr2D( arr, y, x, &type );
01975     else
01976     {
01977         int idx[] = { y, x };
01978         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, 0, 0 );
01979     }
01980 
01981     if( ptr )
01982         cvRawDataToScalar( ptr, type, &scalar );
01983 
01984     return scalar;
01985 }
01986 
01987 
01988 // Returns specifed element of 3D array
01989 CV_IMPL  CvScalar 
01990 cvGet3D( const CvArr* arr, int z, int y, int x )
01991 {
01992     CvScalar  scalar(0);
01993     int type = 0;
01994     uchar* ptr;
01995 
01996     if( !CV_IS_SPARSE_MAT( arr ))
01997         ptr = cvPtr3D( arr, z, y, x, &type );
01998     else
01999     {
02000         int idx[] = { z, y, x };
02001         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, 0, 0 );
02002     }
02003 
02004     if( ptr )
02005         cvRawDataToScalar( ptr, type, &scalar );
02006     return scalar;
02007 }
02008 
02009 
02010 // Returns specifed element of nD array
02011 CV_IMPL  CvScalar 
02012 cvGetND( const CvArr* arr, const int* idx )
02013 {
02014     CvScalar  scalar(0);
02015     int type = 0;
02016     uchar* ptr;
02017 
02018     if( !CV_IS_SPARSE_MAT( arr ))
02019         ptr = cvPtrND( arr, idx, &type );
02020     else
02021         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, 0, 0 );
02022 
02023     if( ptr )
02024         cvRawDataToScalar( ptr, type, &scalar );
02025 
02026     return scalar;
02027 }
02028 
02029 
02030 // Returns specifed element of n-D array given linear index
02031 CV_IMPL  double
02032 cvGetReal1D( const CvArr* arr, int idx )
02033 {
02034     double value = 0;
02035     int type = 0;
02036     uchar* ptr;
02037 
02038     if( CV_IS_MAT( arr ) && CV_IS_MAT_CONT( ((CvMat*)arr)->type ))
02039     {
02040         CvMat* mat = (CvMat*)arr;
02041 
02042         type = CV_MAT_TYPE(mat->type);
02043         int pix_size = CV_ELEM_SIZE(type);
02044 
02045         // the first part is mul-free sufficient check
02046         // that the index is within the matrix
02047         if( (unsigned)idx >= (unsigned)(mat->rows + mat->cols - 1) &&
02048             (unsigned)idx >= (unsigned)(mat->rows*mat->cols))
02049             CV_Error( CV_StsOutOfRange, "index is out of range" );
02050 
02051         ptr = mat->data.ptr + (size_t)idx*pix_size;
02052     }
02053     else if( !CV_IS_SPARSE_MAT( arr ) || ((CvSparseMat*)arr)->dims > 1 )
02054         ptr = cvPtr1D( arr, idx, &type );
02055     else
02056         ptr = icvGetNodePtr( (CvSparseMat*)arr, &idx, &type, 0, 0 );
02057 
02058     if( ptr )
02059     {
02060         if( CV_MAT_CN( type ) > 1 )
02061             CV_Error( CV_BadNumChannels, "cvGetReal* support only single-channel arrays" );
02062 
02063         value = icvGetReal( ptr, type );
02064     }
02065     return value;
02066 }
02067 
02068 
02069 // Returns specifed element of 2D array
02070 CV_IMPL  double
02071 cvGetReal2D( const CvArr* arr, int y, int x )
02072 {
02073     double value = 0;
02074     int type = 0;
02075     uchar* ptr;
02076 
02077     if( CV_IS_MAT( arr ))
02078     {
02079         CvMat* mat = (CvMat*)arr;
02080 
02081         if( (unsigned)y >= (unsigned)(mat->rows) ||
02082             (unsigned)x >= (unsigned)(mat->cols) )
02083             CV_Error( CV_StsOutOfRange, "index is out of range" );
02084 
02085         type = CV_MAT_TYPE(mat->type);
02086         ptr = mat->data.ptr + (size_t)y*mat->step + x*CV_ELEM_SIZE(type);
02087     }
02088     else if( !CV_IS_SPARSE_MAT( arr ))
02089         ptr = cvPtr2D( arr, y, x, &type );
02090     else
02091     {
02092         int idx[] = { y, x };
02093         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, 0, 0 );
02094     }
02095 
02096     if( ptr )
02097     {
02098         if( CV_MAT_CN( type ) > 1 )
02099             CV_Error( CV_BadNumChannels, "cvGetReal* support only single-channel arrays" );
02100 
02101         value = icvGetReal( ptr, type );
02102     }
02103 
02104     return value;
02105 }
02106 
02107 
02108 // Returns specifed element of 3D array
02109 CV_IMPL  double
02110 cvGetReal3D( const CvArr* arr, int z, int y, int x )
02111 {
02112     double value = 0;
02113     int type = 0;
02114     uchar* ptr;
02115 
02116     if( !CV_IS_SPARSE_MAT( arr ))
02117         ptr = cvPtr3D( arr, z, y, x, &type );
02118     else
02119     {
02120         int idx[] = { z, y, x };
02121         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, 0, 0 );
02122     }
02123 
02124     if( ptr )
02125     {
02126         if( CV_MAT_CN( type ) > 1 )
02127             CV_Error( CV_BadNumChannels, "cvGetReal* support only single-channel arrays" );
02128 
02129         value = icvGetReal( ptr, type );
02130     }
02131 
02132     return value;
02133 }
02134 
02135 
02136 // Returns specifed element of nD array
02137 CV_IMPL  double
02138 cvGetRealND( const CvArr* arr, const int* idx )
02139 {
02140     double value = 0;
02141     int type = 0;
02142     uchar* ptr;
02143 
02144     if( !CV_IS_SPARSE_MAT( arr ))
02145         ptr = cvPtrND( arr, idx, &type );
02146     else
02147         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, 0, 0 );
02148 
02149     if( ptr )
02150     {
02151         if( CV_MAT_CN( type ) > 1 )
02152             CV_Error( CV_BadNumChannels, "cvGetReal* support only single-channel arrays" );
02153 
02154         value = icvGetReal( ptr, type );
02155     }
02156 
02157     return value;
02158 }
02159 
02160 
02161 // Assigns new value to specifed element of nD array given linear index
02162 CV_IMPL  void
02163 cvSet1D( CvArr* arr, int idx, CvScalar  scalar )
02164 {
02165     int type = 0;
02166     uchar* ptr;
02167 
02168     if( CV_IS_MAT( arr ) && CV_IS_MAT_CONT( ((CvMat*)arr)->type ))
02169     {
02170         CvMat* mat = (CvMat*)arr;
02171 
02172         type = CV_MAT_TYPE(mat->type);
02173         int pix_size = CV_ELEM_SIZE(type);
02174 
02175         // the first part is mul-free sufficient check
02176         // that the index is within the matrix
02177         if( (unsigned)idx >= (unsigned)(mat->rows + mat->cols - 1) &&
02178             (unsigned)idx >= (unsigned)(mat->rows*mat->cols))
02179             CV_Error( CV_StsOutOfRange, "index is out of range" );
02180 
02181         ptr = mat->data.ptr + (size_t)idx*pix_size;
02182     }
02183     else if( !CV_IS_SPARSE_MAT( arr ) || ((CvSparseMat*)arr)->dims > 1 )
02184         ptr = cvPtr1D( arr, idx, &type );
02185     else
02186         ptr = icvGetNodePtr( (CvSparseMat*)arr, &idx, &type, -1, 0 );
02187 
02188     cvScalarToRawData( &scalar, ptr, type );
02189 }
02190 
02191 
02192 // Assigns new value to specifed element of 2D array
02193 CV_IMPL  void
02194 cvSet2D( CvArr* arr, int y, int x, CvScalar  scalar )
02195 {
02196     int type = 0;
02197     uchar* ptr;
02198 
02199     if( CV_IS_MAT( arr ))
02200     {
02201         CvMat* mat = (CvMat*)arr;
02202 
02203         if( (unsigned)y >= (unsigned)(mat->rows) ||
02204             (unsigned)x >= (unsigned)(mat->cols) )
02205             CV_Error( CV_StsOutOfRange, "index is out of range" );
02206 
02207         type = CV_MAT_TYPE(mat->type);
02208         ptr = mat->data.ptr + (size_t)y*mat->step + x*CV_ELEM_SIZE(type);
02209     }
02210     else if( !CV_IS_SPARSE_MAT( arr ))
02211         ptr = cvPtr2D( arr, y, x, &type );
02212     else
02213     {
02214         int idx[] = { y, x };
02215         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, -1, 0 );
02216     }
02217     cvScalarToRawData( &scalar, ptr, type );
02218 }
02219 
02220 
02221 // Assigns new value to specifed element of 3D array
02222 CV_IMPL  void
02223 cvSet3D( CvArr* arr, int z, int y, int x, CvScalar  scalar )
02224 {
02225     int type = 0;
02226     uchar* ptr;
02227 
02228     if( !CV_IS_SPARSE_MAT( arr ))
02229         ptr = cvPtr3D( arr, z, y, x, &type );
02230     else
02231     {
02232         int idx[] = { z, y, x };
02233         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, -1, 0 );
02234     }
02235     cvScalarToRawData( &scalar, ptr, type );
02236 }
02237 
02238 
02239 // Assigns new value to specifed element of nD array
02240 CV_IMPL  void
02241 cvSetND( CvArr* arr, const int* idx, CvScalar  scalar )
02242 {
02243     int type = 0;
02244     uchar* ptr;
02245 
02246     if( !CV_IS_SPARSE_MAT( arr ))
02247         ptr = cvPtrND( arr, idx, &type );
02248     else
02249         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, -1, 0 );
02250     cvScalarToRawData( &scalar, ptr, type );
02251 }
02252 
02253 
02254 CV_IMPL  void
02255 cvSetReal1D( CvArr* arr, int idx, double value )
02256 {
02257     int type = 0;
02258     uchar* ptr;
02259 
02260     if( CV_IS_MAT( arr ) && CV_IS_MAT_CONT( ((CvMat*)arr)->type ))
02261     {
02262         CvMat* mat = (CvMat*)arr;
02263 
02264         type = CV_MAT_TYPE(mat->type);
02265         int pix_size = CV_ELEM_SIZE(type);
02266 
02267         // the first part is mul-free sufficient check
02268         // that the index is within the matrix
02269         if( (unsigned)idx >= (unsigned)(mat->rows + mat->cols - 1) &&
02270             (unsigned)idx >= (unsigned)(mat->rows*mat->cols))
02271             CV_Error( CV_StsOutOfRange, "index is out of range" );
02272 
02273         ptr = mat->data.ptr + (size_t)idx*pix_size;
02274     }
02275     else if( !CV_IS_SPARSE_MAT( arr ) || ((CvSparseMat*)arr)->dims > 1 )
02276         ptr = cvPtr1D( arr, idx, &type );
02277     else
02278         ptr = icvGetNodePtr( (CvSparseMat*)arr, &idx, &type, -1, 0 );
02279 
02280     if( CV_MAT_CN( type ) > 1 )
02281         CV_Error( CV_BadNumChannels, "cvSetReal* support only single-channel arrays" );
02282 
02283     if( ptr )
02284         icvSetReal( value, ptr, type );
02285 }
02286 
02287 
02288 CV_IMPL  void
02289 cvSetReal2D( CvArr* arr, int y, int x, double value )
02290 {
02291     int type = 0;
02292     uchar* ptr;
02293 
02294     if( CV_IS_MAT( arr ))
02295     {
02296         CvMat* mat = (CvMat*)arr;
02297 
02298         if( (unsigned)y >= (unsigned)(mat->rows) ||
02299             (unsigned)x >= (unsigned)(mat->cols) )
02300             CV_Error( CV_StsOutOfRange, "index is out of range" );
02301 
02302         type = CV_MAT_TYPE(mat->type);
02303         ptr = mat->data.ptr + (size_t)y*mat->step + x*CV_ELEM_SIZE(type);
02304     }
02305     else if( !CV_IS_SPARSE_MAT( arr ))
02306     {
02307         ptr = cvPtr2D( arr, y, x, &type );
02308     }
02309     else
02310     {
02311         int idx[] = { y, x };
02312         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, -1, 0 );
02313     }
02314     if( CV_MAT_CN( type ) > 1 )
02315         CV_Error( CV_BadNumChannels, "cvSetReal* support only single-channel arrays" );
02316 
02317     if( ptr )
02318         icvSetReal( value, ptr, type );
02319 }
02320 
02321 
02322 CV_IMPL  void
02323 cvSetReal3D( CvArr* arr, int z, int y, int x, double value )
02324 {
02325     int type = 0;
02326     uchar* ptr;
02327 
02328     if( !CV_IS_SPARSE_MAT( arr ))
02329         ptr = cvPtr3D( arr, z, y, x, &type );
02330     else
02331     {
02332         int idx[] = { z, y, x };
02333         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, -1, 0 );
02334     }
02335     if( CV_MAT_CN( type ) > 1 )
02336         CV_Error( CV_BadNumChannels, "cvSetReal* support only single-channel arrays" );
02337 
02338     if( ptr )
02339         icvSetReal( value, ptr, type );
02340 }
02341 
02342 
02343 CV_IMPL  void
02344 cvSetRealND( CvArr* arr, const int* idx, double value )
02345 {
02346     int type = 0;
02347     uchar* ptr;
02348 
02349     if( !CV_IS_SPARSE_MAT( arr ))
02350         ptr = cvPtrND( arr, idx, &type );
02351     else
02352         ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, -1, 0 );
02353 
02354     if( CV_MAT_CN( type ) > 1 )
02355         CV_Error( CV_BadNumChannels, "cvSetReal* support only single-channel arrays" );
02356 
02357     if( ptr )
02358         icvSetReal( value, ptr, type );
02359 }
02360 
02361 
02362 CV_IMPL void
02363 cvClearND( CvArr* arr, const int* idx )
02364 {
02365     if( !CV_IS_SPARSE_MAT( arr ))
02366     {
02367         int type;
02368         uchar* ptr;
02369         ptr = cvPtrND( arr, idx, &type );
02370         if( ptr )
02371             memset( ptr, 0, CV_ELEM_SIZE(type) );
02372     }
02373     else
02374         icvDeleteNode( (CvSparseMat*)arr, idx, 0 );
02375 }
02376 
02377 
02378 /****************************************************************************************\
02379 *                             Conversion to CvMat or IplImage                            *
02380 \****************************************************************************************/
02381 
02382 // convert array (CvMat or IplImage) to CvMat
02383 CV_IMPL CvMat*
02384 cvGetMat( const CvArr* array, CvMat* mat,
02385           int* pCOI, int allowND )
02386 {
02387     CvMat* result = 0;
02388     CvMat* src = (CvMat*)array;
02389     int coi = 0;
02390 
02391     if( !mat || !src )
02392         CV_Error( CV_StsNullPtr, "NULL array pointer is passed" );
02393 
02394     if( CV_IS_MAT_HDR(src))
02395     {
02396         if( !src->data.ptr )
02397             CV_Error( CV_StsNullPtr, "The matrix has NULL data pointer" );
02398 
02399         result = (CvMat*)src;
02400     }
02401     else if( CV_IS_IMAGE_HDR(src) )
02402     {
02403         const IplImage* img = (const IplImage*)src;
02404         int depth, order;
02405 
02406         if( img->imageData == 0 )
02407             CV_Error( CV_StsNullPtr, "The image has NULL data pointer" );
02408 
02409         depth = IPL2CV_DEPTH( img->depth );
02410         if( depth < 0 )
02411             CV_Error( CV_BadDepth, "" );
02412 
02413         order = img->dataOrder & (img->nChannels > 1 ? -1 : 0);
02414 
02415         if( img->roi )
02416         {
02417             if( order == IPL_DATA_ORDER_PLANE )
02418             {
02419                 int type = depth;
02420 
02421                 if( img->roi->coi == 0 )
02422                     CV_Error( CV_StsBadFlag,
02423                     "Images with planar data layout should be used with COI selected" );
02424 
02425                 cvInitMatHeader( mat, img->roi->height,
02426                                 img->roi->width, type,
02427                                 img->imageData + (img->roi->coi-1)*img->imageSize +
02428                                 img->roi->yOffset*img->widthStep +
02429                                 img->roi->xOffset*CV_ELEM_SIZE(type),
02430                                 img->widthStep );
02431             }
02432             else /* pixel order */
02433             {
02434                 int type = CV_MAKETYPE( depth, img->nChannels );
02435                 coi = img->roi->coi;
02436 
02437                 if( img->nChannels > CV_CN_MAX )
02438                     CV_Error( CV_BadNumChannels,
02439                         "The image is interleaved and has over CV_CN_MAX channels" );
02440 
02441                 cvInitMatHeader( mat, img->roi->height, img->roi->width,
02442                                  type, img->imageData +
02443                                  img->roi->yOffset*img->widthStep +
02444                                  img->roi->xOffset*CV_ELEM_SIZE(type),
02445                                  img->widthStep );
02446             }
02447         }
02448         else
02449         {
02450             int type = CV_MAKETYPE( depth, img->nChannels );
02451 
02452             if( order != IPL_DATA_ORDER_PIXEL )
02453                 CV_Error( CV_StsBadFlag, "Pixel order should be used with coi == 0" );
02454 
02455             cvInitMatHeader( mat, img->height, img->width, type,
02456                              img->imageData, img->widthStep );
02457         }
02458 
02459         result = mat;
02460     }
02461     else if( allowND && CV_IS_MATND_HDR(src) )
02462     {
02463         CvMatND * matnd = (CvMatND *)src;
02464         int size1 = matnd->dim[0].size, size2 = 1;
02465 
02466         if( !src->data.ptr )
02467             CV_Error( CV_StsNullPtr, "Input array has NULL data pointer" );
02468 
02469         if( !CV_IS_MAT_CONT( matnd->type ))
02470             CV_Error( CV_StsBadArg, "Only continuous nD arrays are supported here" );
02471 
02472         if( matnd->dims > 2 )
02473         {
02474             int i;
02475             for( i = 1; i < matnd->dims; i++ )
02476                 size2 *= matnd->dim[i].size;
02477         }
02478         else
02479             size2 = matnd->dims == 1 ? 1 : matnd->dim[1].size;
02480 
02481         mat->refcount = 0;
02482         mat->hdr_refcount = 0;
02483         mat->data.ptr = matnd->data.ptr;
02484         mat->rows = size1;
02485         mat->cols = size2;
02486         mat->type = CV_MAT_TYPE(matnd->type) | CV_MAT_MAGIC_VAL | CV_MAT_CONT_FLAG;
02487         mat->step = size2*CV_ELEM_SIZE(matnd->type);
02488         mat->step &= size1 > 1 ? -1 : 0;
02489 
02490         icvCheckHuge( mat );
02491         result = mat;
02492     }
02493     else
02494         CV_Error( CV_StsBadFlag, "Unrecognized or unsupported array type" );
02495 
02496     if( pCOI )
02497         *pCOI = coi;
02498 
02499     return result;
02500 }
02501 
02502 
02503 CV_IMPL CvArr*
02504 cvReshapeMatND( const CvArr* arr,
02505                 int sizeof_header, CvArr* _header,
02506                 int new_cn, int new_dims, int* new_sizes )
02507 {
02508     CvArr* result = 0;
02509     int dims, coi = 0;
02510 
02511     if( !arr || !_header )
02512         CV_Error( CV_StsNullPtr, "NULL pointer to array or destination header" );
02513 
02514     if( new_cn == 0 && new_dims == 0 )
02515         CV_Error( CV_StsBadArg, "None of array parameters is changed: dummy call?" );
02516 
02517     dims = cvGetDims( arr );
02518 
02519     if( new_dims == 0 )
02520     {
02521         new_sizes = 0;
02522         new_dims = dims;
02523     }
02524     else if( new_dims == 1 )
02525     {
02526         new_sizes = 0;
02527     }
02528     else
02529     {
02530         if( new_dims <= 0 || new_dims > CV_MAX_DIM )
02531             CV_Error( CV_StsOutOfRange, "Non-positive or too large number of dimensions" );
02532         if( !new_sizes )
02533             CV_Error( CV_StsNullPtr, "New dimension sizes are not specified" );
02534     }
02535 
02536     if( new_dims <= 2 )
02537     {
02538         CvMat* mat = (CvMat*)arr;
02539         CvMat header;
02540         int* refcount = 0;
02541         int  hdr_refcount = 0;
02542         int  total_width, new_rows, cn;
02543 
02544         if( sizeof_header != sizeof(CvMat) && sizeof_header != sizeof(CvMatND ) )
02545             CV_Error( CV_StsBadArg, "The output header should be CvMat or CvMatND" );
02546 
02547         if( mat == (CvMat*)_header )
02548         {
02549             refcount = mat->refcount;
02550             hdr_refcount = mat->hdr_refcount;
02551         }
02552 
02553         if( !CV_IS_MAT( mat ))
02554             mat = cvGetMat( mat, &header, &coi, 1 );
02555 
02556         cn = CV_MAT_CN( mat->type );
02557         total_width = mat->cols * cn;
02558 
02559         if( new_cn == 0 )
02560             new_cn = cn;
02561 
02562         if( new_sizes )
02563             new_rows = new_sizes[0];
02564         else if( new_dims == 1 )
02565             new_rows = total_width*mat->rows/new_cn;
02566         else
02567         {
02568             new_rows = mat->rows;
02569             if( new_cn > total_width )
02570                 new_rows = mat->rows * total_width / new_cn;
02571         }
02572 
02573         if( new_rows != mat->rows )
02574         {
02575             int total_size = total_width * mat->rows;
02576 
02577             if( !CV_IS_MAT_CONT( mat->type ))
02578                 CV_Error( CV_BadStep,
02579                 "The matrix is not continuous so the number of rows can not be changed" );
02580 
02581             total_width = total_size / new_rows;
02582 
02583             if( total_width * new_rows != total_size )
02584                 CV_Error( CV_StsBadArg, "The total number of matrix elements "
02585                                         "is not divisible by the new number of rows" );
02586         }
02587 
02588         header.rows = new_rows;
02589         header.cols = total_width / new_cn;
02590 
02591         if( header.cols * new_cn != total_width ||
02592             (new_sizes && header.cols != new_sizes[1]) )
02593             CV_Error( CV_StsBadArg, "The total matrix width is not "
02594                             "divisible by the new number of columns" );
02595 
02596         header.type = (mat->type & ~CV_MAT_TYPE_MASK) | CV_MAKETYPE(mat->type, new_cn);
02597         header.step = header.cols * CV_ELEM_SIZE(mat->type);
02598         header.step &= new_rows > 1 ? -1 : 0;
02599         header.refcount = refcount;
02600         header.hdr_refcount = hdr_refcount;
02601 
02602         if( sizeof_header == sizeof(CvMat) )
02603             *(CvMat*)_header = header;
02604         else
02605         {
02606             CvMatND * __header = (CvMatND *)_header;
02607             cvGetMatND(&header, __header, 0);
02608             if( new_dims > 0 )
02609                 __header->dims = new_dims;
02610         }
02611     }
02612     else
02613     {
02614         CvMatND * header = (CvMatND *)_header;
02615 
02616         if( sizeof_header != sizeof(CvMatND ))
02617             CV_Error( CV_StsBadSize, "The output header should be CvMatND" );
02618 
02619         if( !new_sizes )
02620         {
02621             if( !CV_IS_MATND( arr ))
02622                 CV_Error( CV_StsBadArg, "The input array must be CvMatND" );
02623 
02624             {
02625             CvMatND * mat = (CvMatND *)arr;
02626             assert( new_cn > 0 );
02627             int last_dim_size = mat->dim[mat->dims-1].size*CV_MAT_CN(mat->type);
02628             int new_size = last_dim_size/new_cn;
02629 
02630             if( new_size*new_cn != last_dim_size )
02631                 CV_Error( CV_StsBadArg,
02632                 "The last dimension full size is not divisible by new number of channels");
02633 
02634             if( mat != header )
02635             {
02636                 memcpy( header, mat, sizeof(*header));
02637                 header->refcount = 0;
02638                 header->hdr_refcount = 0;
02639             }
02640 
02641             header->dim[header->dims-1].size = new_size;
02642             header->type = (header->type & ~CV_MAT_TYPE_MASK) | CV_MAKETYPE(header->type, new_cn);
02643             }
02644         }
02645         else
02646         {
02647             CvMatND  stub;
02648             CvMatND * mat = (CvMatND *)arr;
02649             int i, size1, size2;
02650             int step;
02651 
02652             if( new_cn != 0 )
02653                 CV_Error( CV_StsBadArg,
02654                 "Simultaneous change of shape and number of channels is not supported. "
02655                 "Do it by 2 separate calls" );
02656 
02657             if( !CV_IS_MATND( mat ))
02658             {
02659                 cvGetMatND( mat, &stub, &coi );
02660                 mat = &stub;
02661             }
02662 
02663             if( CV_IS_MAT_CONT( mat->type ))
02664                 CV_Error( CV_StsBadArg, "Non-continuous nD arrays are not supported" );
02665 
02666             size1 = mat->dim[0].size;
02667             for( i = 1; i < dims; i++ )
02668                 size1 *= mat->dim[i].size;
02669 
02670             size2 = 1;
02671             for( i = 0; i < new_dims; i++ )
02672             {
02673                 if( new_sizes[i] <= 0 )
02674                     CV_Error( CV_StsBadSize,
02675                     "One of new dimension sizes is non-positive" );
02676                 size2 *= new_sizes[i];
02677             }
02678 
02679             if( size1 != size2 )
02680                 CV_Error( CV_StsBadSize,
02681                 "Number of elements in the original and reshaped array is different" );
02682 
02683             if( header != mat )
02684             {
02685                 header->refcount = 0;
02686                 header->hdr_refcount = 0;
02687             }
02688 
02689             header->dims = new_dims;
02690             header->type = mat->type;
02691             header->data.ptr = mat->data.ptr;
02692             step = CV_ELEM_SIZE(header->type);
02693 
02694             for( i = new_dims - 1; i >= 0; i-- )
02695             {
02696                 header->dim[i].size = new_sizes[i];
02697                 header->dim[i].step = step;
02698                 step *= new_sizes[i];
02699             }
02700         }
02701     }
02702 
02703     if( coi )
02704         CV_Error( CV_BadCOI, "COI is not supported by this operation" );
02705 
02706     result = _header;
02707     return result;
02708 }
02709 
02710 
02711 CV_IMPL CvMat*
02712 cvReshape( const CvArr* array, CvMat* header,
02713            int new_cn, int new_rows )
02714 {
02715     CvMat* result = 0;
02716     CvMat *mat = (CvMat*)array;
02717     int total_width, new_width;
02718 
02719     if( !header )
02720         CV_Error( CV_StsNullPtr, "" );
02721 
02722     if( !CV_IS_MAT( mat ))
02723     {
02724         int coi = 0;
02725         mat = cvGetMat( mat, header, &coi, 1 );
02726         if( coi )
02727             CV_Error( CV_BadCOI, "COI is not supported" );
02728     }
02729 
02730     if( new_cn == 0 )
02731         new_cn = CV_MAT_CN(mat->type);
02732     else if( (unsigned)(new_cn - 1) > 3 )
02733         CV_Error( CV_BadNumChannels, "" );
02734 
02735     if( mat != header )
02736     {
02737         int hdr_refcount = header->hdr_refcount;
02738         *header = *mat;
02739         header->refcount = 0;
02740         header->hdr_refcount = hdr_refcount;
02741     }
02742 
02743     total_width = mat->cols * CV_MAT_CN( mat->type );
02744 
02745     if( (new_cn > total_width || total_width % new_cn != 0) && new_rows == 0 )
02746         new_rows = mat->rows * total_width / new_cn;
02747 
02748     if( new_rows == 0 || new_rows == mat->rows )
02749     {
02750         header->rows = mat->rows;
02751         header->step = mat->step;
02752     }
02753     else
02754     {
02755         int total_size = total_width * mat->rows;
02756         if( !CV_IS_MAT_CONT( mat->type ))
02757             CV_Error( CV_BadStep,
02758             "The matrix is not continuous, thus its number of rows can not be changed" );
02759 
02760         if( (unsigned)new_rows > (unsigned)total_size )
02761             CV_Error( CV_StsOutOfRange, "Bad new number of rows" );
02762 
02763         total_width = total_size / new_rows;
02764 
02765         if( total_width * new_rows != total_size )
02766             CV_Error( CV_StsBadArg, "The total number of matrix elements "
02767                                     "is not divisible by the new number of rows" );
02768 
02769         header->rows = new_rows;
02770         header->step = total_width * CV_ELEM_SIZE1(mat->type);
02771     }
02772 
02773     new_width = total_width / new_cn;
02774 
02775     if( new_width * new_cn != total_width )
02776         CV_Error( CV_BadNumChannels,
02777         "The total width is not divisible by the new number of channels" );
02778 
02779     header->cols = new_width;
02780     header->type = (mat->type  & ~CV_MAT_TYPE_MASK) | CV_MAKETYPE(mat->type, new_cn);
02781 
02782     result = header;
02783     return  result;
02784 }
02785 
02786 
02787 // convert array (CvMat or IplImage) to IplImage
02788 CV_IMPL IplImage*
02789 cvGetImage( const CvArr* array, IplImage* img )
02790 {
02791     IplImage* result = 0;
02792     const IplImage* src = (const IplImage*)array;
02793 
02794     if( !img )
02795         CV_Error( CV_StsNullPtr, "" );
02796 
02797     if( !CV_IS_IMAGE_HDR(src) )
02798     {
02799         const CvMat* mat = (const CvMat*)src;
02800 
02801         if( !CV_IS_MAT_HDR(mat))
02802             CV_Error( CV_StsBadFlag, "" );
02803 
02804         if( mat->data.ptr == 0 )
02805             CV_Error( CV_StsNullPtr, "" );
02806 
02807         int depth = cvIplDepth(mat->type);
02808 
02809         cvInitImageHeader( img, cvSize(mat->cols, mat->rows),
02810                            depth, CV_MAT_CN(mat->type) );
02811         cvSetData( img, mat->data.ptr, mat->step );
02812 
02813         result = img;
02814     }
02815     else
02816     {
02817         result = (IplImage*)src;
02818     }
02819 
02820     return result;
02821 }
02822 
02823 
02824 /****************************************************************************************\
02825 *                               IplImage-specific functions                              *
02826 \****************************************************************************************/
02827 
02828 static IplROI* icvCreateROI( int coi, int xOffset, int yOffset, int width, int height )
02829 {
02830     IplROI *roi = 0;
02831     if( !CvIPL.createROI )
02832     {
02833         roi = (IplROI*)cvAlloc( sizeof(*roi));
02834 
02835         roi->coi = coi;
02836         roi->xOffset = xOffset;
02837         roi->yOffset = yOffset;
02838         roi->width = width;
02839         roi->height = height;
02840     }
02841     else
02842     {
02843         roi = CvIPL.createROI( coi, xOffset, yOffset, width, height );
02844     }
02845 
02846     return roi;
02847 }
02848 
02849 static  void
02850 icvGetColorModel( int nchannels, const char** colorModel, const char** channelSeq )
02851 {
02852     static const char* tab[][2] =
02853     {
02854         {"GRAY", "GRAY"},
02855         {"",""},
02856         {"RGB","BGR"},
02857         {"RGB","BGRA"}
02858     };
02859 
02860     nchannels--;
02861     *colorModel = *channelSeq = "";
02862 
02863     if( (unsigned)nchannels <= 3 )
02864     {
02865         *colorModel = tab[nchannels][0];
02866         *channelSeq = tab[nchannels][1];
02867     }
02868 }
02869 
02870 
02871 // create IplImage header
02872 CV_IMPL IplImage *
02873 cvCreateImageHeader( CvSize size, int depth, int channels )
02874 {
02875     IplImage *img = 0;
02876 
02877     if( !CvIPL.createHeader )
02878     {
02879         img = (IplImage *)cvAlloc( sizeof( *img ));
02880         cvInitImageHeader( img, size, depth, channels, IPL_ORIGIN_TL,
02881                                     CV_DEFAULT_IMAGE_ROW_ALIGN );
02882     }
02883     else
02884     {
02885         const char *colorModel, *channelSeq;
02886 
02887         icvGetColorModel( channels, &colorModel, &channelSeq );
02888 
02889         img = CvIPL.createHeader( channels, 0, depth, (char*)colorModel, (char*)channelSeq,
02890                                   IPL_DATA_ORDER_PIXEL, IPL_ORIGIN_TL,
02891                                   CV_DEFAULT_IMAGE_ROW_ALIGN,
02892                                   size.width, size.height, 0, 0, 0, 0 );
02893     }
02894 
02895     return img;
02896 }
02897 
02898 
02899 // create IplImage header and allocate underlying data
02900 CV_IMPL IplImage *
02901 cvCreateImage( CvSize size, int depth, int channels )
02902 {
02903     IplImage *img = cvCreateImageHeader( size, depth, channels );
02904     assert( img );
02905     cvCreateData( img );
02906 
02907     return img;
02908 }
02909 
02910 
02911 // initialize IplImage header, allocated by the user
02912 CV_IMPL IplImage*
02913 cvInitImageHeader( IplImage * image, CvSize size, int depth,
02914                    int channels, int origin, int align )
02915 {
02916     const char *colorModel, *channelSeq;
02917 
02918     if( !image )
02919         CV_Error( CV_HeaderIsNull, "null pointer to header" );
02920 
02921     memset( image, 0, sizeof( *image ));
02922     image->nSize = sizeof( *image );
02923 
02924     icvGetColorModel( channels, &colorModel, &channelSeq );
02925     strncpy( image->colorModel, colorModel, 4 );
02926     strncpy( image->channelSeq, channelSeq, 4 );
02927 
02928     if( size.width < 0 || size.height < 0 )
02929         CV_Error( CV_BadROISize, "Bad input roi" );
02930 
02931     if( (depth != (int)IPL_DEPTH_1U && depth != (int)IPL_DEPTH_8U &&
02932          depth != (int)IPL_DEPTH_8S && depth != (int)IPL_DEPTH_16U &&
02933          depth != (int)IPL_DEPTH_16S && depth != (int)IPL_DEPTH_32S &&
02934          depth != (int)IPL_DEPTH_32F && depth != (int)IPL_DEPTH_64F) ||
02935          channels < 0 )
02936         CV_Error( CV_BadDepth, "Unsupported format" );
02937     if( origin != CV_ORIGIN_BL && origin != CV_ORIGIN_TL )
02938         CV_Error( CV_BadOrigin, "Bad input origin" );
02939 
02940     if( align != 4 && align != 8 )
02941         CV_Error( CV_BadAlign, "Bad input align" );
02942 
02943     image->width = size.width;
02944     image->height = size.height;
02945 
02946     if( image->roi )
02947     {
02948         image->roi->coi = 0;
02949         image->roi->xOffset = image->roi->yOffset = 0;
02950         image->roi->width = size.width;
02951         image->roi->height = size.height;
02952     }
02953 
02954     image->nChannels = MAX( channels, 1 );
02955     image->depth = depth;
02956     image->align = align;
02957     image->widthStep = (((image->width * image->nChannels *
02958          (image->depth & ~IPL_DEPTH_SIGN) + 7)/8)+ align - 1) & (~(align - 1));
02959     image->origin = origin;
02960     image->imageSize = image->widthStep * image->height;
02961 
02962     return image;
02963 }
02964 
02965 
02966 CV_IMPL void
02967 cvReleaseImageHeader( IplImage** image )
02968 {
02969     if( !image )
02970         CV_Error( CV_StsNullPtr, "" );
02971 
02972     if( *image )
02973     {
02974         IplImage* img = *image;
02975         *image = 0;
02976 
02977         if( !CvIPL.deallocate )
02978         {
02979             cvFree( &img->roi );
02980             cvFree( &img );
02981         }
02982         else
02983         {
02984             CvIPL.deallocate( img, IPL_IMAGE_HEADER | IPL_IMAGE_ROI );
02985         }
02986     }
02987 }
02988 
02989 
02990 CV_IMPL void
02991 cvReleaseImage( IplImage ** image )
02992 {
02993     if( !image )
02994         CV_Error( CV_StsNullPtr, "" );
02995 
02996     if( *image )
02997     {
02998         IplImage* img = *image;
02999         *image = 0;
03000 
03001         cvReleaseData( img );
03002         cvReleaseImageHeader( &img );
03003     }
03004 }
03005 
03006 
03007 CV_IMPL void
03008 cvSetImageROI( IplImage* image, CvRect  rect )
03009 {
03010     if( !image )
03011         CV_Error( CV_HeaderIsNull, "" );
03012 
03013     // allow zero ROI width or height
03014     CV_Assert( rect.width >= 0 && rect.height >= 0 &&
03015                rect.x < image->width && rect.y < image->height &&
03016                rect.x + rect.width >= (int)(rect.width > 0) &&
03017                rect.y + rect.height >= (int)(rect.height > 0) );
03018 
03019     rect.width += rect.x;
03020     rect.height += rect.y;
03021 
03022     rect.x = std::max(rect.x, 0);
03023     rect.y = std::max(rect.y, 0);
03024     rect.width = std::min(rect.width, image->width);
03025     rect.height = std::min(rect.height, image->height);
03026 
03027     rect.width -= rect.x;
03028     rect.height -= rect.y;
03029 
03030     if( image->roi )
03031     {
03032         image->roi->xOffset = rect.x;
03033         image->roi->yOffset = rect.y;
03034         image->roi->width = rect.width;
03035         image->roi->height = rect.height;
03036     }
03037     else
03038         image->roi = icvCreateROI( 0, rect.x, rect.y, rect.width, rect.height );
03039 }
03040 
03041 
03042 CV_IMPL void
03043 cvResetImageROI( IplImage* image )
03044 {
03045     if( !image )
03046         CV_Error( CV_HeaderIsNull, "" );
03047 
03048     if( image->roi )
03049     {
03050         if( !CvIPL.deallocate )
03051         {
03052             cvFree( &image->roi );
03053         }
03054         else
03055         {
03056             CvIPL.deallocate( image, IPL_IMAGE_ROI );
03057             image->roi = 0;
03058         }
03059     }
03060 }
03061 
03062 
03063 CV_IMPL CvRect 
03064 cvGetImageROI( const IplImage* img )
03065 {
03066     CvRect  rect;
03067     if( !img )
03068         CV_Error( CV_StsNullPtr, "Null pointer to image" );
03069 
03070     if( img->roi )
03071         rect = cvRect( img->roi->xOffset, img->roi->yOffset,
03072                        img->roi->width, img->roi->height );
03073     else
03074         rect = cvRect( 0, 0, img->width, img->height );
03075 
03076     return rect;
03077 }
03078 
03079 
03080 CV_IMPL void
03081 cvSetImageCOI( IplImage* image, int coi )
03082 {
03083     if( !image )
03084         CV_Error( CV_HeaderIsNull, "" );
03085 
03086     if( (unsigned)coi > (unsigned)(image->nChannels) )
03087         CV_Error( CV_BadCOI, "" );
03088 
03089     if( image->roi || coi != 0 )
03090     {
03091         if( image->roi )
03092         {
03093             image->roi->coi = coi;
03094         }
03095         else
03096         {
03097             image->roi = icvCreateROI( coi, 0, 0, image->width, image->height );
03098         }
03099     }
03100 }
03101 
03102 
03103 CV_IMPL int
03104 cvGetImageCOI( const IplImage* image )
03105 {
03106     if( !image )
03107         CV_Error( CV_HeaderIsNull, "" );
03108 
03109     return image->roi ? image->roi->coi : 0;
03110 }
03111 
03112 
03113 CV_IMPL IplImage*
03114 cvCloneImage( const IplImage* src )
03115 {
03116     IplImage* dst = 0;
03117 
03118     if( !CV_IS_IMAGE_HDR( src ))
03119         CV_Error( CV_StsBadArg, "Bad image header" );
03120 
03121     if( !CvIPL.cloneImage )
03122     {
03123         dst = (IplImage*)cvAlloc( sizeof(*dst));
03124 
03125         memcpy( dst, src, sizeof(*src));
03126         dst->imageData = dst->imageDataOrigin = 0;
03127         dst->roi = 0;
03128 
03129         if( src->roi )
03130         {
03131             dst->roi = icvCreateROI( src->roi->coi, src->roi->xOffset,
03132                           src->roi->yOffset, src->roi->width, src->roi->height );
03133         }
03134 
03135         if( src->imageData )
03136         {
03137             int size = src->imageSize;
03138             cvCreateData( dst );
03139             memcpy( dst->imageData, src->imageData, size );
03140         }
03141     }
03142     else
03143         dst = CvIPL.cloneImage( src );
03144 
03145     return dst;
03146 }
03147 
03148 
03149 /****************************************************************************************\
03150 *                            Additional operations on CvTermCriteria                     *
03151 \****************************************************************************************/
03152 
03153 CV_IMPL CvTermCriteria 
03154 cvCheckTermCriteria( CvTermCriteria  criteria, double default_eps,
03155                      int default_max_iters )
03156 {
03157     CvTermCriteria  crit;
03158 
03159     crit.type = CV_TERMCRIT_ITER|CV_TERMCRIT_EPS;
03160     crit.max_iter = default_max_iters;
03161     crit.epsilon = (float)default_eps;
03162 
03163     if( (criteria.type & ~(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER)) != 0 )
03164         CV_Error( CV_StsBadArg,
03165                   "Unknown type of term criteria" );
03166 
03167     if( (criteria.type & CV_TERMCRIT_ITER) != 0 )
03168     {
03169         if( criteria.max_iter <= 0 )
03170             CV_Error( CV_StsBadArg,
03171                   "Iterations flag is set and maximum number of iterations is <= 0" );
03172         crit.max_iter = criteria.max_iter;
03173     }
03174 
03175     if( (criteria.type & CV_TERMCRIT_EPS) != 0 )
03176     {
03177         if( criteria.epsilon < 0 )
03178             CV_Error( CV_StsBadArg, "Accuracy flag is set and epsilon is < 0" );
03179 
03180         crit.epsilon = criteria.epsilon;
03181     }
03182 
03183     if( (criteria.type & (CV_TERMCRIT_EPS | CV_TERMCRIT_ITER)) == 0 )
03184         CV_Error( CV_StsBadArg,
03185                   "Neither accuracy nor maximum iterations "
03186                   "number flags are set in criteria type" );
03187 
03188     crit.epsilon = (float)MAX( 0, crit.epsilon );
03189     crit.max_iter = MAX( 1, crit.max_iter );
03190 
03191     return crit;
03192 }
03193 
03194 namespace cv
03195 {
03196 
03197 template<> void DefaultDeleter<CvMat>::operator ()(CvMat* obj) const
03198 { cvReleaseMat(&obj); }
03199 
03200 template<> void DefaultDeleter<IplImage>::operator ()(IplImage* obj) const
03201 { cvReleaseImage(&obj); }
03202 
03203 template<> void DefaultDeleter<CvMatND>::operator ()(CvMatND * obj) const
03204 { cvReleaseMatND(&obj); }
03205 
03206 template<> void DefaultDeleter<CvSparseMat>::operator ()(CvSparseMat* obj) const
03207 { cvReleaseSparseMat(&obj); }
03208 
03209 template<> void DefaultDeleter<CvMemStorage>::operator ()(CvMemStorage* obj) const
03210 { cvReleaseMemStorage(&obj); }
03211 
03212 template<> void DefaultDeleter<CvFileStorage>::operator ()(CvFileStorage* obj) const
03213 { cvReleaseFileStorage(&obj); }
03214 
03215 }
03216 
03217 /* End of file. */
03218