-/*M///////////////////////////////////////////////////////////////////////////////////////\r
-//\r
-// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.\r
-//\r
-// By downloading, copying, installing or using the software you agree to this license.\r
-// If you do not agree to this license, do not download, install,\r
-// copy or use the software.\r
-//\r
-//\r
-// Intel License Agreement\r
-// For Open Source Computer Vision Library\r
-//\r
-// Copyright (C) 2000, Intel Corporation, all rights reserved.\r
-// Third party copyrights are property of their respective owners.\r
-//\r
-// Redistribution and use in source and binary forms, with or without modification,\r
-// are permitted provided that the following conditions are met:\r
-//\r
-// * Redistribution's of source code must retain the above copyright notice,\r
-// this list of conditions and the following disclaimer.\r
-//\r
-// * Redistribution's in binary form must reproduce the above copyright notice,\r
-// this list of conditions and the following disclaimer in the documentation\r
-// and/or other materials provided with the distribution.\r
-//\r
-// * The name of Intel Corporation may not be used to endorse or promote products\r
-// derived from this software without specific prior written permission.\r
-//\r
-// This software is provided by the copyright holders and contributors "as is" and\r
-// any express or implied warranties, including, but not limited to, the implied\r
-// warranties of merchantability and fitness for a particular purpose are disclaimed.\r
-// In no event shall the Intel Corporation or contributors be liable for any direct,\r
-// indirect, incidental, special, exemplary, or consequential damages\r
-// (including, but not limited to, procurement of substitute goods or services;\r
-// loss of use, data, or profits; or business interruption) however caused\r
-// and on any theory of liability, whether in contract, strict liability,\r
-// or tort (including negligence or otherwise) arising in any way out of\r
-// the use of this software, even if advised of the possibility of such damage.\r
-//\r
-//M*/\r
-\r
-/* ////////////////////////////////////////////////////////////////////\r
-//\r
-// CvMat, CvMatND, CvSparceMat and IplImage support functions\r
-// (creation, deletion, copying, retrieving and setting elements etc.)\r
-//\r
-// */\r
-\r
-#include "_cxcore.h"\r
-\r
-\r
-static struct\r
-{\r
- Cv_iplCreateImageHeader createHeader;\r
- Cv_iplAllocateImageData allocateData;\r
- Cv_iplDeallocate deallocate;\r
- Cv_iplCreateROI createROI;\r
- Cv_iplCloneImage cloneImage;\r
-}\r
-CvIPL;\r
-\r
-// Makes the library use native IPL image allocators\r
-CV_IMPL void\r
-cvSetIPLAllocators( Cv_iplCreateImageHeader createHeader,\r
- Cv_iplAllocateImageData allocateData,\r
- Cv_iplDeallocate deallocate,\r
- Cv_iplCreateROI createROI,\r
- Cv_iplCloneImage cloneImage )\r
-{\r
- if( !createHeader || !allocateData || !deallocate || !createROI || !cloneImage )\r
- {\r
- if( createHeader || allocateData || deallocate || createROI || cloneImage )\r
- CV_Error( CV_StsBadArg, "Either all the pointers should be null or "\r
- "they all should be non-null" );\r
- }\r
-\r
- CvIPL.createHeader = createHeader;\r
- CvIPL.allocateData = allocateData;\r
- CvIPL.deallocate = deallocate;\r
- CvIPL.createROI = createROI;\r
- CvIPL.cloneImage = cloneImage;\r
-}\r
-\r
-\r
-/****************************************************************************************\\r
-* CvMat creation and basic operations *\r
-\****************************************************************************************/\r
-\r
-// Creates CvMat and underlying data\r
-CV_IMPL CvMat*\r
-cvCreateMat( int height, int width, int type )\r
-{\r
- CvMat* arr = cvCreateMatHeader( height, width, type );\r
- cvCreateData( arr );\r
-\r
- return arr;\r
-}\r
-\r
-\r
-static void icvCheckHuge( CvMat* arr )\r
-{\r
- if( (int64)arr->step*arr->rows > INT_MAX )\r
- arr->type &= ~CV_MAT_CONT_FLAG;\r
-}\r
-\r
-// Creates CvMat header only\r
-CV_IMPL CvMat*\r
-cvCreateMatHeader( int rows, int cols, int type )\r
-{\r
- type = CV_MAT_TYPE(type);\r
-\r
- if( rows <= 0 || cols <= 0 )\r
- CV_Error( CV_StsBadSize, "Non-positive width or height" );\r
-\r
- int min_step = CV_ELEM_SIZE(type)*cols;\r
- if( min_step <= 0 )\r
- CV_Error( CV_StsUnsupportedFormat, "Invalid matrix type" );\r
-\r
- CvMat* arr = (CvMat*)cvAlloc( sizeof(*arr));\r
-\r
- arr->step = rows == 1 ? 0 : cvAlign(min_step, CV_DEFAULT_MAT_ROW_ALIGN);\r
- arr->type = CV_MAT_MAGIC_VAL | type |\r
- (arr->step == 0 || arr->step == min_step ? CV_MAT_CONT_FLAG : 0);\r
- arr->rows = rows;\r
- arr->cols = cols;\r
- arr->data.ptr = 0;\r
- arr->refcount = 0;\r
- arr->hdr_refcount = 1;\r
-\r
- icvCheckHuge( arr );\r
- return arr;\r
-}\r
-\r
-\r
-// Initializes CvMat header, allocated by the user\r
-CV_IMPL CvMat*\r
-cvInitMatHeader( CvMat* arr, int rows, int cols,\r
- int type, void* data, int step )\r
-{\r
- if( !arr )\r
- CV_Error( CV_StsNullPtr, "" );\r
-\r
- if( (unsigned)CV_MAT_DEPTH(type) > CV_DEPTH_MAX )\r
- CV_Error( CV_BadNumChannels, "" );\r
-\r
- if( rows <= 0 || cols <= 0 )\r
- CV_Error( CV_StsBadSize, "Non-positive cols or rows" );\r
- \r
- type = CV_MAT_TYPE( type );\r
- arr->type = type | CV_MAT_MAGIC_VAL;\r
- arr->rows = rows;\r
- arr->cols = cols;\r
- arr->data.ptr = (uchar*)data;\r
- arr->refcount = 0;\r
- arr->hdr_refcount = 0;\r
-\r
- int mask = (arr->rows <= 1) - 1;\r
- int pix_size = CV_ELEM_SIZE(type);\r
- int min_step = arr->cols*pix_size & mask;\r
-\r
- if( step != CV_AUTOSTEP && step != 0 )\r
- {\r
- if( step < min_step )\r
- CV_Error( CV_BadStep, "" );\r
- arr->step = step & mask;\r
- }\r
- else\r
- {\r
- arr->step = min_step;\r
- }\r
-\r
- arr->type = CV_MAT_MAGIC_VAL | type |\r
- (arr->step == min_step ? CV_MAT_CONT_FLAG : 0);\r
-\r
- icvCheckHuge( arr );\r
- return arr;\r
-}\r
-\r
-\r
-// Deallocates the CvMat structure and underlying data\r
-CV_IMPL void\r
-cvReleaseMat( CvMat** array )\r
-{\r
- if( !array )\r
- CV_Error( CV_HeaderIsNull, "" );\r
-\r
- if( *array )\r
- {\r
- CvMat* arr = *array;\r
- \r
- if( !CV_IS_MAT_HDR(arr) && !CV_IS_MATND_HDR(arr) )\r
- CV_Error( CV_StsBadFlag, "" );\r
-\r
- *array = 0;\r
-\r
- cvDecRefData( arr );\r
- cvFree( &arr );\r
- }\r
-}\r
-\r
-\r
-// Creates a copy of matrix\r
-CV_IMPL CvMat*\r
-cvCloneMat( const CvMat* src )\r
-{\r
- if( !CV_IS_MAT_HDR( src ))\r
- CV_Error( CV_StsBadArg, "Bad CvMat header" );\r
-\r
- CvMat* dst = cvCreateMatHeader( src->rows, src->cols, src->type );\r
-\r
- if( src->data.ptr )\r
- {\r
- cvCreateData( dst );\r
- cvCopy( src, dst );\r
- }\r
-\r
- return dst;\r
-}\r
-\r
-\r
-/****************************************************************************************\\r
-* CvMatND creation and basic operations *\r
-\****************************************************************************************/\r
-\r
-CV_IMPL CvMatND*\r
-cvInitMatNDHeader( CvMatND* mat, int dims, const int* sizes,\r
- int type, void* data )\r
-{\r
- type = CV_MAT_TYPE(type);\r
- int64 step = CV_ELEM_SIZE(type);\r
-\r
- if( !mat )\r
- CV_Error( CV_StsNullPtr, "NULL matrix header pointer" );\r
-\r
- if( step == 0 )\r
- CV_Error( CV_StsUnsupportedFormat, "invalid array data type" );\r
-\r
- if( !sizes )\r
- CV_Error( CV_StsNullPtr, "NULL <sizes> pointer" );\r
-\r
- if( dims <= 0 || dims > CV_MAX_DIM )\r
- CV_Error( CV_StsOutOfRange,\r
- "non-positive or too large number of dimensions" );\r
-\r
- for( int i = dims - 1; i >= 0; i-- )\r
- {\r
- if( sizes[i] <= 0 )\r
- CV_Error( CV_StsBadSize, "one of dimesion sizes is non-positive" );\r
- mat->dim[i].size = sizes[i];\r
- if( step > INT_MAX )\r
- CV_Error( CV_StsOutOfRange, "The array is too big" );\r
- mat->dim[i].step = (int)step;\r
- step *= sizes[i];\r
- }\r
-\r
- mat->type = CV_MATND_MAGIC_VAL | (step <= INT_MAX ? CV_MAT_CONT_FLAG : 0) | type;\r
- mat->dims = dims;\r
- mat->data.ptr = (uchar*)data;\r
- mat->refcount = 0;\r
- mat->hdr_refcount = 0;\r
- return mat;\r
-}\r
-\r
-\r
-// Creates CvMatND and underlying data\r
-CV_IMPL CvMatND*\r
-cvCreateMatND( int dims, const int* sizes, int type )\r
-{\r
- CvMatND* arr = cvCreateMatNDHeader( dims, sizes, type );\r
- cvCreateData( arr );\r
-\r
- return arr;\r
-}\r
-\r
-\r
-// Creates CvMatND header only\r
-CV_IMPL CvMatND*\r
-cvCreateMatNDHeader( int dims, const int* sizes, int type )\r
-{\r
- if( dims <= 0 || dims > CV_MAX_DIM )\r
- CV_Error( CV_StsOutOfRange,\r
- "non-positive or too large number of dimensions" );\r
-\r
- CvMatND* arr = (CvMatND*)cvAlloc( sizeof(*arr) );\r
- \r
- cvInitMatNDHeader( arr, dims, sizes, type, 0 );\r
- arr->hdr_refcount = 1;\r
- return arr;\r
-}\r
-\r
-\r
-// Creates a copy of nD array\r
-CV_IMPL CvMatND*\r
-cvCloneMatND( const CvMatND* src )\r
-{\r
- if( !CV_IS_MATND_HDR( src ))\r
- CV_Error( CV_StsBadArg, "Bad CvMatND header" );\r
-\r
- int* sizes = (int*)cvStackAlloc( src->dims*sizeof(sizes[0]) );\r
-\r
- for( int i = 0; i < src->dims; i++ )\r
- sizes[i] = src->dim[i].size;\r
-\r
- CvMatND* dst = cvCreateMatNDHeader( src->dims, sizes, src->type );\r
-\r
- if( src->data.ptr )\r
- {\r
- cvCreateData( dst );\r
- cvCopy( src, dst );\r
- }\r
-\r
- return dst;\r
-}\r
-\r
-\r
-static CvMatND*\r
-cvGetMatND( const CvArr* arr, CvMatND* matnd, int* coi )\r
-{\r
- CvMatND* result = 0;\r
-\r
- if( coi )\r
- *coi = 0;\r
-\r
- if( !matnd || !arr )\r
- CV_Error( CV_StsNullPtr, "NULL array pointer is passed" );\r
-\r
- if( CV_IS_MATND_HDR(arr))\r
- {\r
- if( !((CvMatND*)arr)->data.ptr )\r
- CV_Error( CV_StsNullPtr, "The matrix has NULL data pointer" );\r
- \r
- result = (CvMatND*)arr;\r
- }\r
- else\r
- {\r
- CvMat stub, *mat = (CvMat*)arr;\r
- \r
- if( CV_IS_IMAGE_HDR( mat ))\r
- mat = cvGetMat( mat, &stub, coi );\r
-\r
- if( !CV_IS_MAT_HDR( mat ))\r
- CV_Error( CV_StsBadArg, "Unrecognized or unsupported array type" );\r
- \r
- if( !mat->data.ptr )\r
- CV_Error( CV_StsNullPtr, "Input array has NULL data pointer" );\r
-\r
- matnd->data.ptr = mat->data.ptr;\r
- matnd->refcount = 0;\r
- matnd->hdr_refcount = 0;\r
- matnd->type = mat->type;\r
- matnd->dims = 2;\r
- matnd->dim[0].size = mat->rows;\r
- matnd->dim[0].step = mat->step;\r
- matnd->dim[1].size = mat->cols;\r
- matnd->dim[1].step = CV_ELEM_SIZE(mat->type);\r
- result = matnd;\r
- }\r
-\r
- return result;\r
-}\r
-\r
-\r
-// returns number of dimensions to iterate.\r
-/*\r
-Checks whether <count> arrays have equal type, sizes (mask is optional array\r
-that needs to have the same size, but 8uC1 or 8sC1 type).\r
-Returns number of dimensions to iterate through:\r
-0 means that all arrays are continuous,\r
-1 means that all arrays are vectors of continuous arrays etc.\r
-and the size of largest common continuous part of the arrays \r
-*/\r
-CV_IMPL int\r
-cvInitNArrayIterator( int count, CvArr** arrs,\r
- const CvArr* mask, CvMatND* stubs,\r
- CvNArrayIterator* iterator, int flags )\r
-{\r
- int dims = -1;\r
- int i, j, size, dim0 = -1;\r
- int64 step;\r
- CvMatND* hdr0 = 0;\r
-\r
- if( count < 1 || count > CV_MAX_ARR )\r
- CV_Error( CV_StsOutOfRange, "Incorrect number of arrays" );\r
-\r
- if( !arrs || !stubs )\r
- CV_Error( CV_StsNullPtr, "Some of required array pointers is NULL" );\r
-\r
- if( !iterator )\r
- CV_Error( CV_StsNullPtr, "Iterator pointer is NULL" );\r
-\r
- for( i = 0; i <= count; i++ )\r
- {\r
- const CvArr* arr = i < count ? arrs[i] : mask;\r
- CvMatND* hdr;\r
- \r
- if( !arr )\r
- {\r
- if( i < count )\r
- CV_Error( CV_StsNullPtr, "Some of required array pointers is NULL" );\r
- break;\r
- }\r
-\r
- if( CV_IS_MATND( arr ))\r
- hdr = (CvMatND*)arr;\r
- else\r
- {\r
- int coi = 0;\r
- hdr = cvGetMatND( arr, stubs + i, &coi );\r
- if( coi != 0 )\r
- CV_Error( CV_BadCOI, "COI set is not allowed here" );\r
- }\r
-\r
- iterator->hdr[i] = hdr;\r
-\r
- if( i > 0 )\r
- {\r
- if( hdr->dims != hdr0->dims )\r
- CV_Error( CV_StsUnmatchedSizes,\r
- "Number of dimensions is the same for all arrays" );\r
- \r
- if( i < count )\r
- {\r
- switch( flags & (CV_NO_DEPTH_CHECK|CV_NO_CN_CHECK))\r
- {\r
- case 0:\r
- if( !CV_ARE_TYPES_EQ( hdr, hdr0 ))\r
- CV_Error( CV_StsUnmatchedFormats,\r
- "Data type is not the same for all arrays" );\r
- break;\r
- case CV_NO_DEPTH_CHECK:\r
- if( !CV_ARE_CNS_EQ( hdr, hdr0 ))\r
- CV_Error( CV_StsUnmatchedFormats,\r
- "Number of channels is not the same for all arrays" );\r
- break;\r
- case CV_NO_CN_CHECK:\r
- if( !CV_ARE_CNS_EQ( hdr, hdr0 ))\r
- CV_Error( CV_StsUnmatchedFormats,\r
- "Depth is not the same for all arrays" );\r
- break;\r
- }\r
- }\r
- else\r
- {\r
- if( !CV_IS_MASK_ARR( hdr ))\r
- CV_Error( CV_StsBadMask, "Mask should have 8uC1 or 8sC1 data type" );\r
- }\r
-\r
- if( !(flags & CV_NO_SIZE_CHECK) )\r
- {\r
- for( j = 0; j < hdr->dims; j++ )\r
- if( hdr->dim[j].size != hdr0->dim[j].size )\r
- CV_Error( CV_StsUnmatchedSizes,\r
- "Dimension sizes are the same for all arrays" );\r
- }\r
- }\r
- else\r
- hdr0 = hdr;\r
-\r
- step = CV_ELEM_SIZE(hdr->type);\r
- for( j = hdr->dims - 1; j > dim0; j-- )\r
- {\r
- if( step != hdr->dim[j].step )\r
- break;\r
- step *= hdr->dim[j].size;\r
- }\r
-\r
- if( j == dim0 && step > INT_MAX )\r
- j++;\r
-\r
- if( j > dim0 )\r
- dim0 = j;\r
-\r
- iterator->hdr[i] = (CvMatND*)hdr;\r
- iterator->ptr[i] = (uchar*)hdr->data.ptr;\r
- }\r
-\r
- size = 1;\r
- for( j = hdr0->dims - 1; j > dim0; j-- )\r
- size *= hdr0->dim[j].size;\r
-\r
- dims = dim0 + 1;\r
- iterator->dims = dims;\r
- iterator->count = count;\r
- iterator->size = cvSize(size,1);\r
-\r
- for( i = 0; i < dims; i++ )\r
- iterator->stack[i] = hdr0->dim[i].size;\r
-\r
- return dims;\r
-}\r
-\r
-\r
-// returns zero value if iteration is finished, non-zero otherwise\r
-CV_IMPL int cvNextNArraySlice( CvNArrayIterator* iterator )\r
-{\r
- assert( iterator != 0 );\r
- int i, dims, size = 0;\r
-\r
- for( dims = iterator->dims; dims > 0; dims-- )\r
- {\r
- for( i = 0; i < iterator->count; i++ )\r
- iterator->ptr[i] += iterator->hdr[i]->dim[dims-1].step;\r
-\r
- if( --iterator->stack[dims-1] > 0 )\r
- break;\r
-\r
- size = iterator->hdr[0]->dim[dims-1].size;\r
-\r
- for( i = 0; i < iterator->count; i++ )\r
- iterator->ptr[i] -= (size_t)size*iterator->hdr[i]->dim[dims-1].step;\r
-\r
- iterator->stack[dims-1] = size;\r
- }\r
-\r
- return dims > 0;\r
-}\r
-\r
-\r
-/****************************************************************************************\\r
-* CvSparseMat creation and basic operations *\r
-\****************************************************************************************/\r
-\r
-\r
-// Creates CvMatND and underlying data\r
-CV_IMPL CvSparseMat*\r
-cvCreateSparseMat( int dims, const int* sizes, int type )\r
-{\r
- type = CV_MAT_TYPE( type );\r
- int pix_size1 = CV_ELEM_SIZE1(type);\r
- int pix_size = pix_size1*CV_MAT_CN(type);\r
- int i, size;\r
- CvMemStorage* storage;\r
-\r
- if( pix_size == 0 )\r
- CV_Error( CV_StsUnsupportedFormat, "invalid array data type" );\r
-\r
- if( dims <= 0 || dims > CV_MAX_DIM_HEAP )\r
- CV_Error( CV_StsOutOfRange, "bad number of dimensions" );\r
-\r
- if( !sizes )\r
- CV_Error( CV_StsNullPtr, "NULL <sizes> pointer" );\r
-\r
- for( i = 0; i < dims; i++ )\r
- {\r
- if( sizes[i] <= 0 )\r
- CV_Error( CV_StsBadSize, "one of dimesion sizes is non-positive" );\r
- }\r
-\r
- CvSparseMat* arr = (CvSparseMat*)cvAlloc(sizeof(*arr)+MAX(0,dims-CV_MAX_DIM)*sizeof(arr->size[0]));\r
-\r
- arr->type = CV_SPARSE_MAT_MAGIC_VAL | type;\r
- arr->dims = dims;\r
- arr->refcount = 0;\r
- arr->hdr_refcount = 1;\r
- memcpy( arr->size, sizes, dims*sizeof(sizes[0]));\r
-\r
- arr->valoffset = (int)cvAlign(sizeof(CvSparseNode), pix_size1);\r
- arr->idxoffset = (int)cvAlign(arr->valoffset + pix_size, sizeof(int));\r
- size = (int)cvAlign(arr->idxoffset + dims*sizeof(int), sizeof(CvSetElem));\r
-\r
- storage = cvCreateMemStorage( CV_SPARSE_MAT_BLOCK );\r
- arr->heap = cvCreateSet( 0, sizeof(CvSet), size, storage );\r
-\r
- arr->hashsize = CV_SPARSE_HASH_SIZE0;\r
- size = arr->hashsize*sizeof(arr->hashtable[0]);\r
- \r
- arr->hashtable = (void**)cvAlloc( size );\r
- memset( arr->hashtable, 0, size );\r
-\r
- return arr;\r
-}\r
-\r
-\r
-// Creates CvMatND and underlying data\r
-CV_IMPL void\r
-cvReleaseSparseMat( CvSparseMat** array )\r
-{\r
- if( !array )\r
- CV_Error( CV_HeaderIsNull, "" );\r
-\r
- if( *array )\r
- {\r
- CvSparseMat* arr = *array;\r
- \r
- if( !CV_IS_SPARSE_MAT_HDR(arr) )\r
- CV_Error( CV_StsBadFlag, "" );\r
-\r
- *array = 0;\r
-\r
- CvMemStorage* storage = arr->heap->storage;\r
- cvReleaseMemStorage( &storage );\r
- cvFree( &arr->hashtable );\r
- cvFree( &arr );\r
- }\r
-}\r
-\r
-\r
-// Creates CvMatND and underlying data\r
-CV_IMPL CvSparseMat*\r
-cvCloneSparseMat( const CvSparseMat* src )\r
-{\r
- if( !CV_IS_SPARSE_MAT_HDR(src) )\r
- CV_Error( CV_StsBadArg, "Invalid sparse array header" );\r
-\r
- CvSparseMat* dst = cvCreateSparseMat( src->dims, src->size, src->type );\r
- cvCopy( src, dst ); \r
- return dst;\r
-}\r
-\r
-\r
-CvSparseNode*\r
-cvInitSparseMatIterator( const CvSparseMat* mat, CvSparseMatIterator* iterator )\r
-{\r
- CvSparseNode* node = 0;\r
- int idx;\r
-\r
- if( !CV_IS_SPARSE_MAT( mat ))\r
- CV_Error( CV_StsBadArg, "Invalid sparse matrix header" );\r
-\r
- if( !iterator )\r
- CV_Error( CV_StsNullPtr, "NULL iterator pointer" );\r
-\r
- iterator->mat = (CvSparseMat*)mat;\r
- iterator->node = 0;\r
-\r
- for( idx = 0; idx < mat->hashsize; idx++ )\r
- if( mat->hashtable[idx] )\r
- {\r
- node = iterator->node = (CvSparseNode*)mat->hashtable[idx];\r
- break;\r
- }\r
-\r
- iterator->curidx = idx;\r
- return node;\r
-}\r
-\r
-#define ICV_SPARSE_MAT_HASH_MULTIPLIER 33\r
-\r
-static uchar*\r
-icvGetNodePtr( CvSparseMat* mat, const int* idx, int* _type,\r
- int create_node, unsigned* precalc_hashval )\r
-{\r
- uchar* ptr = 0;\r
- int i, tabidx;\r
- unsigned hashval = 0;\r
- CvSparseNode *node;\r
- assert( CV_IS_SPARSE_MAT( mat ));\r
-\r
- if( !precalc_hashval )\r
- {\r
- for( i = 0; i < mat->dims; i++ )\r
- {\r
- int t = idx[i];\r
- if( (unsigned)t >= (unsigned)mat->size[i] )\r
- CV_Error( CV_StsOutOfRange, "One of indices is out of range" );\r
- hashval = hashval*ICV_SPARSE_MAT_HASH_MULTIPLIER + t;\r
- }\r
- }\r
- else\r
- {\r
- hashval = *precalc_hashval;\r
- }\r
-\r
- tabidx = hashval & (mat->hashsize - 1);\r
- hashval &= INT_MAX;\r
-\r
- for( node = (CvSparseNode*)mat->hashtable[tabidx];\r
- node != 0; node = node->next )\r
- {\r
- if( node->hashval == hashval )\r
- {\r
- int* nodeidx = CV_NODE_IDX(mat,node);\r
- for( i = 0; i < mat->dims; i++ )\r
- if( idx[i] != nodeidx[i] )\r
- break;\r
- if( i == mat->dims )\r
- {\r
- ptr = (uchar*)CV_NODE_VAL(mat,node);\r
- break;\r
- }\r
- }\r
- }\r
-\r
- if( !ptr && create_node )\r
- {\r
- if( mat->heap->active_count >= mat->hashsize*CV_SPARSE_HASH_RATIO )\r
- {\r
- void** newtable;\r
- int newsize = MAX( mat->hashsize*2, CV_SPARSE_HASH_SIZE0);\r
- int newrawsize = newsize*sizeof(newtable[0]);\r
- \r
- CvSparseMatIterator iterator;\r
- assert( (newsize & (newsize - 1)) == 0 );\r
-\r
- // resize hash table\r
- newtable = (void**)cvAlloc( newrawsize );\r
- memset( newtable, 0, newrawsize );\r
-\r
- node = cvInitSparseMatIterator( mat, &iterator );\r
- while( node )\r
- {\r
- CvSparseNode* next = cvGetNextSparseNode( &iterator );\r
- int newidx = node->hashval & (newsize - 1);\r
- node->next = (CvSparseNode*)newtable[newidx];\r
- newtable[newidx] = node;\r
- node = next;\r
- }\r
-\r
- cvFree( &mat->hashtable );\r
- mat->hashtable = newtable;\r
- mat->hashsize = newsize;\r
- tabidx = hashval & (newsize - 1);\r
- }\r
-\r
- node = (CvSparseNode*)cvSetNew( mat->heap );\r
- node->hashval = hashval;\r
- node->next = (CvSparseNode*)mat->hashtable[tabidx];\r
- mat->hashtable[tabidx] = node;\r
- CV_MEMCPY_INT( CV_NODE_IDX(mat,node), idx, mat->dims );\r
- ptr = (uchar*)CV_NODE_VAL(mat,node);\r
- if( create_node > 0 )\r
- CV_ZERO_CHAR( ptr, CV_ELEM_SIZE(mat->type));\r
- }\r
-\r
- if( _type )\r
- *_type = CV_MAT_TYPE(mat->type);\r
-\r
- return ptr;\r
-}\r
-\r
-\r
-static void\r
-icvDeleteNode( CvSparseMat* mat, const int* idx, unsigned* precalc_hashval )\r
-{\r
- int i, tabidx;\r
- unsigned hashval = 0;\r
- CvSparseNode *node, *prev = 0;\r
- assert( CV_IS_SPARSE_MAT( mat ));\r
-\r
- if( !precalc_hashval )\r
- {\r
- for( i = 0; i < mat->dims; i++ )\r
- {\r
- int t = idx[i];\r
- if( (unsigned)t >= (unsigned)mat->size[i] )\r
- CV_Error( CV_StsOutOfRange, "One of indices is out of range" );\r
- hashval = hashval*ICV_SPARSE_MAT_HASH_MULTIPLIER + t;\r
- }\r
- }\r
- else\r
- {\r
- hashval = *precalc_hashval;\r
- }\r
-\r
- tabidx = hashval & (mat->hashsize - 1);\r
- hashval &= INT_MAX;\r
-\r
- for( node = (CvSparseNode*)mat->hashtable[tabidx];\r
- node != 0; prev = node, node = node->next )\r
- {\r
- if( node->hashval == hashval )\r
- {\r
- int* nodeidx = CV_NODE_IDX(mat,node);\r
- for( i = 0; i < mat->dims; i++ )\r
- if( idx[i] != nodeidx[i] )\r
- break;\r
- if( i == mat->dims )\r
- break;\r
- }\r
- }\r
-\r
- if( node )\r
- {\r
- if( prev )\r
- prev->next = node->next;\r
- else\r
- mat->hashtable[tabidx] = node->next;\r
- cvSetRemoveByPtr( mat->heap, node );\r
- }\r
-}\r
-\r
-\r
-/****************************************************************************************\\r
-* Common for multiple array types operations *\r
-\****************************************************************************************/\r
-\r
-// Allocates underlying array data\r
-CV_IMPL void\r
-cvCreateData( CvArr* arr )\r
-{\r
- if( CV_IS_MAT_HDR( arr ))\r
- {\r
- size_t step, total_size;\r
- CvMat* mat = (CvMat*)arr;\r
- step = mat->step;\r
-\r
- if( mat->data.ptr != 0 )\r
- CV_Error( CV_StsError, "Data is already allocated" );\r
-\r
- if( step == 0 )\r
- step = CV_ELEM_SIZE(mat->type)*mat->cols;\r
-\r
- total_size = step*mat->rows + sizeof(int) + CV_MALLOC_ALIGN;\r
- mat->refcount = (int*)cvAlloc( (size_t)total_size );\r
- mat->data.ptr = (uchar*)cvAlignPtr( mat->refcount + 1, CV_MALLOC_ALIGN );\r
- *mat->refcount = 1;\r
- }\r
- else if( CV_IS_IMAGE_HDR(arr))\r
- {\r
- IplImage* img = (IplImage*)arr;\r
-\r
- if( img->imageData != 0 )\r
- CV_Error( CV_StsError, "Data is already allocated" );\r
-\r
- if( !CvIPL.allocateData )\r
- {\r
- img->imageData = img->imageDataOrigin = \r
- (char*)cvAlloc( (size_t)img->imageSize );\r
- }\r
- else\r
- {\r
- int depth = img->depth;\r
- int width = img->width;\r
-\r
- if( img->depth == IPL_DEPTH_32F || img->nChannels == 64 )\r
- {\r
- img->width *= img->depth == IPL_DEPTH_32F ? sizeof(float) : sizeof(double);\r
- img->depth = IPL_DEPTH_8U;\r
- }\r
-\r
- CvIPL.allocateData( img, 0, 0 );\r
-\r
- img->width = width;\r
- img->depth = depth;\r
- }\r
- }\r
- else if( CV_IS_MATND_HDR( arr ))\r
- {\r
- CvMatND* mat = (CvMatND*)arr;\r
- int i;\r
- size_t total_size = CV_ELEM_SIZE(mat->type);\r
-\r
- if( mat->data.ptr != 0 )\r
- CV_Error( CV_StsError, "Data is already allocated" );\r
-\r
- if( CV_IS_MAT_CONT( mat->type ))\r
- {\r
- total_size = (size_t)mat->dim[0].size*(mat->dim[0].step != 0 ?\r
- mat->dim[0].step : total_size);\r
- }\r
- else\r
- {\r
- for( i = mat->dims - 1; i >= 0; i-- )\r
- {\r
- size_t size = (size_t)mat->dim[i].step*mat->dim[i].size;\r
-\r
- if( total_size < size )\r
- total_size = size;\r
- }\r
- }\r
- \r
- mat->refcount = (int*)cvAlloc( total_size +\r
- sizeof(int) + CV_MALLOC_ALIGN );\r
- mat->data.ptr = (uchar*)cvAlignPtr( mat->refcount + 1, CV_MALLOC_ALIGN );\r
- *mat->refcount = 1;\r
- }\r
- else\r
- CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );\r
-}\r
-\r
-\r
-// Assigns external data to array\r
-CV_IMPL void\r
-cvSetData( CvArr* arr, void* data, int step )\r
-{\r
- int pix_size, min_step;\r
-\r
- if( CV_IS_MAT_HDR(arr) || CV_IS_MATND_HDR(arr) )\r
- cvReleaseData( arr );\r
-\r
- if( CV_IS_MAT_HDR( arr ))\r
- {\r
- CvMat* mat = (CvMat*)arr;\r
- \r
- int type = CV_MAT_TYPE(mat->type);\r
- pix_size = CV_ELEM_SIZE(type);\r
- min_step = mat->cols*pix_size & ((mat->rows <= 1) - 1);\r
-\r
- if( step != CV_AUTOSTEP )\r
- {\r
- if( step < min_step && data != 0 )\r
- CV_Error( CV_BadStep, "" );\r
- mat->step = step & ((mat->rows <= 1) - 1);\r
- }\r
- else\r
- {\r
- mat->step = min_step;\r
- }\r
-\r
- mat->data.ptr = (uchar*)data;\r
- mat->type = CV_MAT_MAGIC_VAL | type |\r
- (mat->step==min_step ? CV_MAT_CONT_FLAG : 0);\r
- icvCheckHuge( mat );\r
- }\r
- else if( CV_IS_IMAGE_HDR( arr ))\r
- {\r
- IplImage* img = (IplImage*)arr;\r
- \r
- pix_size = ((img->depth & 255) >> 3)*img->nChannels;\r
- min_step = img->width*pix_size;\r
-\r
- if( step != CV_AUTOSTEP && img->height > 1 )\r
- {\r
- if( step < min_step && data != 0 )\r
- CV_Error( CV_BadStep, "" );\r
- img->widthStep = step;\r
- }\r
- else\r
- {\r
- img->widthStep = min_step;\r
- }\r
-\r
- img->imageSize = img->widthStep * img->height;\r
- img->imageData = img->imageDataOrigin = (char*)data;\r
-\r
- if( (((int)(size_t)data | step) & 7) == 0 &&\r
- cvAlign(img->width * pix_size, 8) == step )\r
- {\r
- img->align = 8;\r
- }\r
- else\r
- {\r
- img->align = 4;\r
- }\r
- }\r
- else if( CV_IS_MATND_HDR( arr ))\r
- {\r
- CvMatND* mat = (CvMatND*)arr;\r
- int i;\r
- int64 cur_step;\r
- \r
- if( step != CV_AUTOSTEP )\r
- CV_Error( CV_BadStep,\r
- "For multidimensional array only CV_AUTOSTEP is allowed here" );\r
-\r
- mat->data.ptr = (uchar*)data;\r
- cur_step = CV_ELEM_SIZE(mat->type);\r
-\r
- for( i = mat->dims - 1; i >= 0; i-- )\r
- {\r
- if( cur_step > INT_MAX )\r
- CV_Error( CV_StsOutOfRange, "The array is too big" );\r
- mat->dim[i].step = (int)cur_step;\r
- cur_step *= mat->dim[i].size;\r
- }\r
- }\r
- else\r
- CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );\r
-}\r
-\r
-\r
-// Deallocates array's data\r
-CV_IMPL void\r
-cvReleaseData( CvArr* arr )\r
-{\r
- if( CV_IS_MAT_HDR( arr ) || CV_IS_MATND_HDR( arr ))\r
- {\r
- CvMat* mat = (CvMat*)arr;\r
- cvDecRefData( mat );\r
- }\r
- else if( CV_IS_IMAGE_HDR( arr ))\r
- {\r
- IplImage* img = (IplImage*)arr;\r
-\r
- if( !CvIPL.deallocate )\r
- {\r
- char* ptr = img->imageDataOrigin;\r
- img->imageData = img->imageDataOrigin = 0;\r
- cvFree( &ptr );\r
- }\r
- else\r
- {\r
- CvIPL.deallocate( img, IPL_IMAGE_DATA );\r
- }\r
- }\r
- else\r
- CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );\r
-}\r
-\r
-\r
-// Retrieves essential information about image ROI or CvMat data\r
-CV_IMPL void\r
-cvGetRawData( const CvArr* arr, uchar** data, int* step, CvSize* roi_size )\r
-{\r
- if( CV_IS_MAT( arr ))\r
- {\r
- CvMat *mat = (CvMat*)arr;\r
-\r
- if( step )\r
- *step = mat->step;\r
-\r
- if( data )\r
- *data = mat->data.ptr;\r
-\r
- if( roi_size )\r
- *roi_size = cvGetMatSize( mat );\r
- }\r
- else if( CV_IS_IMAGE( arr ))\r
- {\r
- IplImage* img = (IplImage*)arr;\r
-\r
- if( step )\r
- *step = img->widthStep;\r
-\r
- if( data )\r
- *data = cvPtr2D( img, 0, 0 );\r
-\r
- if( roi_size )\r
- {\r
- if( img->roi )\r
- {\r
- *roi_size = cvSize( img->roi->width, img->roi->height );\r
- }\r
- else\r
- {\r
- *roi_size = cvSize( img->width, img->height );\r
- }\r
- }\r
- }\r
- else if( CV_IS_MATND( arr ))\r
- {\r
- CvMatND* mat = (CvMatND*)arr;\r
-\r
- if( !CV_IS_MAT_CONT( mat->type ))\r
- CV_Error( CV_StsBadArg, "Only continuous nD arrays are supported here" );\r
-\r
- if( data )\r
- *data = mat->data.ptr;\r
-\r
- if( roi_size || step )\r
- {\r
- int i, size1 = mat->dim[0].size, size2 = 1;\r
-\r
- if( mat->dims > 2 )\r
- for( i = 1; i < mat->dims; i++ )\r
- size1 *= mat->dim[i].size;\r
- else\r
- size2 = mat->dim[1].size;\r
-\r
- if( roi_size )\r
- {\r
- roi_size->width = size2;\r
- roi_size->height = size1;\r
- }\r
-\r
- if( step )\r
- *step = size1 == 1 ? 0 : mat->dim[0].step;\r
- }\r
- }\r
- else\r
- CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );\r
-}\r
-\r
-\r
-CV_IMPL int\r
-cvGetElemType( const CvArr* arr )\r
-{\r
- int type = -1;\r
- if( CV_IS_MAT_HDR(arr) || CV_IS_MATND_HDR(arr) || CV_IS_SPARSE_MAT_HDR(arr))\r
- type = CV_MAT_TYPE( ((CvMat*)arr)->type );\r
- else if( CV_IS_IMAGE(arr))\r
- {\r
- IplImage* img = (IplImage*)arr;\r
- type = CV_MAKETYPE( IplToCvDepth(img->depth), img->nChannels );\r
- }\r
- else\r
- CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );\r
-\r
- return type;\r
-}\r
-\r
-\r
-// Returns a number of array dimensions\r
-CV_IMPL int\r
-cvGetDims( const CvArr* arr, int* sizes )\r
-{\r
- int dims = -1;\r
- if( CV_IS_MAT_HDR( arr ))\r
- {\r
- CvMat* mat = (CvMat*)arr;\r
- \r
- dims = 2;\r
- if( sizes )\r
- {\r
- sizes[0] = mat->rows;\r
- sizes[1] = mat->cols;\r
- }\r
- }\r
- else if( CV_IS_IMAGE( arr ))\r
- {\r
- IplImage* img = (IplImage*)arr;\r
- dims = 2;\r
-\r
- if( sizes )\r
- {\r
- sizes[0] = img->height;\r
- sizes[1] = img->width;\r
- }\r
- }\r
- else if( CV_IS_MATND_HDR( arr ))\r
- {\r
- CvMatND* mat = (CvMatND*)arr;\r
- dims = mat->dims;\r
- \r
- if( sizes )\r
- {\r
- int i;\r
- for( i = 0; i < dims; i++ )\r
- sizes[i] = mat->dim[i].size;\r
- }\r
- }\r
- else if( CV_IS_SPARSE_MAT_HDR( arr ))\r
- {\r
- CvSparseMat* mat = (CvSparseMat*)arr;\r
- dims = mat->dims;\r
- \r
- if( sizes )\r
- memcpy( sizes, mat->size, dims*sizeof(sizes[0]));\r
- }\r
- else\r
- CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );\r
-\r
- return dims;\r
-}\r
-\r
-\r
-// Returns the size of particular array dimension\r
-CV_IMPL int\r
-cvGetDimSize( const CvArr* arr, int index )\r
-{\r
- int size = -1;\r
-\r
- if( CV_IS_MAT( arr ))\r
- {\r
- CvMat *mat = (CvMat*)arr;\r
-\r
- switch( index )\r
- {\r
- case 0:\r
- size = mat->rows;\r
- break;\r
- case 1:\r
- size = mat->cols;\r
- break;\r
- default:\r
- CV_Error( CV_StsOutOfRange, "bad dimension index" );\r
- }\r
- }\r
- else if( CV_IS_IMAGE( arr ))\r
- {\r
- IplImage* img = (IplImage*)arr;\r
-\r
- switch( index )\r
- {\r
- case 0:\r
- size = !img->roi ? img->height : img->roi->height;\r
- break;\r
- case 1:\r
- size = !img->roi ? img->width : img->roi->width;\r
- break;\r
- default:\r
- CV_Error( CV_StsOutOfRange, "bad dimension index" );\r
- }\r
- }\r
- else if( CV_IS_MATND_HDR( arr ))\r
- {\r
- CvMatND* mat = (CvMatND*)arr;\r
- \r
- if( (unsigned)index >= (unsigned)mat->dims )\r
- CV_Error( CV_StsOutOfRange, "bad dimension index" );\r
-\r
- size = mat->dim[index].size;\r
- }\r
- else if( CV_IS_SPARSE_MAT_HDR( arr ))\r
- {\r
- CvSparseMat* mat = (CvSparseMat*)arr;\r
- \r
- if( (unsigned)index >= (unsigned)mat->dims )\r
- CV_Error( CV_StsOutOfRange, "bad dimension index" );\r
-\r
- size = mat->size[index];\r
- }\r
- else\r
- CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );\r
-\r
- return size;\r
-}\r
-\r
-\r
-// Returns the size of CvMat or IplImage\r
-CV_IMPL CvSize\r
-cvGetSize( const CvArr* arr )\r
-{\r
- CvSize size = { 0, 0 };\r
-\r
- if( CV_IS_MAT_HDR( arr ))\r
- {\r
- CvMat *mat = (CvMat*)arr;\r
-\r
- size.width = mat->cols;\r
- size.height = mat->rows;\r
- }\r
- else if( CV_IS_IMAGE_HDR( arr ))\r
- {\r
- IplImage* img = (IplImage*)arr;\r
-\r
- if( img->roi )\r
- {\r
- size.width = img->roi->width;\r
- size.height = img->roi->height;\r
- }\r
- else\r
- {\r
- size.width = img->width;\r
- size.height = img->height;\r
- }\r
- }\r
- else\r
- CV_Error( CV_StsBadArg, "Array should be CvMat or IplImage" );\r
-\r
- return size;\r
-}\r
-\r
-\r
-// Selects sub-array (no data is copied)\r
-CV_IMPL CvMat*\r
-cvGetSubRect( const CvArr* arr, CvMat* submat, CvRect rect )\r
-{\r
- CvMat* res = 0;\r
- CvMat stub, *mat = (CvMat*)arr;\r
-\r
- if( !CV_IS_MAT( mat ))\r
- mat = cvGetMat( mat, &stub );\r
-\r
- if( !submat )\r
- CV_Error( CV_StsNullPtr, "" );\r
-\r
- if( (rect.x|rect.y|rect.width|rect.height) < 0 )\r
- CV_Error( CV_StsBadSize, "" );\r
-\r
- if( rect.x + rect.width > mat->cols ||\r
- rect.y + rect.height > mat->rows )\r
- CV_Error( CV_StsBadSize, "" );\r
-\r
- {\r
- /*\r
- int* refcount = mat->refcount;\r
-\r
- if( refcount )\r
- ++*refcount;\r
-\r
- cvDecRefData( submat );\r
- */\r
- submat->data.ptr = mat->data.ptr + (size_t)rect.y*mat->step +\r
- rect.x*CV_ELEM_SIZE(mat->type);\r
- submat->step = mat->step & (rect.height > 1 ? -1 : 0);\r
- submat->type = (mat->type & (rect.width < mat->cols ? ~CV_MAT_CONT_FLAG : -1)) |\r
- (submat->step == 0 ? CV_MAT_CONT_FLAG : 0);\r
- submat->rows = rect.height;\r
- submat->cols = rect.width;\r
- submat->refcount = 0;\r
- res = submat;\r
- }\r
-\r
- return res;\r
-}\r
-\r
-\r
-// Selects array's row span.\r
-CV_IMPL CvMat*\r
-cvGetRows( const CvArr* arr, CvMat* submat,\r
- int start_row, int end_row, int delta_row )\r
-{\r
- CvMat* res = 0;\r
- CvMat stub, *mat = (CvMat*)arr;\r
-\r
- if( !CV_IS_MAT( mat ))\r
- mat = cvGetMat( mat, &stub );\r
-\r
- if( !submat )\r
- CV_Error( CV_StsNullPtr, "" );\r
-\r
- if( (unsigned)start_row >= (unsigned)mat->rows ||\r
- (unsigned)end_row > (unsigned)mat->rows || delta_row <= 0 )\r
- CV_Error( CV_StsOutOfRange, "" );\r
-\r
- {\r
- /*\r
- int* refcount = mat->refcount;\r
-\r
- if( refcount )\r
- ++*refcount;\r
-\r
- cvDecRefData( submat );\r
- */\r
- if( delta_row == 1 )\r
- {\r
- submat->rows = end_row - start_row;\r
- submat->step = mat->step & (submat->rows > 1 ? -1 : 0);\r
- }\r
- else\r
- {\r
- submat->rows = (end_row - start_row + delta_row - 1)/delta_row;\r
- submat->step = mat->step * delta_row;\r
- }\r
-\r
- submat->cols = mat->cols;\r
- submat->step &= submat->rows > 1 ? -1 : 0;\r
- submat->data.ptr = mat->data.ptr + (size_t)start_row*mat->step;\r
- submat->type = (mat->type | (submat->step == 0 ? CV_MAT_CONT_FLAG : 0)) &\r
- (delta_row != 1 ? ~CV_MAT_CONT_FLAG : -1);\r
- submat->refcount = 0;\r
- submat->hdr_refcount = 0;\r
- res = submat;\r
- }\r
-\r
- return res;\r
-}\r
-\r
-\r
-// Selects array's column span.\r
-CV_IMPL CvMat*\r
-cvGetCols( const CvArr* arr, CvMat* submat, int start_col, int end_col )\r
-{\r
- CvMat* res = 0;\r
- CvMat stub, *mat = (CvMat*)arr;\r
- int cols;\r
-\r
- if( !CV_IS_MAT( mat ))\r
- mat = cvGetMat( mat, &stub );\r
-\r
- if( !submat )\r
- CV_Error( CV_StsNullPtr, "" );\r
- \r
- cols = mat->cols;\r
- if( (unsigned)start_col >= (unsigned)cols ||\r
- (unsigned)end_col > (unsigned)cols )\r
- CV_Error( CV_StsOutOfRange, "" );\r
-\r
- {\r
- /*\r
- int* refcount = mat->refcount;\r
-\r
- if( refcount )\r
- ++*refcount;\r
-\r
- cvDecRefData( submat );\r
- */\r
- submat->rows = mat->rows;\r
- submat->cols = end_col - start_col;\r
- submat->step = mat->step & (submat->rows > 1 ? -1 : 0);\r
- submat->data.ptr = mat->data.ptr + (size_t)start_col*CV_ELEM_SIZE(mat->type);\r
- submat->type = mat->type & (submat->step && submat->cols < cols ? ~CV_MAT_CONT_FLAG : -1);\r
- submat->refcount = 0;\r
- submat->hdr_refcount = 0;\r
- res = submat;\r
- }\r
-\r
- return res;\r
-}\r
-\r
-\r
-// Selects array diagonal\r
-CV_IMPL CvMat*\r
-cvGetDiag( const CvArr* arr, CvMat* submat, int diag )\r
-{\r
- CvMat* res = 0;\r
- CvMat stub, *mat = (CvMat*)arr;\r
- int len, pix_size; \r
-\r
- if( !CV_IS_MAT( mat ))\r
- mat = cvGetMat( mat, &stub );\r
-\r
- if( !submat )\r
- CV_Error( CV_StsNullPtr, "" );\r
-\r
- pix_size = CV_ELEM_SIZE(mat->type);\r
-\r
- /*{\r
- int* refcount = mat->refcount;\r
-\r
- if( refcount )\r
- ++*refcount;\r
-\r
- cvDecRefData( submat );\r
- }*/\r
-\r
- if( diag >= 0 )\r
- {\r
- len = mat->cols - diag;\r
- \r
- if( len <= 0 )\r
- CV_Error( CV_StsOutOfRange, "" );\r
-\r
- len = CV_IMIN( len, mat->rows );\r
- submat->data.ptr = mat->data.ptr + diag*pix_size;\r
- }\r
- else\r
- {\r
- len = mat->rows + diag;\r
- \r
- if( len <= 0 )\r
- CV_Error( CV_StsOutOfRange, "" );\r
-\r
- len = CV_IMIN( len, mat->cols );\r
- submat->data.ptr = mat->data.ptr - diag*mat->step;\r
- }\r
-\r
- submat->rows = len;\r
- submat->cols = 1;\r
- submat->step = (mat->step + pix_size) & (submat->rows > 1 ? -1 : 0);\r
- submat->type = mat->type;\r
- if( submat->step )\r
- submat->type &= ~CV_MAT_CONT_FLAG;\r
- else\r
- submat->type |= CV_MAT_CONT_FLAG;\r
- submat->refcount = 0;\r
- submat->hdr_refcount = 0;\r
- res = submat;\r
-\r
- return res;\r
-}\r
-\r
-\r
-/****************************************************************************************\\r
-* Operations on CvScalar and accessing array elements *\r
-\****************************************************************************************/\r
-\r
-// Converts CvScalar to specified type\r
-CV_IMPL void\r
-cvScalarToRawData( const CvScalar* scalar, void* data, int type, int extend_to_12 )\r
-{\r
- type = CV_MAT_TYPE(type);\r
- int cn = CV_MAT_CN( type );\r
- int depth = type & CV_MAT_DEPTH_MASK;\r
-\r
- assert( scalar && data );\r
- if( (unsigned)(cn - 1) >= 4 )\r
- CV_Error( CV_StsOutOfRange, "The number of channels must be 1, 2, 3 or 4" );\r
-\r
- switch( depth )\r
- {\r
- case CV_8UC1:\r
- while( cn-- )\r
- {\r
- int t = cvRound( scalar->val[cn] );\r
- ((uchar*)data)[cn] = CV_CAST_8U(t);\r
- }\r
- break;\r
- case CV_8SC1:\r
- while( cn-- )\r
- {\r
- int t = cvRound( scalar->val[cn] );\r
- ((char*)data)[cn] = CV_CAST_8S(t);\r
- }\r
- break;\r
- case CV_16UC1:\r
- while( cn-- )\r
- {\r
- int t = cvRound( scalar->val[cn] );\r
- ((ushort*)data)[cn] = CV_CAST_16U(t);\r
- }\r
- break;\r
- case CV_16SC1:\r
- while( cn-- )\r
- {\r
- int t = cvRound( scalar->val[cn] );\r
- ((short*)data)[cn] = CV_CAST_16S(t);\r
- }\r
- break;\r
- case CV_32SC1:\r
- while( cn-- )\r
- ((int*)data)[cn] = cvRound( scalar->val[cn] );\r
- break;\r
- case CV_32FC1:\r
- while( cn-- )\r
- ((float*)data)[cn] = (float)(scalar->val[cn]);\r
- break;\r
- case CV_64FC1:\r
- while( cn-- )\r
- ((double*)data)[cn] = (double)(scalar->val[cn]);\r
- break;\r
- default:\r
- assert(0);\r
- CV_Error( CV_BadDepth, "" );\r
- }\r
-\r
- if( extend_to_12 )\r
- {\r
- int pix_size = CV_ELEM_SIZE(type);\r
- int offset = CV_ELEM_SIZE1(depth)*12;\r
-\r
- do\r
- {\r
- offset -= pix_size;\r
- CV_MEMCPY_AUTO( (char*)data + offset, data, pix_size );\r
- }\r
- while( offset > pix_size );\r
- }\r
-}\r
-\r
-\r
-// Converts data of specified type to CvScalar\r
-CV_IMPL void\r
-cvRawDataToScalar( const void* data, int flags, CvScalar* scalar )\r
-{\r
- int cn = CV_MAT_CN( flags );\r
-\r
- assert( scalar && data );\r
- \r
- if( (unsigned)(cn - 1) >= 4 )\r
- CV_Error( CV_StsOutOfRange, "The number of channels must be 1, 2, 3 or 4" );\r
-\r
- memset( scalar->val, 0, sizeof(scalar->val));\r
-\r
- switch( CV_MAT_DEPTH( flags ))\r
- {\r
- case CV_8U:\r
- while( cn-- )\r
- scalar->val[cn] = CV_8TO32F(((uchar*)data)[cn]);\r
- break;\r
- case CV_8S:\r
- while( cn-- )\r
- scalar->val[cn] = CV_8TO32F(((char*)data)[cn]);\r
- break;\r
- case CV_16U:\r
- while( cn-- )\r
- scalar->val[cn] = ((ushort*)data)[cn];\r
- break;\r
- case CV_16S:\r
- while( cn-- )\r
- scalar->val[cn] = ((short*)data)[cn];\r
- break;\r
- case CV_32S:\r
- while( cn-- )\r
- scalar->val[cn] = ((int*)data)[cn];\r
- break;\r
- case CV_32F:\r
- while( cn-- )\r
- scalar->val[cn] = ((float*)data)[cn];\r
- break;\r
- case CV_64F:\r
- while( cn-- )\r
- scalar->val[cn] = ((double*)data)[cn];\r
- break;\r
- default:\r
- assert(0);\r
- CV_Error( CV_BadDepth, "" );\r
- }\r
-}\r
-\r
-\r
-static double icvGetReal( const void* data, int type )\r
-{\r
- switch( type )\r
- {\r
- case CV_8U:\r
- return *(uchar*)data;\r
- case CV_8S:\r
- return *(char*)data;\r
- case CV_16U:\r
- return *(ushort*)data;\r
- case CV_16S:\r
- return *(short*)data;\r
- case CV_32S:\r
- return *(int*)data;\r
- case CV_32F:\r
- return *(float*)data;\r
- case CV_64F:\r
- return *(double*)data;\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-\r
-static void icvSetReal( double value, const void* data, int type )\r
-{\r
- if( type < CV_32F )\r
- {\r
- int ivalue = cvRound(value);\r
- switch( type )\r
- {\r
- case CV_8U:\r
- *(uchar*)data = CV_CAST_8U(ivalue);\r
- break;\r
- case CV_8S:\r
- *(char*)data = CV_CAST_8S(ivalue);\r
- break;\r
- case CV_16U:\r
- *(ushort*)data = CV_CAST_16U(ivalue);\r
- break;\r
- case CV_16S:\r
- *(short*)data = CV_CAST_16S(ivalue);\r
- break;\r
- case CV_32S:\r
- *(int*)data = CV_CAST_32S(ivalue);\r
- break;\r
- }\r
- }\r
- else\r
- {\r
- switch( type )\r
- {\r
- case CV_32F:\r
- *(float*)data = (float)value;\r
- break;\r
- case CV_64F:\r
- *(double*)data = value;\r
- break;\r
- }\r
- }\r
-}\r
-\r
-\r
-// Returns pointer to specified element of array (linear index is used)\r
-CV_IMPL uchar*\r
-cvPtr1D( const CvArr* arr, int idx, int* _type )\r
-{\r
- uchar* ptr = 0;\r
- if( CV_IS_MAT( arr ))\r
- {\r
- CvMat* mat = (CvMat*)arr;\r
-\r
- int type = CV_MAT_TYPE(mat->type);\r
- int pix_size = CV_ELEM_SIZE(type);\r
-\r
- if( _type )\r
- *_type = type;\r
- \r
- // the first part is mul-free sufficient check\r
- // that the index is within the matrix\r
- if( (unsigned)idx >= (unsigned)(mat->rows + mat->cols - 1) &&\r
- (unsigned)idx >= (unsigned)(mat->rows*mat->cols))\r
- CV_Error( CV_StsOutOfRange, "index is out of range" );\r
-\r
- if( CV_IS_MAT_CONT(mat->type))\r
- {\r
- ptr = mat->data.ptr + (size_t)idx*pix_size;\r
- }\r
- else\r
- {\r
- int row, col;\r
- if( mat->cols == 1 )\r
- row = idx, col = 0;\r
- else\r
- row = idx/mat->cols, col = idx - row*mat->cols;\r
- ptr = mat->data.ptr + (size_t)row*mat->step + col*pix_size;\r
- }\r
- }\r
- else if( CV_IS_IMAGE_HDR( arr ))\r
- {\r
- IplImage* img = (IplImage*)arr;\r
- int width = !img->roi ? img->width : img->roi->width;\r
- int y = idx/width, x = idx - y*width;\r
-\r
- ptr = cvPtr2D( arr, y, x, _type );\r
- }\r
- else if( CV_IS_MATND( arr ))\r
- {\r
- CvMatND* mat = (CvMatND*)arr;\r
- int j, type = CV_MAT_TYPE(mat->type);\r
- size_t size = mat->dim[0].size;\r
-\r
- if( _type )\r
- *_type = type;\r
-\r
- for( j = 1; j < mat->dims; j++ )\r
- size *= mat->dim[j].size;\r
-\r
- if((unsigned)idx >= (unsigned)size )\r
- CV_Error( CV_StsOutOfRange, "index is out of range" );\r
-\r
- if( CV_IS_MAT_CONT(mat->type))\r
- {\r
- int pix_size = CV_ELEM_SIZE(type);\r
- ptr = mat->data.ptr + (size_t)idx*pix_size;\r
- }\r
- else\r
- {\r
- ptr = mat->data.ptr;\r
- for( j = mat->dims - 1; j >= 0; j-- )\r
- {\r
- int sz = mat->dim[j].size;\r
- if( sz )\r
- {\r
- int t = idx/sz;\r
- ptr += (idx - t*sz)*mat->dim[j].step;\r
- idx = t;\r
- }\r
- }\r
- }\r
- }\r
- else if( CV_IS_SPARSE_MAT( arr ))\r
- {\r
- CvSparseMat* m = (CvSparseMat*)arr;\r
- if( m->dims == 1 )\r
- ptr = icvGetNodePtr( (CvSparseMat*)arr, &idx, _type, 1, 0 );\r
- else\r
- {\r
- int i, n = m->dims;\r
- int* _idx = (int*)cvStackAlloc(n*sizeof(_idx[0]));\r
- \r
- for( i = n - 1; i >= 0; i-- )\r
- {\r
- int t = idx / m->size[i];\r
- _idx[i] = idx - t*m->size[i];\r
- idx = t;\r
- }\r
- ptr = icvGetNodePtr( (CvSparseMat*)arr, _idx, _type, 1, 0 );\r
- }\r
- }\r
- else\r
- {\r
- CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );\r
- }\r
-\r
- return ptr;\r
-}\r
-\r
-\r
-// Returns pointer to specified element of 2d array\r
-CV_IMPL uchar*\r
-cvPtr2D( const CvArr* arr, int y, int x, int* _type )\r
-{\r
- uchar* ptr = 0;\r
- if( CV_IS_MAT( arr ))\r
- {\r
- CvMat* mat = (CvMat*)arr;\r
- int type;\r
-\r
- if( (unsigned)y >= (unsigned)(mat->rows) ||\r
- (unsigned)x >= (unsigned)(mat->cols) )\r
- CV_Error( CV_StsOutOfRange, "index is out of range" );\r
-\r
- type = CV_MAT_TYPE(mat->type);\r
- if( _type )\r
- *_type = type;\r
-\r
- ptr = mat->data.ptr + (size_t)y*mat->step + x*CV_ELEM_SIZE(type);\r
- }\r
- else if( CV_IS_IMAGE( arr ))\r
- {\r
- IplImage* img = (IplImage*)arr;\r
- int pix_size = (img->depth & 255) >> 3;\r
- int width, height;\r
- ptr = (uchar*)img->imageData;\r
-\r
- if( img->dataOrder == 0 )\r
- pix_size *= img->nChannels;\r
-\r
- if( img->roi )\r
- {\r
- width = img->roi->width;\r
- height = img->roi->height;\r
-\r
- ptr += img->roi->yOffset*img->widthStep +\r
- img->roi->xOffset*pix_size;\r
-\r
- if( img->dataOrder )\r
- {\r
- int coi = img->roi->coi;\r
- if( !coi )\r
- CV_Error( CV_BadCOI,\r
- "COI must be non-null in case of planar images" );\r
- ptr += (coi - 1)*img->imageSize;\r
- }\r
- }\r
- else\r
- {\r
- width = img->width;\r
- height = img->height;\r
- }\r
-\r
- if( (unsigned)y >= (unsigned)height ||\r
- (unsigned)x >= (unsigned)width )\r
- CV_Error( CV_StsOutOfRange, "index is out of range" );\r
-\r
- ptr += y*img->widthStep + x*pix_size;\r
-\r
- if( _type )\r
- {\r
- int type = IplToCvDepth(img->depth);\r
- if( type < 0 || (unsigned)(img->nChannels - 1) > 3 )\r
- CV_Error( CV_StsUnsupportedFormat, "" );\r
-\r
- *_type = CV_MAKETYPE( type, img->nChannels );\r
- }\r
- }\r
- else if( CV_IS_MATND( arr ))\r
- {\r
- CvMatND* mat = (CvMatND*)arr;\r
-\r
- if( mat->dims != 2 || \r
- (unsigned)y >= (unsigned)(mat->dim[0].size) ||\r
- (unsigned)x >= (unsigned)(mat->dim[1].size) )\r
- CV_Error( CV_StsOutOfRange, "index is out of range" );\r
-\r
- ptr = mat->data.ptr + (size_t)y*mat->dim[0].step + x*mat->dim[1].step;\r
- if( _type )\r
- *_type = CV_MAT_TYPE(mat->type);\r
- }\r
- else if( CV_IS_SPARSE_MAT( arr ))\r
- {\r
- int idx[] = { y, x };\r
- ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, _type, 1, 0 );\r
- }\r
- else\r
- {\r
- CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );\r
- }\r
-\r
- return ptr;\r
-}\r
-\r
-\r
-// Returns pointer to specified element of 3d array\r
-CV_IMPL uchar*\r
-cvPtr3D( const CvArr* arr, int z, int y, int x, int* _type )\r
-{\r
- uchar* ptr = 0;\r
- if( CV_IS_MATND( arr ))\r
- {\r
- CvMatND* mat = (CvMatND*)arr;\r
-\r
- if( mat->dims != 3 || \r
- (unsigned)z >= (unsigned)(mat->dim[0].size) ||\r
- (unsigned)y >= (unsigned)(mat->dim[1].size) ||\r
- (unsigned)x >= (unsigned)(mat->dim[2].size) )\r
- CV_Error( CV_StsOutOfRange, "index is out of range" );\r
-\r
- ptr = mat->data.ptr + (size_t)z*mat->dim[0].step +\r
- (size_t)y*mat->dim[1].step + x*mat->dim[2].step;\r
-\r
- if( _type )\r
- *_type = CV_MAT_TYPE(mat->type);\r
- }\r
- else if( CV_IS_SPARSE_MAT( arr ))\r
- {\r
- int idx[] = { z, y, x };\r
- ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, _type, 1, 0 );\r
- }\r
- else\r
- {\r
- CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );\r
- }\r
-\r
- return ptr;\r
-}\r
-\r
-\r
-// Returns pointer to specified element of n-d array\r
-CV_IMPL uchar*\r
-cvPtrND( const CvArr* arr, const int* idx, int* _type,\r
- int create_node, unsigned* precalc_hashval )\r
-{\r
- uchar* ptr = 0;\r
- if( !idx )\r
- CV_Error( CV_StsNullPtr, "NULL pointer to indices" );\r
-\r
- if( CV_IS_SPARSE_MAT( arr ))\r
- ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, \r
- _type, create_node, precalc_hashval );\r
- else if( CV_IS_MATND( arr ))\r
- {\r
- CvMatND* mat = (CvMatND*)arr;\r
- int i;\r
- ptr = mat->data.ptr;\r
-\r
- for( i = 0; i < mat->dims; i++ )\r
- {\r
- if( (unsigned)idx[i] >= (unsigned)(mat->dim[i].size) )\r
- CV_Error( CV_StsOutOfRange, "index is out of range" );\r
- ptr += (size_t)idx[i]*mat->dim[i].step;\r
- }\r
-\r
- if( _type )\r
- *_type = CV_MAT_TYPE(mat->type);\r
- }\r
- else if( CV_IS_MAT_HDR(arr) || CV_IS_IMAGE_HDR(arr) )\r
- ptr = cvPtr2D( arr, idx[0], idx[1], _type );\r
- else\r
- CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );\r
-\r
- return ptr;\r
-}\r
-\r
-\r
-// Returns specifed element of n-D array given linear index\r
-CV_IMPL CvScalar\r
-cvGet1D( const CvArr* arr, int idx )\r
-{\r
- CvScalar scalar = {{0,0,0,0}};\r
- int type = 0;\r
- uchar* ptr;\r
- \r
- if( CV_IS_MAT( arr ) && CV_IS_MAT_CONT( ((CvMat*)arr)->type ))\r
- {\r
- CvMat* mat = (CvMat*)arr;\r
-\r
- type = CV_MAT_TYPE(mat->type);\r
- int pix_size = CV_ELEM_SIZE(type);\r
-\r
- // the first part is mul-free sufficient check\r
- // that the index is within the matrix\r
- if( (unsigned)idx >= (unsigned)(mat->rows + mat->cols - 1) &&\r
- (unsigned)idx >= (unsigned)(mat->rows*mat->cols))\r
- CV_Error( CV_StsOutOfRange, "index is out of range" );\r
-\r
- ptr = mat->data.ptr + (size_t)idx*pix_size;\r
- }\r
- else if( !CV_IS_SPARSE_MAT( arr ) || ((CvSparseMat*)arr)->dims > 1 )\r
- ptr = cvPtr1D( arr, idx, &type );\r
- else\r
- ptr = icvGetNodePtr( (CvSparseMat*)arr, &idx, &type, 0, 0 );\r
-\r
- cvRawDataToScalar( ptr, type, &scalar );\r
-\r
- return scalar;\r
-}\r
-\r
-\r
-// Returns specifed element of 2D array\r
-CV_IMPL CvScalar\r
-cvGet2D( const CvArr* arr, int y, int x )\r
-{\r
- CvScalar scalar = {{0,0,0,0}};\r
- int type = 0;\r
- uchar* ptr;\r
-\r
- if( CV_IS_MAT( arr ))\r
- {\r
- CvMat* mat = (CvMat*)arr;\r
-\r
- if( (unsigned)y >= (unsigned)(mat->rows) ||\r
- (unsigned)x >= (unsigned)(mat->cols) )\r
- CV_Error( CV_StsOutOfRange, "index is out of range" );\r
-\r
- type = CV_MAT_TYPE(mat->type);\r
- ptr = mat->data.ptr + (size_t)y*mat->step + x*CV_ELEM_SIZE(type);\r
- }\r
- else if( !CV_IS_SPARSE_MAT( arr ))\r
- ptr = cvPtr2D( arr, y, x, &type );\r
- else\r
- {\r
- int idx[] = { y, x };\r
- ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, 0, 0 );\r
- }\r
-\r
- cvRawDataToScalar( ptr, type, &scalar );\r
-\r
- return scalar;\r
-}\r
-\r
-\r
-// Returns specifed element of 3D array\r
-CV_IMPL CvScalar\r
-cvGet3D( const CvArr* arr, int z, int y, int x )\r
-{\r
- CvScalar scalar = {{0,0,0,0}};\r
- int type = 0;\r
- uchar* ptr;\r
-\r
- if( !CV_IS_SPARSE_MAT( arr ))\r
- ptr = cvPtr3D( arr, z, y, x, &type );\r
- else\r
- {\r
- int idx[] = { z, y, x };\r
- ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, 0, 0 );\r
- }\r
-\r
- cvRawDataToScalar( ptr, type, &scalar );\r
- return scalar;\r
-}\r
-\r
-\r
-// Returns specifed element of nD array\r
-CV_IMPL CvScalar\r
-cvGetND( const CvArr* arr, const int* idx )\r
-{\r
- CvScalar scalar = {{0,0,0,0}};\r
- int type = 0;\r
- uchar* ptr;\r
-\r
- if( !CV_IS_SPARSE_MAT( arr ))\r
- ptr = cvPtrND( arr, idx, &type );\r
- else\r
- ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, 0, 0 );\r
-\r
- cvRawDataToScalar( ptr, type, &scalar );\r
-\r
- return scalar;\r
-}\r
-\r
-\r
-// Returns specifed element of n-D array given linear index\r
-CV_IMPL double\r
-cvGetReal1D( const CvArr* arr, int idx )\r
-{\r
- double value = 0;\r
- int type = 0;\r
- uchar* ptr;\r
-\r
- if( CV_IS_MAT( arr ) && CV_IS_MAT_CONT( ((CvMat*)arr)->type ))\r
- {\r
- CvMat* mat = (CvMat*)arr;\r
-\r
- type = CV_MAT_TYPE(mat->type);\r
- int pix_size = CV_ELEM_SIZE(type);\r
-\r
- // the first part is mul-free sufficient check\r
- // that the index is within the matrix\r
- if( (unsigned)idx >= (unsigned)(mat->rows + mat->cols - 1) &&\r
- (unsigned)idx >= (unsigned)(mat->rows*mat->cols))\r
- CV_Error( CV_StsOutOfRange, "index is out of range" );\r
-\r
- ptr = mat->data.ptr + (size_t)idx*pix_size;\r
- }\r
- else if( !CV_IS_SPARSE_MAT( arr ) || ((CvSparseMat*)arr)->dims > 1 )\r
- ptr = cvPtr1D( arr, idx, &type );\r
- else\r
- ptr = icvGetNodePtr( (CvSparseMat*)arr, &idx, &type, 0, 0 );\r
-\r
- if( ptr )\r
- {\r
- if( CV_MAT_CN( type ) > 1 )\r
- CV_Error( CV_BadNumChannels, "cvGetReal* support only single-channel arrays" );\r
-\r
- value = icvGetReal( ptr, type );\r
- }\r
- return value;\r
-}\r
-\r
-\r
-// Returns specifed element of 2D array\r
-CV_IMPL double\r
-cvGetReal2D( const CvArr* arr, int y, int x )\r
-{\r
- double value = 0;\r
- int type = 0;\r
- uchar* ptr;\r
- \r
- if( CV_IS_MAT( arr ))\r
- {\r
- CvMat* mat = (CvMat*)arr;\r
-\r
- if( (unsigned)y >= (unsigned)(mat->rows) ||\r
- (unsigned)x >= (unsigned)(mat->cols) )\r
- CV_Error( CV_StsOutOfRange, "index is out of range" );\r
-\r
- type = CV_MAT_TYPE(mat->type);\r
- ptr = mat->data.ptr + (size_t)y*mat->step + x*CV_ELEM_SIZE(type);\r
- }\r
- else if( !CV_IS_SPARSE_MAT( arr ))\r
- ptr = cvPtr2D( arr, y, x, &type );\r
- else\r
- {\r
- int idx[] = { y, x };\r
- ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, 0, 0 );\r
- }\r
-\r
- if( ptr )\r
- {\r
- if( CV_MAT_CN( type ) > 1 )\r
- CV_Error( CV_BadNumChannels, "cvGetReal* support only single-channel arrays" );\r
-\r
- value = icvGetReal( ptr, type );\r
- }\r
-\r
- return value;\r
-}\r
-\r
-\r
-// Returns specifed element of 3D array\r
-CV_IMPL double\r
-cvGetReal3D( const CvArr* arr, int z, int y, int x )\r
-{\r
- double value = 0;\r
- int type = 0;\r
- uchar* ptr;\r
-\r
- if( !CV_IS_SPARSE_MAT( arr ))\r
- ptr = cvPtr3D( arr, z, y, x, &type );\r
- else\r
- {\r
- int idx[] = { z, y, x };\r
- ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, 0, 0 );\r
- }\r
- \r
- if( ptr )\r
- {\r
- if( CV_MAT_CN( type ) > 1 )\r
- CV_Error( CV_BadNumChannels, "cvGetReal* support only single-channel arrays" );\r
-\r
- value = icvGetReal( ptr, type );\r
- }\r
-\r
- return value;\r
-}\r
-\r
-\r
-// Returns specifed element of nD array\r
-CV_IMPL double\r
-cvGetRealND( const CvArr* arr, const int* idx )\r
-{\r
- double value = 0;\r
- int type = 0;\r
- uchar* ptr;\r
- \r
- if( !CV_IS_SPARSE_MAT( arr ))\r
- ptr = cvPtrND( arr, idx, &type );\r
- else\r
- ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, 0, 0 );\r
-\r
- if( ptr )\r
- {\r
- if( CV_MAT_CN( type ) > 1 )\r
- CV_Error( CV_BadNumChannels, "cvGetReal* support only single-channel arrays" );\r
-\r
- value = icvGetReal( ptr, type );\r
- }\r
-\r
- return value;\r
-}\r
-\r
-\r
-// Assigns new value to specifed element of nD array given linear index\r
-CV_IMPL void\r
-cvSet1D( CvArr* arr, int idx, CvScalar scalar )\r
-{\r
- int type = 0;\r
- uchar* ptr;\r
- \r
- if( CV_IS_MAT( arr ) && CV_IS_MAT_CONT( ((CvMat*)arr)->type ))\r
- {\r
- CvMat* mat = (CvMat*)arr;\r
-\r
- type = CV_MAT_TYPE(mat->type);\r
- int pix_size = CV_ELEM_SIZE(type);\r
-\r
- // the first part is mul-free sufficient check\r
- // that the index is within the matrix\r
- if( (unsigned)idx >= (unsigned)(mat->rows + mat->cols - 1) &&\r
- (unsigned)idx >= (unsigned)(mat->rows*mat->cols))\r
- CV_Error( CV_StsOutOfRange, "index is out of range" );\r
-\r
- ptr = mat->data.ptr + (size_t)idx*pix_size;\r
- }\r
- else if( !CV_IS_SPARSE_MAT( arr ) || ((CvSparseMat*)arr)->dims > 1 )\r
- ptr = cvPtr1D( arr, idx, &type );\r
- else\r
- ptr = icvGetNodePtr( (CvSparseMat*)arr, &idx, &type, -1, 0 );\r
-\r
- cvScalarToRawData( &scalar, ptr, type );\r
-}\r
-\r
-\r
-// Assigns new value to specifed element of 2D array\r
-CV_IMPL void\r
-cvSet2D( CvArr* arr, int y, int x, CvScalar scalar )\r
-{\r
- int type = 0;\r
- uchar* ptr;\r
- \r
- if( CV_IS_MAT( arr ))\r
- {\r
- CvMat* mat = (CvMat*)arr;\r
-\r
- if( (unsigned)y >= (unsigned)(mat->rows) ||\r
- (unsigned)x >= (unsigned)(mat->cols) )\r
- CV_Error( CV_StsOutOfRange, "index is out of range" );\r
-\r
- type = CV_MAT_TYPE(mat->type);\r
- ptr = mat->data.ptr + (size_t)y*mat->step + x*CV_ELEM_SIZE(type);\r
- }\r
- else if( !CV_IS_SPARSE_MAT( arr ))\r
- ptr = cvPtr2D( arr, y, x, &type );\r
- else\r
- {\r
- int idx[] = { y, x };\r
- ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, -1, 0 );\r
- }\r
- cvScalarToRawData( &scalar, ptr, type );\r
-}\r
-\r
-\r
-// Assigns new value to specifed element of 3D array\r
-CV_IMPL void\r
-cvSet3D( CvArr* arr, int z, int y, int x, CvScalar scalar )\r
-{\r
- int type = 0;\r
- uchar* ptr;\r
- \r
- if( !CV_IS_SPARSE_MAT( arr ))\r
- ptr = cvPtr3D( arr, z, y, x, &type );\r
- else\r
- {\r
- int idx[] = { z, y, x };\r
- ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, -1, 0 );\r
- }\r
- cvScalarToRawData( &scalar, ptr, type );\r
-}\r
-\r
-\r
-// Assigns new value to specifed element of nD array\r
-CV_IMPL void\r
-cvSetND( CvArr* arr, const int* idx, CvScalar scalar )\r
-{\r
- int type = 0;\r
- uchar* ptr;\r
- \r
- if( !CV_IS_SPARSE_MAT( arr ))\r
- ptr = cvPtrND( arr, idx, &type );\r
- else\r
- ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, -1, 0 );\r
- cvScalarToRawData( &scalar, ptr, type );\r
-}\r
-\r
-\r
-CV_IMPL void\r
-cvSetReal1D( CvArr* arr, int idx, double value )\r
-{\r
- int type = 0;\r
- uchar* ptr;\r
- \r
- if( CV_IS_MAT( arr ) && CV_IS_MAT_CONT( ((CvMat*)arr)->type ))\r
- {\r
- CvMat* mat = (CvMat*)arr;\r
-\r
- type = CV_MAT_TYPE(mat->type);\r
- int pix_size = CV_ELEM_SIZE(type);\r
-\r
- // the first part is mul-free sufficient check\r
- // that the index is within the matrix\r
- if( (unsigned)idx >= (unsigned)(mat->rows + mat->cols - 1) &&\r
- (unsigned)idx >= (unsigned)(mat->rows*mat->cols))\r
- CV_Error( CV_StsOutOfRange, "index is out of range" );\r
-\r
- ptr = mat->data.ptr + (size_t)idx*pix_size;\r
- }\r
- else if( !CV_IS_SPARSE_MAT( arr ) || ((CvSparseMat*)arr)->dims > 1 )\r
- ptr = cvPtr1D( arr, idx, &type );\r
- else\r
- ptr = icvGetNodePtr( (CvSparseMat*)arr, &idx, &type, -1, 0 );\r
-\r
- if( CV_MAT_CN( type ) > 1 )\r
- CV_Error( CV_BadNumChannels, "cvSetReal* support only single-channel arrays" );\r
-\r
- if( ptr )\r
- icvSetReal( value, ptr, type );\r
-}\r
-\r
-\r
-CV_IMPL void\r
-cvSetReal2D( CvArr* arr, int y, int x, double value )\r
-{\r
- int type = 0;\r
- uchar* ptr;\r
- \r
- if( CV_IS_MAT( arr ))\r
- {\r
- CvMat* mat = (CvMat*)arr;\r
-\r
- if( (unsigned)y >= (unsigned)(mat->rows) ||\r
- (unsigned)x >= (unsigned)(mat->cols) )\r
- CV_Error( CV_StsOutOfRange, "index is out of range" );\r
-\r
- type = CV_MAT_TYPE(mat->type);\r
- ptr = mat->data.ptr + (size_t)y*mat->step + x*CV_ELEM_SIZE(type);\r
- }\r
- else if( !CV_IS_SPARSE_MAT( arr ))\r
- {\r
- ptr = cvPtr2D( arr, y, x, &type );\r
- }\r
- else\r
- {\r
- int idx[] = { y, x };\r
- ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, -1, 0 );\r
- }\r
- if( CV_MAT_CN( type ) > 1 )\r
- CV_Error( CV_BadNumChannels, "cvSetReal* support only single-channel arrays" );\r
-\r
- if( ptr )\r
- icvSetReal( value, ptr, type );\r
-}\r
-\r
-\r
-CV_IMPL void\r
-cvSetReal3D( CvArr* arr, int z, int y, int x, double value )\r
-{\r
- int type = 0;\r
- uchar* ptr;\r
- \r
- if( !CV_IS_SPARSE_MAT( arr ))\r
- ptr = cvPtr3D( arr, z, y, x, &type );\r
- else\r
- {\r
- int idx[] = { z, y, x };\r
- ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, -1, 0 );\r
- }\r
- if( CV_MAT_CN( type ) > 1 )\r
- CV_Error( CV_BadNumChannels, "cvSetReal* support only single-channel arrays" );\r
-\r
- if( ptr )\r
- icvSetReal( value, ptr, type );\r
-}\r
-\r
-\r
-CV_IMPL void\r
-cvSetRealND( CvArr* arr, const int* idx, double value )\r
-{\r
- int type = 0;\r
- uchar* ptr;\r
- \r
- if( !CV_IS_SPARSE_MAT( arr ))\r
- ptr = cvPtrND( arr, idx, &type );\r
- else\r
- ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, -1, 0 );\r
-\r
- if( CV_MAT_CN( type ) > 1 )\r
- CV_Error( CV_BadNumChannels, "cvSetReal* support only single-channel arrays" );\r
-\r
- if( ptr )\r
- icvSetReal( value, ptr, type );\r
-}\r
-\r
-\r
-CV_IMPL void\r
-cvClearND( CvArr* arr, const int* idx )\r
-{\r
- if( !CV_IS_SPARSE_MAT( arr ))\r
- {\r
- int type;\r
- uchar* ptr;\r
- ptr = cvPtrND( arr, idx, &type );\r
- if( ptr )\r
- CV_ZERO_CHAR( ptr, CV_ELEM_SIZE(type) );\r
- }\r
- else\r
- icvDeleteNode( (CvSparseMat*)arr, idx, 0 );\r
-}\r
-\r
-\r
-/****************************************************************************************\\r
-* Conversion to CvMat or IplImage *\r
-\****************************************************************************************/\r
-\r
-// convert array (CvMat or IplImage) to CvMat\r
-CV_IMPL CvMat*\r
-cvGetMat( const CvArr* array, CvMat* mat,\r
- int* pCOI, int allowND )\r
-{\r
- CvMat* result = 0;\r
- CvMat* src = (CvMat*)array;\r
- int coi = 0;\r
-\r
- if( !mat || !src )\r
- CV_Error( CV_StsNullPtr, "NULL array pointer is passed" );\r
-\r
- if( CV_IS_MAT_HDR(src))\r
- {\r
- if( !src->data.ptr )\r
- CV_Error( CV_StsNullPtr, "The matrix has NULL data pointer" );\r
- \r
- result = (CvMat*)src;\r
- }\r
- else if( CV_IS_IMAGE_HDR(src) )\r
- {\r
- const IplImage* img = (const IplImage*)src;\r
- int depth, order;\r
-\r
- if( img->imageData == 0 )\r
- CV_Error( CV_StsNullPtr, "The image has NULL data pointer" );\r
-\r
- depth = IplToCvDepth( img->depth );\r
- if( depth < 0 )\r
- CV_Error( CV_BadDepth, "" );\r
-\r
- order = img->dataOrder & (img->nChannels > 1 ? -1 : 0);\r
-\r
- if( img->roi )\r
- {\r
- if( order == IPL_DATA_ORDER_PLANE )\r
- {\r
- int type = depth;\r
-\r
- if( img->roi->coi == 0 )\r
- CV_Error( CV_StsBadFlag,\r
- "Images with planar data layout should be used with COI selected" );\r
-\r
- cvInitMatHeader( mat, img->roi->height,\r
- img->roi->width, type,\r
- img->imageData + (img->roi->coi-1)*img->imageSize +\r
- img->roi->yOffset*img->widthStep +\r
- img->roi->xOffset*CV_ELEM_SIZE(type),\r
- img->widthStep );\r
- }\r
- else /* pixel order */\r
- {\r
- int type = CV_MAKETYPE( depth, img->nChannels );\r
- coi = img->roi->coi;\r
-\r
- if( img->nChannels > CV_CN_MAX )\r
- CV_Error( CV_BadNumChannels,\r
- "The image is interleaved and has over CV_CN_MAX channels" );\r
-\r
- cvInitMatHeader( mat, img->roi->height, img->roi->width,\r
- type, img->imageData +\r
- img->roi->yOffset*img->widthStep +\r
- img->roi->xOffset*CV_ELEM_SIZE(type),\r
- img->widthStep );\r
- }\r
- }\r
- else\r
- {\r
- int type = CV_MAKETYPE( depth, img->nChannels );\r
-\r
- if( order != IPL_DATA_ORDER_PIXEL )\r
- CV_Error( CV_StsBadFlag, "Pixel order should be used with coi == 0" );\r
-\r
- cvInitMatHeader( mat, img->height, img->width, type,\r
- img->imageData, img->widthStep );\r
- }\r
-\r
- result = mat;\r
- }\r
- else if( allowND && CV_IS_MATND_HDR(src) )\r
- {\r
- CvMatND* matnd = (CvMatND*)src;\r
- int i;\r
- int size1 = matnd->dim[0].size, size2 = 1;\r
- \r
- if( !src->data.ptr )\r
- CV_Error( CV_StsNullPtr, "Input array has NULL data pointer" );\r
-\r
- if( !CV_IS_MAT_CONT( matnd->type ))\r
- CV_Error( CV_StsBadArg, "Only continuous nD arrays are supported here" );\r
-\r
- if( matnd->dims > 2 )\r
- for( i = 1; i < matnd->dims; i++ )\r
- size2 *= matnd->dim[i].size;\r
- else\r
- size2 = matnd->dims == 1 ? 1 : matnd->dim[1].size;\r
-\r
- mat->refcount = 0;\r
- mat->hdr_refcount = 0;\r
- mat->data.ptr = matnd->data.ptr;\r
- mat->rows = size1;\r
- mat->cols = size2;\r
- mat->type = CV_MAT_TYPE(matnd->type) | CV_MAT_MAGIC_VAL | CV_MAT_CONT_FLAG;\r
- mat->step = size2*CV_ELEM_SIZE(matnd->type);\r
- mat->step &= size1 > 1 ? -1 : 0;\r
-\r
- icvCheckHuge( mat );\r
- result = mat;\r
- }\r
- else\r
- CV_Error( CV_StsBadFlag, "Unrecognized or unsupported array type" );\r
-\r
- if( pCOI )\r
- *pCOI = coi;\r
-\r
- return result;\r
-}\r
-\r
-\r
-CV_IMPL CvArr*\r
-cvReshapeMatND( const CvArr* arr,\r
- int sizeof_header, CvArr* _header,\r
- int new_cn, int new_dims, int* new_sizes )\r
-{\r
- CvArr* result = 0;\r
- int dims, coi = 0;\r
-\r
- if( !arr || !_header )\r
- CV_Error( CV_StsNullPtr, "NULL pointer to array or destination header" );\r
-\r
- if( new_cn == 0 && new_dims == 0 )\r
- CV_Error( CV_StsBadArg, "None of array parameters is changed: dummy call?" );\r
-\r
- dims = cvGetDims( arr );\r
-\r
- if( new_dims == 0 )\r
- {\r
- new_sizes = 0;\r
- new_dims = dims;\r
- }\r
- else if( new_dims == 1 )\r
- {\r
- new_sizes = 0;\r
- }\r
- else\r
- {\r
- if( new_dims <= 0 || new_dims > CV_MAX_DIM )\r
- CV_Error( CV_StsOutOfRange, "Non-positive or too large number of dimensions" );\r
- if( !new_sizes )\r
- CV_Error( CV_StsNullPtr, "New dimension sizes are not specified" );\r
- }\r
-\r
- if( new_dims <= 2 )\r
- {\r
- CvMat* mat = (CvMat*)arr;\r
- CvMat* header = (CvMat*)_header;\r
- int* refcount = 0;\r
- int hdr_refcount = 0;\r
- int total_width, new_rows, cn;\r
-\r
- if( sizeof_header != sizeof(CvMat))\r
- CV_Error( CV_StsBadArg, "The header should be CvMat" );\r
-\r
- if( mat == header )\r
- {\r
- refcount = mat->refcount;\r
- hdr_refcount = mat->hdr_refcount;\r
- }\r
- else if( !CV_IS_MAT( mat ))\r
- mat = cvGetMat( mat, header, &coi, 1 );\r
-\r
- cn = CV_MAT_CN( mat->type );\r
- total_width = mat->cols * cn;\r
-\r
- if( new_cn == 0 )\r
- new_cn = cn;\r
-\r
- if( new_sizes )\r
- new_rows = new_sizes[0];\r
- else if( new_dims == 1 )\r
- new_rows = total_width*mat->rows/new_cn;\r
- else\r
- {\r
- new_rows = mat->rows;\r
- if( new_cn > total_width )\r
- new_rows = mat->rows * total_width / new_cn;\r
- }\r
-\r
- if( new_rows != mat->rows )\r
- {\r
- int total_size = total_width * mat->rows;\r
-\r
- if( !CV_IS_MAT_CONT( mat->type ))\r
- CV_Error( CV_BadStep,\r
- "The matrix is not continuous so the number of rows can not be changed" );\r
-\r
- total_width = total_size / new_rows;\r
-\r
- if( total_width * new_rows != total_size )\r
- CV_Error( CV_StsBadArg, "The total number of matrix elements "\r
- "is not divisible by the new number of rows" );\r
- }\r
-\r
- header->rows = new_rows;\r
- header->cols = total_width / new_cn;\r
-\r
- if( header->cols * new_cn != total_width ||\r
- (new_sizes && header->cols != new_sizes[1]) )\r
- CV_Error( CV_StsBadArg, "The total matrix width is not "\r
- "divisible by the new number of columns" );\r
-\r
- header->type = CV_MAKETYPE( mat->type & ~CV_MAT_CN_MASK, new_cn );\r
- header->step = header->cols * CV_ELEM_SIZE(mat->type);\r
- header->step &= new_rows > 1 ? -1 : 0;\r
- header->refcount = refcount;\r
- header->hdr_refcount = hdr_refcount;\r
- }\r
- else\r
- {\r
- CvMatND* header = (CvMatND*)_header;\r
-\r
- if( sizeof_header != sizeof(CvMatND))\r
- CV_Error( CV_StsBadSize, "The header should be CvMatND" );\r
- \r
- if( !new_sizes )\r
- {\r
- if( !CV_IS_MATND( arr ))\r
- CV_Error( CV_StsBadArg, "The source array must be CvMatND" );\r
-\r
- {\r
- CvMatND* mat = (CvMatND*)arr;\r
- assert( new_cn > 0 );\r
- int last_dim_size = mat->dim[mat->dims-1].size*CV_MAT_CN(mat->type);\r
- int new_size = last_dim_size/new_cn;\r
-\r
- if( new_size*new_cn != last_dim_size )\r
- CV_Error( CV_StsBadArg,\r
- "The last dimension full size is not divisible by new number of channels");\r
-\r
- if( mat != header )\r
- {\r
- memcpy( header, mat, sizeof(*header));\r
- header->refcount = 0;\r
- header->hdr_refcount = 0;\r
- }\r
-\r
- header->dim[header->dims-1].size = new_size;\r
- header->type = CV_MAKETYPE( header->type & ~CV_MAT_CN_MASK, new_cn );\r
- }\r
- }\r
- else\r
- {\r
- CvMatND stub;\r
- CvMatND* mat = (CvMatND*)arr;\r
- int i, size1, size2;\r
- int step;\r
- \r
- if( new_cn != 0 )\r
- CV_Error( CV_StsBadArg,\r
- "Simultaneous change of shape and number of channels is not supported. "\r
- "Do it by 2 separate calls" );\r
- \r
- if( !CV_IS_MATND( mat ))\r
- {\r
- cvGetMatND( mat, &stub, &coi );\r
- mat = &stub;\r
- }\r
-\r
- if( CV_IS_MAT_CONT( mat->type ))\r
- CV_Error( CV_StsBadArg, "Non-continuous nD arrays are not supported" );\r
-\r
- size1 = mat->dim[0].size;\r
- for( i = 1; i < dims; i++ )\r
- size1 *= mat->dim[i].size;\r
-\r
- size2 = 1;\r
- for( i = 0; i < new_dims; i++ )\r
- {\r
- if( new_sizes[i] <= 0 )\r
- CV_Error( CV_StsBadSize,\r
- "One of new dimension sizes is non-positive" );\r
- size2 *= new_sizes[i];\r
- }\r
-\r
- if( size1 != size2 )\r
- CV_Error( CV_StsBadSize,\r
- "Number of elements in the original and reshaped array is different" );\r
-\r
- if( header != mat )\r
- {\r
- header->refcount = 0;\r
- header->hdr_refcount = 0;\r
- }\r
-\r
- header->dims = new_dims;\r
- header->type = mat->type;\r
- header->data.ptr = mat->data.ptr;\r
- step = CV_ELEM_SIZE(header->type);\r
-\r
- for( i = new_dims - 1; i >= 0; i-- )\r
- {\r
- header->dim[i].size = new_sizes[i];\r
- header->dim[i].step = step;\r
- step *= new_sizes[i];\r
- }\r
- }\r
- }\r
-\r
- if( !coi )\r
- CV_Error( CV_BadCOI, "COI is not supported by this operation" );\r
-\r
- result = _header;\r
- return result;\r
-}\r
-\r
-\r
-CV_IMPL CvMat*\r
-cvReshape( const CvArr* array, CvMat* header,\r
- int new_cn, int new_rows )\r
-{\r
- CvMat* result = 0;\r
- CvMat *mat = (CvMat*)array;\r
- int total_width, new_width;\r
-\r
- if( !header )\r
- CV_Error( CV_StsNullPtr, "" );\r
-\r
- if( !CV_IS_MAT( mat ))\r
- {\r
- int coi = 0;\r
- mat = cvGetMat( mat, header, &coi, 1 );\r
- if( coi )\r
- CV_Error( CV_BadCOI, "COI is not supported" );\r
- }\r
-\r
- if( new_cn == 0 )\r
- new_cn = CV_MAT_CN(mat->type);\r
- else if( (unsigned)(new_cn - 1) > 3 )\r
- CV_Error( CV_BadNumChannels, "" );\r
-\r
- if( mat != header )\r
- {\r
- int hdr_refcount = header->hdr_refcount;\r
- *header = *mat;\r
- header->refcount = 0;\r
- header->hdr_refcount = hdr_refcount;\r
- }\r
-\r
- total_width = mat->cols * CV_MAT_CN( mat->type );\r
-\r
- if( (new_cn > total_width || total_width % new_cn != 0) && new_rows == 0 )\r
- new_rows = mat->rows * total_width / new_cn;\r
-\r
- if( new_rows == 0 || new_rows == mat->rows )\r
- {\r
- header->rows = mat->rows;\r
- header->step = mat->step;\r
- }\r
- else\r
- {\r
- int total_size = total_width * mat->rows;\r
- if( !CV_IS_MAT_CONT( mat->type ))\r
- CV_Error( CV_BadStep,\r
- "The matrix is not continuous, thus its number of rows can not be changed" );\r
-\r
- if( (unsigned)new_rows > (unsigned)total_size )\r
- CV_Error( CV_StsOutOfRange, "Bad new number of rows" );\r
-\r
- total_width = total_size / new_rows;\r
-\r
- if( total_width * new_rows != total_size )\r
- CV_Error( CV_StsBadArg, "The total number of matrix elements "\r
- "is not divisible by the new number of rows" );\r
-\r
- header->rows = new_rows;\r
- header->step = total_width * CV_ELEM_SIZE1(mat->type);\r
- }\r
-\r
- new_width = total_width / new_cn;\r
-\r
- if( new_width * new_cn != total_width )\r
- CV_Error( CV_BadNumChannels,\r
- "The total width is not divisible by the new number of channels" );\r
-\r
- header->cols = new_width;\r
- header->type = CV_MAKETYPE( mat->type & ~CV_MAT_CN_MASK, new_cn );\r
-\r
- result = header;\r
- return result;\r
-}\r
-\r
-\r
-// convert array (CvMat or IplImage) to IplImage\r
-CV_IMPL IplImage*\r
-cvGetImage( const CvArr* array, IplImage* img )\r
-{\r
- IplImage* result = 0;\r
- const IplImage* src = (const IplImage*)array;\r
- int depth;\r
-\r
- if( !img )\r
- CV_Error( CV_StsNullPtr, "" );\r
-\r
- if( !CV_IS_IMAGE_HDR(src) )\r
- {\r
- const CvMat* mat = (const CvMat*)src;\r
- \r
- if( !CV_IS_MAT_HDR(mat))\r
- CV_Error( CV_StsBadFlag, "" );\r
-\r
- if( mat->data.ptr == 0 )\r
- CV_Error( CV_StsNullPtr, "" );\r
-\r
- depth = cvCvToIplDepth(mat->type);\r
-\r
- cvInitImageHeader( img, cvSize(mat->cols, mat->rows),\r
- depth, CV_MAT_CN(mat->type) );\r
- cvSetData( img, mat->data.ptr, mat->step );\r
-\r
- result = img;\r
- }\r
- else\r
- {\r
- result = (IplImage*)src;\r
- }\r
-\r
- return result;\r
-}\r
-\r
-\r
-/****************************************************************************************\\r
-* IplImage-specific functions *\r
-\****************************************************************************************/\r
-\r
-static IplROI* icvCreateROI( int coi, int xOffset, int yOffset, int width, int height )\r
-{\r
- IplROI *roi = 0;\r
- if( !CvIPL.createROI )\r
- {\r
- roi = (IplROI*)cvAlloc( sizeof(*roi));\r
-\r
- roi->coi = coi;\r
- roi->xOffset = xOffset;\r
- roi->yOffset = yOffset;\r
- roi->width = width;\r
- roi->height = height;\r
- }\r
- else\r
- {\r
- roi = CvIPL.createROI( coi, xOffset, yOffset, width, height );\r
- }\r
-\r
- return roi;\r
-}\r
-\r
-static void\r
-icvGetColorModel( int nchannels, const char** colorModel, const char** channelSeq )\r
-{\r
- static const char* tab[][2] =\r
- {\r
- {"GRAY", "GRAY"},\r
- {"",""},\r
- {"RGB","BGR"},\r
- {"RGB","BGRA"}\r
- };\r
-\r
- nchannels--;\r
- *colorModel = *channelSeq = "";\r
-\r
- if( (unsigned)nchannels <= 3 )\r
- {\r
- *colorModel = tab[nchannels][0];\r
- *channelSeq = tab[nchannels][1];\r
- }\r
-}\r
-\r
-\r
-// create IplImage header\r
-CV_IMPL IplImage *\r
-cvCreateImageHeader( CvSize size, int depth, int channels )\r
-{\r
- IplImage *img = 0;\r
-\r
- if( !CvIPL.createHeader )\r
- {\r
- img = (IplImage *)cvAlloc( sizeof( *img ));\r
- cvInitImageHeader( img, size, depth, channels, IPL_ORIGIN_TL,\r
- CV_DEFAULT_IMAGE_ROW_ALIGN );\r
- }\r
- else\r
- {\r
- const char *colorModel, *channelSeq;\r
-\r
- icvGetColorModel( channels, &colorModel, &channelSeq );\r
-\r
- img = CvIPL.createHeader( channels, 0, depth, (char*)colorModel, (char*)channelSeq,\r
- IPL_DATA_ORDER_PIXEL, IPL_ORIGIN_TL,\r
- CV_DEFAULT_IMAGE_ROW_ALIGN,\r
- size.width, size.height, 0, 0, 0, 0 );\r
- }\r
-\r
- return img;\r
-}\r
-\r
-\r
-// create IplImage header and allocate underlying data\r
-CV_IMPL IplImage *\r
-cvCreateImage( CvSize size, int depth, int channels )\r
-{\r
- IplImage *img = cvCreateImageHeader( size, depth, channels );\r
- assert( img );\r
- cvCreateData( img );\r
-\r
- return img;\r
-}\r
-\r
-\r
-// initalize IplImage header, allocated by the user\r
-CV_IMPL IplImage*\r
-cvInitImageHeader( IplImage * image, CvSize size, int depth,\r
- int channels, int origin, int align )\r
-{\r
- const char *colorModel, *channelSeq;\r
-\r
- if( !image )\r
- CV_Error( CV_HeaderIsNull, "null pointer to header" );\r
-\r
- memset( image, 0, sizeof( *image ));\r
- image->nSize = sizeof( *image );\r
-\r
- icvGetColorModel( channels, &colorModel, &channelSeq );\r
- strncpy( image->colorModel, colorModel, 4 );\r
- strncpy( image->channelSeq, channelSeq, 4 );\r
-\r
- if( size.width < 0 || size.height < 0 )\r
- CV_Error( CV_BadROISize, "Bad input roi" );\r
-\r
- if( (depth != (int)IPL_DEPTH_1U && depth != (int)IPL_DEPTH_8U &&\r
- depth != (int)IPL_DEPTH_8S && depth != (int)IPL_DEPTH_16U &&\r
- depth != (int)IPL_DEPTH_16S && depth != (int)IPL_DEPTH_32S &&\r
- depth != (int)IPL_DEPTH_32F && depth != (int)IPL_DEPTH_64F) ||\r
- channels < 0 )\r
- CV_Error( CV_BadDepth, "Unsupported format" );\r
- if( origin != CV_ORIGIN_BL && origin != CV_ORIGIN_TL )\r
- CV_Error( CV_BadOrigin, "Bad input origin" );\r
-\r
- if( align != 4 && align != 8 )\r
- CV_Error( CV_BadAlign, "Bad input align" );\r
-\r
- image->width = size.width;\r
- image->height = size.height;\r
-\r
- if( image->roi )\r
- {\r
- image->roi->coi = 0;\r
- image->roi->xOffset = image->roi->yOffset = 0;\r
- image->roi->width = size.width;\r
- image->roi->height = size.height;\r
- }\r
-\r
- image->nChannels = MAX( channels, 1 );\r
- image->depth = depth;\r
- image->align = align;\r
- image->widthStep = (((image->width * image->nChannels *\r
- (image->depth & ~IPL_DEPTH_SIGN) + 7)/8)+ align - 1) & (~(align - 1));\r
- image->origin = origin;\r
- image->imageSize = image->widthStep * image->height;\r
-\r
- return image;\r
-}\r
-\r
-\r
-CV_IMPL void\r
-cvReleaseImageHeader( IplImage** image )\r
-{\r
- if( !image )\r
- CV_Error( CV_StsNullPtr, "" );\r
-\r
- if( *image )\r
- {\r
- IplImage* img = *image;\r
- *image = 0;\r
- \r
- if( !CvIPL.deallocate )\r
- {\r
- cvFree( &img->roi );\r
- cvFree( &img );\r
- }\r
- else\r
- {\r
- CvIPL.deallocate( img, IPL_IMAGE_HEADER | IPL_IMAGE_ROI );\r
- }\r
- }\r
-}\r
-\r
-\r
-CV_IMPL void\r
-cvReleaseImage( IplImage ** image )\r
-{\r
- if( !image )\r
- CV_Error( CV_StsNullPtr, "" );\r
-\r
- if( *image )\r
- {\r
- IplImage* img = *image;\r
- *image = 0;\r
- \r
- cvReleaseData( img );\r
- cvReleaseImageHeader( &img );\r
- }\r
-}\r
-\r
-\r
-CV_IMPL void\r
-cvSetImageROI( IplImage* image, CvRect rect )\r
-{\r
- if( !image )\r
- CV_Error( CV_HeaderIsNull, "" );\r
-\r
- if( rect.x > image->width || rect.y > image->height )\r
- CV_Error( CV_BadROISize, "" );\r
-\r
- if( rect.x + rect.width < 0 || rect.y + rect.height < 0 )\r
- CV_Error( CV_BadROISize, "" );\r
-\r
- if( rect.x < 0 )\r
- {\r
- rect.width += rect.x;\r
- rect.x = 0;\r
- }\r
-\r
- if( rect.y < 0 )\r
- {\r
- rect.height += rect.y;\r
- rect.y = 0;\r
- }\r
-\r
- if( rect.x + rect.width > image->width )\r
- rect.width = image->width - rect.x;\r
-\r
- if( rect.y + rect.height > image->height )\r
- rect.height = image->height - rect.y;\r
-\r
- if( image->roi )\r
- {\r
- image->roi->xOffset = rect.x;\r
- image->roi->yOffset = rect.y;\r
- image->roi->width = rect.width;\r
- image->roi->height = rect.height;\r
- }\r
- else\r
- image->roi = icvCreateROI( 0, rect.x, rect.y, rect.width, rect.height );\r
-}\r
-\r
-\r
-CV_IMPL void\r
-cvResetImageROI( IplImage* image )\r
-{\r
- if( !image )\r
- CV_Error( CV_HeaderIsNull, "" );\r
-\r
- if( image->roi )\r
- {\r
- if( !CvIPL.deallocate )\r
- {\r
- cvFree( &image->roi );\r
- }\r
- else\r
- {\r
- CvIPL.deallocate( image, IPL_IMAGE_ROI );\r
- image->roi = 0;\r
- }\r
- }\r
-}\r
-\r
-\r
-CV_IMPL CvRect\r
-cvGetImageROI( const IplImage* img )\r
-{\r
- CvRect rect = { 0, 0, 0, 0 };\r
- if( !img )\r
- CV_Error( CV_StsNullPtr, "Null pointer to image" );\r
-\r
- if( img->roi )\r
- rect = cvRect( img->roi->xOffset, img->roi->yOffset,\r
- img->roi->width, img->roi->height );\r
- else\r
- rect = cvRect( 0, 0, img->width, img->height );\r
- \r
- return rect;\r
-}\r
-\r
-\r
-CV_IMPL void\r
-cvSetImageCOI( IplImage* image, int coi )\r
-{\r
- if( !image )\r
- CV_Error( CV_HeaderIsNull, "" );\r
-\r
- if( (unsigned)coi > (unsigned)(image->nChannels) )\r
- CV_Error( CV_BadCOI, "" );\r
-\r
- if( image->roi || coi != 0 )\r
- {\r
- if( image->roi )\r
- {\r
- image->roi->coi = coi;\r
- }\r
- else\r
- {\r
- image->roi = icvCreateROI( coi, 0, 0, image->width, image->height );\r
- }\r
- }\r
-}\r
-\r
-\r
-CV_IMPL int\r
-cvGetImageCOI( const IplImage* image )\r
-{\r
- if( !image )\r
- CV_Error( CV_HeaderIsNull, "" );\r
-\r
- return image->roi ? image->roi->coi : 0;\r
-}\r
-\r
-\r
-CV_IMPL IplImage*\r
-cvCloneImage( const IplImage* src )\r
-{\r
- IplImage* dst = 0;\r
-\r
- if( !CV_IS_IMAGE_HDR( src ))\r
- CV_Error( CV_StsBadArg, "Bad image header" );\r
-\r
- if( !CvIPL.cloneImage )\r
- {\r
- dst = (IplImage*)cvAlloc( sizeof(*dst));\r
-\r
- memcpy( dst, src, sizeof(*src));\r
- dst->imageData = dst->imageDataOrigin = 0;\r
- dst->roi = 0;\r
-\r
- if( src->roi )\r
- {\r
- dst->roi = icvCreateROI( src->roi->coi, src->roi->xOffset,\r
- src->roi->yOffset, src->roi->width, src->roi->height );\r
- }\r
-\r
- if( src->imageData )\r
- {\r
- int size = src->imageSize;\r
- cvCreateData( dst );\r
- memcpy( dst->imageData, src->imageData, size );\r
- }\r
- }\r
- else\r
- dst = CvIPL.cloneImage( src );\r
-\r
- return dst;\r
-}\r
-\r
-\r
-/****************************************************************************************\\r
-* Additional operations on CvTermCriteria *\r
-\****************************************************************************************/\r
-\r
-CV_IMPL CvTermCriteria\r
-cvCheckTermCriteria( CvTermCriteria criteria, double default_eps,\r
- int default_max_iters )\r
-{\r
- CvTermCriteria crit;\r
-\r
- crit.type = CV_TERMCRIT_ITER|CV_TERMCRIT_EPS;\r
- crit.max_iter = default_max_iters;\r
- crit.epsilon = (float)default_eps;\r
-\r
- if( (criteria.type & ~(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER)) != 0 )\r
- CV_Error( CV_StsBadArg,\r
- "Unknown type of term criteria" );\r
-\r
- if( (criteria.type & CV_TERMCRIT_ITER) != 0 )\r
- {\r
- if( criteria.max_iter <= 0 )\r
- CV_Error( CV_StsBadArg,\r
- "Iterations flag is set and maximum number of iterations is <= 0" );\r
- crit.max_iter = criteria.max_iter;\r
- }\r
- \r
- if( (criteria.type & CV_TERMCRIT_EPS) != 0 )\r
- {\r
- if( criteria.epsilon < 0 )\r
- CV_Error( CV_StsBadArg, "Accuracy flag is set and epsilon is < 0" );\r
-\r
- crit.epsilon = criteria.epsilon;\r
- }\r
-\r
- if( (criteria.type & (CV_TERMCRIT_EPS | CV_TERMCRIT_ITER)) == 0 )\r
- CV_Error( CV_StsBadArg,\r
- "Neither accuracy nor maximum iterations "\r
- "number flags are set in criteria type" );\r
-\r
- crit.epsilon = (float)MAX( 0, crit.epsilon );\r
- crit.max_iter = MAX( 1, crit.max_iter );\r
-\r
- return crit;\r
-}\r
-\r
-\r
-/* End of file. */\r
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+// By downloading, copying, installing or using the software you agree to this license.
+// If you do not agree to this license, do not download, install,
+// copy or use the software.
+//
+//
+// Intel License Agreement
+// For Open Source Computer Vision Library
+//
+// Copyright (C) 2000, Intel Corporation, all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistribution's of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// * Redistribution's in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// * The name of Intel Corporation may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+/* ////////////////////////////////////////////////////////////////////
+//
+// CvMat, CvMatND, CvSparceMat and IplImage support functions
+// (creation, deletion, copying, retrieving and setting elements etc.)
+//
+// */
+
+#include "_cxcore.h"
+
+
+static struct
+{
+ Cv_iplCreateImageHeader createHeader;
+ Cv_iplAllocateImageData allocateData;
+ Cv_iplDeallocate deallocate;
+ Cv_iplCreateROI createROI;
+ Cv_iplCloneImage cloneImage;
+}
+CvIPL;
+
+// Makes the library use native IPL image allocators
+CV_IMPL void
+cvSetIPLAllocators( Cv_iplCreateImageHeader createHeader,
+ Cv_iplAllocateImageData allocateData,
+ Cv_iplDeallocate deallocate,
+ Cv_iplCreateROI createROI,
+ Cv_iplCloneImage cloneImage )
+{
+ int count = (createHeader != 0) + (allocateData != 0) + (deallocate != 0) +
+ (createROI != 0) + (cloneImage != 0);
+
+ if( count != 0 && count != 5 )
+ CV_Error( CV_StsBadArg, "Either all the pointers should be null or "
+ "they all should be non-null" );
+
+ CvIPL.createHeader = createHeader;
+ CvIPL.allocateData = allocateData;
+ CvIPL.deallocate = deallocate;
+ CvIPL.createROI = createROI;
+ CvIPL.cloneImage = cloneImage;
+}
+
+
+/****************************************************************************************\
+* CvMat creation and basic operations *
+\****************************************************************************************/
+
+// Creates CvMat and underlying data
+CV_IMPL CvMat*
+cvCreateMat( int height, int width, int type )
+{
+ CvMat* arr = cvCreateMatHeader( height, width, type );
+ cvCreateData( arr );
+
+ return arr;
+}
+
+
+static void icvCheckHuge( CvMat* arr )
+{
+ if( (int64)arr->step*arr->rows > INT_MAX )
+ arr->type &= ~CV_MAT_CONT_FLAG;
+}
+
+// Creates CvMat header only
+CV_IMPL CvMat*
+cvCreateMatHeader( int rows, int cols, int type )
+{
+ type = CV_MAT_TYPE(type);
+
+ if( rows <= 0 || cols <= 0 )
+ CV_Error( CV_StsBadSize, "Non-positive width or height" );
+
+ int min_step = CV_ELEM_SIZE(type)*cols;
+ if( min_step <= 0 )
+ CV_Error( CV_StsUnsupportedFormat, "Invalid matrix type" );
+
+ CvMat* arr = (CvMat*)cvAlloc( sizeof(*arr));
+
+ arr->step = min_step;
+ arr->type = CV_MAT_MAGIC_VAL | type | CV_MAT_CONT_FLAG;
+ arr->rows = rows;
+ arr->cols = cols;
+ arr->data.ptr = 0;
+ arr->refcount = 0;
+ arr->hdr_refcount = 1;
+
+ icvCheckHuge( arr );
+ return arr;
+}
+
+
+// Initializes CvMat header, allocated by the user
+CV_IMPL CvMat*
+cvInitMatHeader( CvMat* arr, int rows, int cols,
+ int type, void* data, int step )
+{
+ if( !arr )
+ CV_Error( CV_StsNullPtr, "" );
+
+ if( (unsigned)CV_MAT_DEPTH(type) > CV_DEPTH_MAX )
+ CV_Error( CV_BadNumChannels, "" );
+
+ if( rows <= 0 || cols <= 0 )
+ CV_Error( CV_StsBadSize, "Non-positive cols or rows" );
+
+ type = CV_MAT_TYPE( type );
+ arr->type = type | CV_MAT_MAGIC_VAL;
+ arr->rows = rows;
+ arr->cols = cols;
+ arr->data.ptr = (uchar*)data;
+ arr->refcount = 0;
+ arr->hdr_refcount = 0;
+
+ int pix_size = CV_ELEM_SIZE(type);
+ int min_step = arr->cols*pix_size;
+
+ if( step != CV_AUTOSTEP && step != 0 )
+ {
+ if( step < min_step )
+ CV_Error( CV_BadStep, "" );
+ arr->step = step;
+ }
+ else
+ {
+ arr->step = min_step;
+ }
+
+ arr->type = CV_MAT_MAGIC_VAL | type |
+ (arr->rows == 1 || arr->step == min_step ? CV_MAT_CONT_FLAG : 0);
+
+ icvCheckHuge( arr );
+ return arr;
+}
+
+
+#undef CV_IS_MAT_HDR_Z
+#define CV_IS_MAT_HDR_Z(mat) \
+ ((mat) != NULL && \
+ (((const CvMat*)(mat))->type & CV_MAGIC_MASK) == CV_MAT_MAGIC_VAL && \
+ ((const CvMat*)(mat))->cols >= 0 && ((const CvMat*)(mat))->rows >= 0)
+
+// Deallocates the CvMat structure and underlying data
+CV_IMPL void
+cvReleaseMat( CvMat** array )
+{
+ if( !array )
+ CV_Error( CV_HeaderIsNull, "" );
+
+ if( *array )
+ {
+ CvMat* arr = *array;
+
+ if( !CV_IS_MAT_HDR_Z(arr) && !CV_IS_MATND_HDR(arr) )
+ CV_Error( CV_StsBadFlag, "" );
+
+ *array = 0;
+
+ cvDecRefData( arr );
+ cvFree( &arr );
+ }
+}
+
+
+// Creates a copy of matrix
+CV_IMPL CvMat*
+cvCloneMat( const CvMat* src )
+{
+ if( !CV_IS_MAT_HDR( src ))
+ CV_Error( CV_StsBadArg, "Bad CvMat header" );
+
+ CvMat* dst = cvCreateMatHeader( src->rows, src->cols, src->type );
+
+ if( src->data.ptr )
+ {
+ cvCreateData( dst );
+ cvCopy( src, dst );
+ }
+
+ return dst;
+}
+
+
+/****************************************************************************************\
+* CvMatND creation and basic operations *
+\****************************************************************************************/
+
+CV_IMPL CvMatND*
+cvInitMatNDHeader( CvMatND* mat, int dims, const int* sizes,
+ int type, void* data )
+{
+ type = CV_MAT_TYPE(type);
+ int64 step = CV_ELEM_SIZE(type);
+
+ if( !mat )
+ CV_Error( CV_StsNullPtr, "NULL matrix header pointer" );
+
+ if( step == 0 )
+ CV_Error( CV_StsUnsupportedFormat, "invalid array data type" );
+
+ if( !sizes )
+ CV_Error( CV_StsNullPtr, "NULL <sizes> pointer" );
+
+ if( dims <= 0 || dims > CV_MAX_DIM )
+ CV_Error( CV_StsOutOfRange,
+ "non-positive or too large number of dimensions" );
+
+ for( int i = dims - 1; i >= 0; i-- )
+ {
+ if( sizes[i] <= 0 )
+ CV_Error( CV_StsBadSize, "one of dimesion sizes is non-positive" );
+ mat->dim[i].size = sizes[i];
+ if( step > INT_MAX )
+ CV_Error( CV_StsOutOfRange, "The array is too big" );
+ mat->dim[i].step = (int)step;
+ step *= sizes[i];
+ }
+
+ mat->type = CV_MATND_MAGIC_VAL | (step <= INT_MAX ? CV_MAT_CONT_FLAG : 0) | type;
+ mat->dims = dims;
+ mat->data.ptr = (uchar*)data;
+ mat->refcount = 0;
+ mat->hdr_refcount = 0;
+ return mat;
+}
+
+
+// Creates CvMatND and underlying data
+CV_IMPL CvMatND*
+cvCreateMatND( int dims, const int* sizes, int type )
+{
+ CvMatND* arr = cvCreateMatNDHeader( dims, sizes, type );
+ cvCreateData( arr );
+
+ return arr;
+}
+
+
+// Creates CvMatND header only
+CV_IMPL CvMatND*
+cvCreateMatNDHeader( int dims, const int* sizes, int type )
+{
+ if( dims <= 0 || dims > CV_MAX_DIM )
+ CV_Error( CV_StsOutOfRange,
+ "non-positive or too large number of dimensions" );
+
+ CvMatND* arr = (CvMatND*)cvAlloc( sizeof(*arr) );
+
+ cvInitMatNDHeader( arr, dims, sizes, type, 0 );
+ arr->hdr_refcount = 1;
+ return arr;
+}
+
+
+// Creates a copy of nD array
+CV_IMPL CvMatND*
+cvCloneMatND( const CvMatND* src )
+{
+ if( !CV_IS_MATND_HDR( src ))
+ CV_Error( CV_StsBadArg, "Bad CvMatND header" );
+
+ int* sizes = (int*)cvStackAlloc( src->dims*sizeof(sizes[0]) );
+
+ for( int i = 0; i < src->dims; i++ )
+ sizes[i] = src->dim[i].size;
+
+ CvMatND* dst = cvCreateMatNDHeader( src->dims, sizes, src->type );
+
+ if( src->data.ptr )
+ {
+ cvCreateData( dst );
+ cvCopy( src, dst );
+ }
+
+ return dst;
+}
+
+
+static CvMatND*
+cvGetMatND( const CvArr* arr, CvMatND* matnd, int* coi )
+{
+ CvMatND* result = 0;
+
+ if( coi )
+ *coi = 0;
+
+ if( !matnd || !arr )
+ CV_Error( CV_StsNullPtr, "NULL array pointer is passed" );
+
+ if( CV_IS_MATND_HDR(arr))
+ {
+ if( !((CvMatND*)arr)->data.ptr )
+ CV_Error( CV_StsNullPtr, "The matrix has NULL data pointer" );
+
+ result = (CvMatND*)arr;
+ }
+ else
+ {
+ CvMat stub, *mat = (CvMat*)arr;
+
+ if( CV_IS_IMAGE_HDR( mat ))
+ mat = cvGetMat( mat, &stub, coi );
+
+ if( !CV_IS_MAT_HDR( mat ))
+ CV_Error( CV_StsBadArg, "Unrecognized or unsupported array type" );
+
+ if( !mat->data.ptr )
+ CV_Error( CV_StsNullPtr, "Input array has NULL data pointer" );
+
+ matnd->data.ptr = mat->data.ptr;
+ matnd->refcount = 0;
+ matnd->hdr_refcount = 0;
+ matnd->type = mat->type;
+ matnd->dims = 2;
+ matnd->dim[0].size = mat->rows;
+ matnd->dim[0].step = mat->step;
+ matnd->dim[1].size = mat->cols;
+ matnd->dim[1].step = CV_ELEM_SIZE(mat->type);
+ result = matnd;
+ }
+
+ return result;
+}
+
+
+// returns number of dimensions to iterate.
+/*
+Checks whether <count> arrays have equal type, sizes (mask is optional array
+that needs to have the same size, but 8uC1 or 8sC1 type).
+Returns number of dimensions to iterate through:
+0 means that all arrays are continuous,
+1 means that all arrays are vectors of continuous arrays etc.
+and the size of largest common continuous part of the arrays
+*/
+CV_IMPL int
+cvInitNArrayIterator( int count, CvArr** arrs,
+ const CvArr* mask, CvMatND* stubs,
+ CvNArrayIterator* iterator, int flags )
+{
+ int dims = -1;
+ int i, j, size, dim0 = -1;
+ int64 step;
+ CvMatND* hdr0 = 0;
+
+ if( count < 1 || count > CV_MAX_ARR )
+ CV_Error( CV_StsOutOfRange, "Incorrect number of arrays" );
+
+ if( !arrs || !stubs )
+ CV_Error( CV_StsNullPtr, "Some of required array pointers is NULL" );
+
+ if( !iterator )
+ CV_Error( CV_StsNullPtr, "Iterator pointer is NULL" );
+
+ for( i = 0; i <= count; i++ )
+ {
+ const CvArr* arr = i < count ? arrs[i] : mask;
+ CvMatND* hdr;
+
+ if( !arr )
+ {
+ if( i < count )
+ CV_Error( CV_StsNullPtr, "Some of required array pointers is NULL" );
+ break;
+ }
+
+ if( CV_IS_MATND( arr ))
+ hdr = (CvMatND*)arr;
+ else
+ {
+ int coi = 0;
+ hdr = cvGetMatND( arr, stubs + i, &coi );
+ if( coi != 0 )
+ CV_Error( CV_BadCOI, "COI set is not allowed here" );
+ }
+
+ iterator->hdr[i] = hdr;
+
+ if( i > 0 )
+ {
+ if( hdr->dims != hdr0->dims )
+ CV_Error( CV_StsUnmatchedSizes,
+ "Number of dimensions is the same for all arrays" );
+
+ if( i < count )
+ {
+ switch( flags & (CV_NO_DEPTH_CHECK|CV_NO_CN_CHECK))
+ {
+ case 0:
+ if( !CV_ARE_TYPES_EQ( hdr, hdr0 ))
+ CV_Error( CV_StsUnmatchedFormats,
+ "Data type is not the same for all arrays" );
+ break;
+ case CV_NO_DEPTH_CHECK:
+ if( !CV_ARE_CNS_EQ( hdr, hdr0 ))
+ CV_Error( CV_StsUnmatchedFormats,
+ "Number of channels is not the same for all arrays" );
+ break;
+ case CV_NO_CN_CHECK:
+ if( !CV_ARE_CNS_EQ( hdr, hdr0 ))
+ CV_Error( CV_StsUnmatchedFormats,
+ "Depth is not the same for all arrays" );
+ break;
+ }
+ }
+ else
+ {
+ if( !CV_IS_MASK_ARR( hdr ))
+ CV_Error( CV_StsBadMask, "Mask should have 8uC1 or 8sC1 data type" );
+ }
+
+ if( !(flags & CV_NO_SIZE_CHECK) )
+ {
+ for( j = 0; j < hdr->dims; j++ )
+ if( hdr->dim[j].size != hdr0->dim[j].size )
+ CV_Error( CV_StsUnmatchedSizes,
+ "Dimension sizes are the same for all arrays" );
+ }
+ }
+ else
+ hdr0 = hdr;
+
+ step = CV_ELEM_SIZE(hdr->type);
+ for( j = hdr->dims - 1; j > dim0; j-- )
+ {
+ if( step != hdr->dim[j].step )
+ break;
+ step *= hdr->dim[j].size;
+ }
+
+ if( j == dim0 && step > INT_MAX )
+ j++;
+
+ if( j > dim0 )
+ dim0 = j;
+
+ iterator->hdr[i] = (CvMatND*)hdr;
+ iterator->ptr[i] = (uchar*)hdr->data.ptr;
+ }
+
+ size = 1;
+ for( j = hdr0->dims - 1; j > dim0; j-- )
+ size *= hdr0->dim[j].size;
+
+ dims = dim0 + 1;
+ iterator->dims = dims;
+ iterator->count = count;
+ iterator->size = cvSize(size,1);
+
+ for( i = 0; i < dims; i++ )
+ iterator->stack[i] = hdr0->dim[i].size;
+
+ return dims;
+}
+
+
+// returns zero value if iteration is finished, non-zero otherwise
+CV_IMPL int cvNextNArraySlice( CvNArrayIterator* iterator )
+{
+ assert( iterator != 0 );
+ int i, dims, size = 0;
+
+ for( dims = iterator->dims; dims > 0; dims-- )
+ {
+ for( i = 0; i < iterator->count; i++ )
+ iterator->ptr[i] += iterator->hdr[i]->dim[dims-1].step;
+
+ if( --iterator->stack[dims-1] > 0 )
+ break;
+
+ size = iterator->hdr[0]->dim[dims-1].size;
+
+ for( i = 0; i < iterator->count; i++ )
+ iterator->ptr[i] -= (size_t)size*iterator->hdr[i]->dim[dims-1].step;
+
+ iterator->stack[dims-1] = size;
+ }
+
+ return dims > 0;
+}
+
+
+/****************************************************************************************\
+* CvSparseMat creation and basic operations *
+\****************************************************************************************/
+
+
+// Creates CvMatND and underlying data
+CV_IMPL CvSparseMat*
+cvCreateSparseMat( int dims, const int* sizes, int type )
+{
+ type = CV_MAT_TYPE( type );
+ int pix_size1 = CV_ELEM_SIZE1(type);
+ int pix_size = pix_size1*CV_MAT_CN(type);
+ int i, size;
+ CvMemStorage* storage;
+
+ if( pix_size == 0 )
+ CV_Error( CV_StsUnsupportedFormat, "invalid array data type" );
+
+ if( dims <= 0 || dims > CV_MAX_DIM_HEAP )
+ CV_Error( CV_StsOutOfRange, "bad number of dimensions" );
+
+ if( !sizes )
+ CV_Error( CV_StsNullPtr, "NULL <sizes> pointer" );
+
+ for( i = 0; i < dims; i++ )
+ {
+ if( sizes[i] <= 0 )
+ CV_Error( CV_StsBadSize, "one of dimesion sizes is non-positive" );
+ }
+
+ CvSparseMat* arr = (CvSparseMat*)cvAlloc(sizeof(*arr)+MAX(0,dims-CV_MAX_DIM)*sizeof(arr->size[0]));
+
+ arr->type = CV_SPARSE_MAT_MAGIC_VAL | type;
+ arr->dims = dims;
+ arr->refcount = 0;
+ arr->hdr_refcount = 1;
+ memcpy( arr->size, sizes, dims*sizeof(sizes[0]));
+
+ arr->valoffset = (int)cvAlign(sizeof(CvSparseNode), pix_size1);
+ arr->idxoffset = (int)cvAlign(arr->valoffset + pix_size, sizeof(int));
+ size = (int)cvAlign(arr->idxoffset + dims*sizeof(int), sizeof(CvSetElem));
+
+ storage = cvCreateMemStorage( CV_SPARSE_MAT_BLOCK );
+ arr->heap = cvCreateSet( 0, sizeof(CvSet), size, storage );
+
+ arr->hashsize = CV_SPARSE_HASH_SIZE0;
+ size = arr->hashsize*sizeof(arr->hashtable[0]);
+
+ arr->hashtable = (void**)cvAlloc( size );
+ memset( arr->hashtable, 0, size );
+
+ return arr;
+}
+
+
+// Creates CvMatND and underlying data
+CV_IMPL void
+cvReleaseSparseMat( CvSparseMat** array )
+{
+ if( !array )
+ CV_Error( CV_HeaderIsNull, "" );
+
+ if( *array )
+ {
+ CvSparseMat* arr = *array;
+
+ if( !CV_IS_SPARSE_MAT_HDR(arr) )
+ CV_Error( CV_StsBadFlag, "" );
+
+ *array = 0;
+
+ CvMemStorage* storage = arr->heap->storage;
+ cvReleaseMemStorage( &storage );
+ cvFree( &arr->hashtable );
+ cvFree( &arr );
+ }
+}
+
+
+// Creates CvMatND and underlying data
+CV_IMPL CvSparseMat*
+cvCloneSparseMat( const CvSparseMat* src )
+{
+ if( !CV_IS_SPARSE_MAT_HDR(src) )
+ CV_Error( CV_StsBadArg, "Invalid sparse array header" );
+
+ CvSparseMat* dst = cvCreateSparseMat( src->dims, src->size, src->type );
+ cvCopy( src, dst );
+ return dst;
+}
+
+
+CvSparseNode*
+cvInitSparseMatIterator( const CvSparseMat* mat, CvSparseMatIterator* iterator )
+{
+ CvSparseNode* node = 0;
+ int idx;
+
+ if( !CV_IS_SPARSE_MAT( mat ))
+ CV_Error( CV_StsBadArg, "Invalid sparse matrix header" );
+
+ if( !iterator )
+ CV_Error( CV_StsNullPtr, "NULL iterator pointer" );
+
+ iterator->mat = (CvSparseMat*)mat;
+ iterator->node = 0;
+
+ for( idx = 0; idx < mat->hashsize; idx++ )
+ if( mat->hashtable[idx] )
+ {
+ node = iterator->node = (CvSparseNode*)mat->hashtable[idx];
+ break;
+ }
+
+ iterator->curidx = idx;
+ return node;
+}
+
+#define ICV_SPARSE_MAT_HASH_MULTIPLIER cv::SparseMat::HASH_SCALE
+
+static uchar*
+icvGetNodePtr( CvSparseMat* mat, const int* idx, int* _type,
+ int create_node, unsigned* precalc_hashval )
+{
+ uchar* ptr = 0;
+ int i, tabidx;
+ unsigned hashval = 0;
+ CvSparseNode *node;
+ assert( CV_IS_SPARSE_MAT( mat ));
+
+ if( !precalc_hashval )
+ {
+ for( i = 0; i < mat->dims; i++ )
+ {
+ int t = idx[i];
+ if( (unsigned)t >= (unsigned)mat->size[i] )
+ CV_Error( CV_StsOutOfRange, "One of indices is out of range" );
+ hashval = hashval*ICV_SPARSE_MAT_HASH_MULTIPLIER + t;
+ }
+ }
+ else
+ {
+ hashval = *precalc_hashval;
+ }
+
+ tabidx = hashval & (mat->hashsize - 1);
+ hashval &= INT_MAX;
+
+ if( create_node >= -1 )
+ {
+ for( node = (CvSparseNode*)mat->hashtable[tabidx];
+ node != 0; node = node->next )
+ {
+ if( node->hashval == hashval )
+ {
+ int* nodeidx = CV_NODE_IDX(mat,node);
+ for( i = 0; i < mat->dims; i++ )
+ if( idx[i] != nodeidx[i] )
+ break;
+ if( i == mat->dims )
+ {
+ ptr = (uchar*)CV_NODE_VAL(mat,node);
+ break;
+ }
+ }
+ }
+ }
+
+ if( !ptr && create_node )
+ {
+ if( mat->heap->active_count >= mat->hashsize*CV_SPARSE_HASH_RATIO )
+ {
+ void** newtable;
+ int newsize = MAX( mat->hashsize*2, CV_SPARSE_HASH_SIZE0);
+ int newrawsize = newsize*sizeof(newtable[0]);
+
+ CvSparseMatIterator iterator;
+ assert( (newsize & (newsize - 1)) == 0 );
+
+ // resize hash table
+ newtable = (void**)cvAlloc( newrawsize );
+ memset( newtable, 0, newrawsize );
+
+ node = cvInitSparseMatIterator( mat, &iterator );
+ while( node )
+ {
+ CvSparseNode* next = cvGetNextSparseNode( &iterator );
+ int newidx = node->hashval & (newsize - 1);
+ node->next = (CvSparseNode*)newtable[newidx];
+ newtable[newidx] = node;
+ node = next;
+ }
+
+ cvFree( &mat->hashtable );
+ mat->hashtable = newtable;
+ mat->hashsize = newsize;
+ tabidx = hashval & (newsize - 1);
+ }
+
+ node = (CvSparseNode*)cvSetNew( mat->heap );
+ node->hashval = hashval;
+ node->next = (CvSparseNode*)mat->hashtable[tabidx];
+ mat->hashtable[tabidx] = node;
+ CV_MEMCPY_INT( CV_NODE_IDX(mat,node), idx, mat->dims );
+ ptr = (uchar*)CV_NODE_VAL(mat,node);
+ if( create_node > 0 )
+ CV_ZERO_CHAR( ptr, CV_ELEM_SIZE(mat->type));
+ }
+
+ if( _type )
+ *_type = CV_MAT_TYPE(mat->type);
+
+ return ptr;
+}
+
+
+static void
+icvDeleteNode( CvSparseMat* mat, const int* idx, unsigned* precalc_hashval )
+{
+ int i, tabidx;
+ unsigned hashval = 0;
+ CvSparseNode *node, *prev = 0;
+ assert( CV_IS_SPARSE_MAT( mat ));
+
+ if( !precalc_hashval )
+ {
+ for( i = 0; i < mat->dims; i++ )
+ {
+ int t = idx[i];
+ if( (unsigned)t >= (unsigned)mat->size[i] )
+ CV_Error( CV_StsOutOfRange, "One of indices is out of range" );
+ hashval = hashval*ICV_SPARSE_MAT_HASH_MULTIPLIER + t;
+ }
+ }
+ else
+ {
+ hashval = *precalc_hashval;
+ }
+
+ tabidx = hashval & (mat->hashsize - 1);
+ hashval &= INT_MAX;
+
+ for( node = (CvSparseNode*)mat->hashtable[tabidx];
+ node != 0; prev = node, node = node->next )
+ {
+ if( node->hashval == hashval )
+ {
+ int* nodeidx = CV_NODE_IDX(mat,node);
+ for( i = 0; i < mat->dims; i++ )
+ if( idx[i] != nodeidx[i] )
+ break;
+ if( i == mat->dims )
+ break;
+ }
+ }
+
+ if( node )
+ {
+ if( prev )
+ prev->next = node->next;
+ else
+ mat->hashtable[tabidx] = node->next;
+ cvSetRemoveByPtr( mat->heap, node );
+ }
+}
+
+
+/****************************************************************************************\
+* Common for multiple array types operations *
+\****************************************************************************************/
+
+// Allocates underlying array data
+CV_IMPL void
+cvCreateData( CvArr* arr )
+{
+ if( CV_IS_MAT_HDR( arr ))
+ {
+ size_t step, total_size;
+ CvMat* mat = (CvMat*)arr;
+ step = mat->step;
+
+ if( mat->data.ptr != 0 )
+ CV_Error( CV_StsError, "Data is already allocated" );
+
+ if( step == 0 )
+ step = CV_ELEM_SIZE(mat->type)*mat->cols;
+
+ int64 _total_size = (int64)step*mat->rows + sizeof(int) + CV_MALLOC_ALIGN;
+ total_size = (size_t)_total_size;
+ if(_total_size != (int64)total_size)
+ CV_Error(CV_StsNoMem, "Too big buffer is allocated" );
+ mat->refcount = (int*)cvAlloc( (size_t)total_size );
+ mat->data.ptr = (uchar*)cvAlignPtr( mat->refcount + 1, CV_MALLOC_ALIGN );
+ *mat->refcount = 1;
+ }
+ else if( CV_IS_IMAGE_HDR(arr))
+ {
+ IplImage* img = (IplImage*)arr;
+
+ if( img->imageData != 0 )
+ CV_Error( CV_StsError, "Data is already allocated" );
+
+ if( !CvIPL.allocateData )
+ {
+ img->imageData = img->imageDataOrigin =
+ (char*)cvAlloc( (size_t)img->imageSize );
+ }
+ else
+ {
+ int depth = img->depth;
+ int width = img->width;
+
+ if( img->depth == IPL_DEPTH_32F || img->depth == IPL_DEPTH_64F )
+ {
+ img->width *= img->depth == IPL_DEPTH_32F ? sizeof(float) : sizeof(double);
+ img->depth = IPL_DEPTH_8U;
+ }
+
+ CvIPL.allocateData( img, 0, 0 );
+
+ img->width = width;
+ img->depth = depth;
+ }
+ }
+ else if( CV_IS_MATND_HDR( arr ))
+ {
+ CvMatND* mat = (CvMatND*)arr;
+ int i;
+ size_t total_size = CV_ELEM_SIZE(mat->type);
+
+ if( mat->data.ptr != 0 )
+ CV_Error( CV_StsError, "Data is already allocated" );
+
+ if( CV_IS_MAT_CONT( mat->type ))
+ {
+ total_size = (size_t)mat->dim[0].size*(mat->dim[0].step != 0 ?
+ mat->dim[0].step : total_size);
+ }
+ else
+ {
+ for( i = mat->dims - 1; i >= 0; i-- )
+ {
+ size_t size = (size_t)mat->dim[i].step*mat->dim[i].size;
+
+ if( total_size < size )
+ total_size = size;
+ }
+ }
+
+ mat->refcount = (int*)cvAlloc( total_size +
+ sizeof(int) + CV_MALLOC_ALIGN );
+ mat->data.ptr = (uchar*)cvAlignPtr( mat->refcount + 1, CV_MALLOC_ALIGN );
+ *mat->refcount = 1;
+ }
+ else
+ CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
+}
+
+
+// Assigns external data to array
+CV_IMPL void
+cvSetData( CvArr* arr, void* data, int step )
+{
+ int pix_size, min_step;
+
+ if( CV_IS_MAT_HDR(arr) || CV_IS_MATND_HDR(arr) )
+ cvReleaseData( arr );
+
+ if( CV_IS_MAT_HDR( arr ))
+ {
+ CvMat* mat = (CvMat*)arr;
+
+ int type = CV_MAT_TYPE(mat->type);
+ pix_size = CV_ELEM_SIZE(type);
+ min_step = mat->cols*pix_size;
+
+ if( step != CV_AUTOSTEP && step != 0 )
+ {
+ if( step < min_step && data != 0 )
+ CV_Error( CV_BadStep, "" );
+ mat->step = step;
+ }
+ else
+ mat->step = min_step;
+
+ mat->data.ptr = (uchar*)data;
+ mat->type = CV_MAT_MAGIC_VAL | type |
+ (mat->rows == 1 || mat->step == min_step ? CV_MAT_CONT_FLAG : 0);
+ icvCheckHuge( mat );
+ }
+ else if( CV_IS_IMAGE_HDR( arr ))
+ {
+ IplImage* img = (IplImage*)arr;
+
+ pix_size = ((img->depth & 255) >> 3)*img->nChannels;
+ min_step = img->width*pix_size;
+
+ if( step != CV_AUTOSTEP && img->height > 1 )
+ {
+ if( step < min_step && data != 0 )
+ CV_Error( CV_BadStep, "" );
+ img->widthStep = step;
+ }
+ else
+ {
+ img->widthStep = min_step;
+ }
+
+ img->imageSize = img->widthStep * img->height;
+ img->imageData = img->imageDataOrigin = (char*)data;
+
+ if( (((int)(size_t)data | step) & 7) == 0 &&
+ cvAlign(img->width * pix_size, 8) == step )
+ img->align = 8;
+ else
+ img->align = 4;
+ }
+ else if( CV_IS_MATND_HDR( arr ))
+ {
+ CvMatND* mat = (CvMatND*)arr;
+ int i;
+ int64 cur_step;
+
+ if( step != CV_AUTOSTEP )
+ CV_Error( CV_BadStep,
+ "For multidimensional array only CV_AUTOSTEP is allowed here" );
+
+ mat->data.ptr = (uchar*)data;
+ cur_step = CV_ELEM_SIZE(mat->type);
+
+ for( i = mat->dims - 1; i >= 0; i-- )
+ {
+ if( cur_step > INT_MAX )
+ CV_Error( CV_StsOutOfRange, "The array is too big" );
+ mat->dim[i].step = (int)cur_step;
+ cur_step *= mat->dim[i].size;
+ }
+ }
+ else
+ CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
+}
+
+
+// Deallocates array's data
+CV_IMPL void
+cvReleaseData( CvArr* arr )
+{
+ if( CV_IS_MAT_HDR( arr ) || CV_IS_MATND_HDR( arr ))
+ {
+ CvMat* mat = (CvMat*)arr;
+ cvDecRefData( mat );
+ }
+ else if( CV_IS_IMAGE_HDR( arr ))
+ {
+ IplImage* img = (IplImage*)arr;
+
+ if( !CvIPL.deallocate )
+ {
+ char* ptr = img->imageDataOrigin;
+ img->imageData = img->imageDataOrigin = 0;
+ cvFree( &ptr );
+ }
+ else
+ {
+ CvIPL.deallocate( img, IPL_IMAGE_DATA );
+ }
+ }
+ else
+ CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
+}
+
+
+// Retrieves essential information about image ROI or CvMat data
+CV_IMPL void
+cvGetRawData( const CvArr* arr, uchar** data, int* step, CvSize* roi_size )
+{
+ if( CV_IS_MAT( arr ))
+ {
+ CvMat *mat = (CvMat*)arr;
+
+ if( step )
+ *step = mat->step;
+
+ if( data )
+ *data = mat->data.ptr;
+
+ if( roi_size )
+ *roi_size = cvGetMatSize( mat );
+ }
+ else if( CV_IS_IMAGE( arr ))
+ {
+ IplImage* img = (IplImage*)arr;
+
+ if( step )
+ *step = img->widthStep;
+
+ if( data )
+ *data = cvPtr2D( img, 0, 0 );
+
+ if( roi_size )
+ {
+ if( img->roi )
+ {
+ *roi_size = cvSize( img->roi->width, img->roi->height );
+ }
+ else
+ {
+ *roi_size = cvSize( img->width, img->height );
+ }
+ }
+ }
+ else if( CV_IS_MATND( arr ))
+ {
+ CvMatND* mat = (CvMatND*)arr;
+
+ if( !CV_IS_MAT_CONT( mat->type ))
+ CV_Error( CV_StsBadArg, "Only continuous nD arrays are supported here" );
+
+ if( data )
+ *data = mat->data.ptr;
+
+ if( roi_size || step )
+ {
+ int i, size1 = mat->dim[0].size, size2 = 1;
+
+ if( mat->dims > 2 )
+ for( i = 1; i < mat->dims; i++ )
+ size1 *= mat->dim[i].size;
+ else
+ size2 = mat->dim[1].size;
+
+ if( roi_size )
+ {
+ roi_size->width = size2;
+ roi_size->height = size1;
+ }
+
+ if( step )
+ *step = mat->dim[0].step;
+ }
+ }
+ else
+ CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
+}
+
+
+CV_IMPL int
+cvGetElemType( const CvArr* arr )
+{
+ int type = -1;
+ if( CV_IS_MAT_HDR(arr) || CV_IS_MATND_HDR(arr) || CV_IS_SPARSE_MAT_HDR(arr))
+ type = CV_MAT_TYPE( ((CvMat*)arr)->type );
+ else if( CV_IS_IMAGE(arr))
+ {
+ IplImage* img = (IplImage*)arr;
+ type = CV_MAKETYPE( IPL2CV_DEPTH(img->depth), img->nChannels );
+ }
+ else
+ CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
+
+ return type;
+}
+
+
+// Returns a number of array dimensions
+CV_IMPL int
+cvGetDims( const CvArr* arr, int* sizes )
+{
+ int dims = -1;
+ if( CV_IS_MAT_HDR( arr ))
+ {
+ CvMat* mat = (CvMat*)arr;
+
+ dims = 2;
+ if( sizes )
+ {
+ sizes[0] = mat->rows;
+ sizes[1] = mat->cols;
+ }
+ }
+ else if( CV_IS_IMAGE( arr ))
+ {
+ IplImage* img = (IplImage*)arr;
+ dims = 2;
+
+ if( sizes )
+ {
+ sizes[0] = img->height;
+ sizes[1] = img->width;
+ }
+ }
+ else if( CV_IS_MATND_HDR( arr ))
+ {
+ CvMatND* mat = (CvMatND*)arr;
+ dims = mat->dims;
+
+ if( sizes )
+ {
+ int i;
+ for( i = 0; i < dims; i++ )
+ sizes[i] = mat->dim[i].size;
+ }
+ }
+ else if( CV_IS_SPARSE_MAT_HDR( arr ))
+ {
+ CvSparseMat* mat = (CvSparseMat*)arr;
+ dims = mat->dims;
+
+ if( sizes )
+ memcpy( sizes, mat->size, dims*sizeof(sizes[0]));
+ }
+ else
+ CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
+
+ return dims;
+}
+
+
+// Returns the size of particular array dimension
+CV_IMPL int
+cvGetDimSize( const CvArr* arr, int index )
+{
+ int size = -1;
+
+ if( CV_IS_MAT( arr ))
+ {
+ CvMat *mat = (CvMat*)arr;
+
+ switch( index )
+ {
+ case 0:
+ size = mat->rows;
+ break;
+ case 1:
+ size = mat->cols;
+ break;
+ default:
+ CV_Error( CV_StsOutOfRange, "bad dimension index" );
+ }
+ }
+ else if( CV_IS_IMAGE( arr ))
+ {
+ IplImage* img = (IplImage*)arr;
+
+ switch( index )
+ {
+ case 0:
+ size = !img->roi ? img->height : img->roi->height;
+ break;
+ case 1:
+ size = !img->roi ? img->width : img->roi->width;
+ break;
+ default:
+ CV_Error( CV_StsOutOfRange, "bad dimension index" );
+ }
+ }
+ else if( CV_IS_MATND_HDR( arr ))
+ {
+ CvMatND* mat = (CvMatND*)arr;
+
+ if( (unsigned)index >= (unsigned)mat->dims )
+ CV_Error( CV_StsOutOfRange, "bad dimension index" );
+
+ size = mat->dim[index].size;
+ }
+ else if( CV_IS_SPARSE_MAT_HDR( arr ))
+ {
+ CvSparseMat* mat = (CvSparseMat*)arr;
+
+ if( (unsigned)index >= (unsigned)mat->dims )
+ CV_Error( CV_StsOutOfRange, "bad dimension index" );
+
+ size = mat->size[index];
+ }
+ else
+ CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
+
+ return size;
+}
+
+
+// Returns the size of CvMat or IplImage
+CV_IMPL CvSize
+cvGetSize( const CvArr* arr )
+{
+ CvSize size = { 0, 0 };
+
+ if( CV_IS_MAT_HDR( arr ))
+ {
+ CvMat *mat = (CvMat*)arr;
+
+ size.width = mat->cols;
+ size.height = mat->rows;
+ }
+ else if( CV_IS_IMAGE_HDR( arr ))
+ {
+ IplImage* img = (IplImage*)arr;
+
+ if( img->roi )
+ {
+ size.width = img->roi->width;
+ size.height = img->roi->height;
+ }
+ else
+ {
+ size.width = img->width;
+ size.height = img->height;
+ }
+ }
+ else
+ CV_Error( CV_StsBadArg, "Array should be CvMat or IplImage" );
+
+ return size;
+}
+
+
+// Selects sub-array (no data is copied)
+CV_IMPL CvMat*
+cvGetSubRect( const CvArr* arr, CvMat* submat, CvRect rect )
+{
+ CvMat* res = 0;
+ CvMat stub, *mat = (CvMat*)arr;
+
+ if( !CV_IS_MAT( mat ))
+ mat = cvGetMat( mat, &stub );
+
+ if( !submat )
+ CV_Error( CV_StsNullPtr, "" );
+
+ if( (rect.x|rect.y|rect.width|rect.height) < 0 )
+ CV_Error( CV_StsBadSize, "" );
+
+ if( rect.x + rect.width > mat->cols ||
+ rect.y + rect.height > mat->rows )
+ CV_Error( CV_StsBadSize, "" );
+
+ {
+ /*
+ int* refcount = mat->refcount;
+
+ if( refcount )
+ ++*refcount;
+
+ cvDecRefData( submat );
+ */
+ submat->data.ptr = mat->data.ptr + (size_t)rect.y*mat->step +
+ rect.x*CV_ELEM_SIZE(mat->type);
+ submat->step = mat->step;
+ submat->type = (mat->type & (rect.width < mat->cols ? ~CV_MAT_CONT_FLAG : -1)) |
+ (rect.height <= 1 ? CV_MAT_CONT_FLAG : 0);
+ submat->rows = rect.height;
+ submat->cols = rect.width;
+ submat->refcount = 0;
+ res = submat;
+ }
+
+ return res;
+}
+
+
+// Selects array's row span.
+CV_IMPL CvMat*
+cvGetRows( const CvArr* arr, CvMat* submat,
+ int start_row, int end_row, int delta_row )
+{
+ CvMat* res = 0;
+ CvMat stub, *mat = (CvMat*)arr;
+
+ if( !CV_IS_MAT( mat ))
+ mat = cvGetMat( mat, &stub );
+
+ if( !submat )
+ CV_Error( CV_StsNullPtr, "" );
+
+ if( (unsigned)start_row >= (unsigned)mat->rows ||
+ (unsigned)end_row > (unsigned)mat->rows || delta_row <= 0 )
+ CV_Error( CV_StsOutOfRange, "" );
+
+ {
+ /*
+ int* refcount = mat->refcount;
+
+ if( refcount )
+ ++*refcount;
+
+ cvDecRefData( submat );
+ */
+ if( delta_row == 1 )
+ {
+ submat->rows = end_row - start_row;
+ submat->step = mat->step;
+ }
+ else
+ {
+ submat->rows = (end_row - start_row + delta_row - 1)/delta_row;
+ submat->step = mat->step * delta_row;
+ }
+
+ submat->cols = mat->cols;
+ submat->step &= submat->rows > 1 ? -1 : 0;
+ submat->data.ptr = mat->data.ptr + (size_t)start_row*mat->step;
+ submat->type = (mat->type | (submat->rows == 1 ? CV_MAT_CONT_FLAG : 0)) &
+ (delta_row != 1 && submat->rows > 1 ? ~CV_MAT_CONT_FLAG : -1);
+ submat->refcount = 0;
+ submat->hdr_refcount = 0;
+ res = submat;
+ }
+
+ return res;
+}
+
+
+// Selects array's column span.
+CV_IMPL CvMat*
+cvGetCols( const CvArr* arr, CvMat* submat, int start_col, int end_col )
+{
+ CvMat* res = 0;
+ CvMat stub, *mat = (CvMat*)arr;
+ int cols;
+
+ if( !CV_IS_MAT( mat ))
+ mat = cvGetMat( mat, &stub );
+
+ if( !submat )
+ CV_Error( CV_StsNullPtr, "" );
+
+ cols = mat->cols;
+ if( (unsigned)start_col >= (unsigned)cols ||
+ (unsigned)end_col > (unsigned)cols )
+ CV_Error( CV_StsOutOfRange, "" );
+
+ {
+ /*
+ int* refcount = mat->refcount;
+
+ if( refcount )
+ ++*refcount;
+
+ cvDecRefData( submat );
+ */
+ submat->rows = mat->rows;
+ submat->cols = end_col - start_col;
+ submat->step = mat->step;
+ submat->data.ptr = mat->data.ptr + (size_t)start_col*CV_ELEM_SIZE(mat->type);
+ submat->type = mat->type & (submat->rows > 1 && submat->cols < cols ? ~CV_MAT_CONT_FLAG : -1);
+ submat->refcount = 0;
+ submat->hdr_refcount = 0;
+ res = submat;
+ }
+
+ return res;
+}
+
+
+// Selects array diagonal
+CV_IMPL CvMat*
+cvGetDiag( const CvArr* arr, CvMat* submat, int diag )
+{
+ CvMat* res = 0;
+ CvMat stub, *mat = (CvMat*)arr;
+ int len, pix_size;
+
+ if( !CV_IS_MAT( mat ))
+ mat = cvGetMat( mat, &stub );
+
+ if( !submat )
+ CV_Error( CV_StsNullPtr, "" );
+
+ pix_size = CV_ELEM_SIZE(mat->type);
+
+ /*{
+ int* refcount = mat->refcount;
+
+ if( refcount )
+ ++*refcount;
+
+ cvDecRefData( submat );
+ }*/
+
+ if( diag >= 0 )
+ {
+ len = mat->cols - diag;
+
+ if( len <= 0 )
+ CV_Error( CV_StsOutOfRange, "" );
+
+ len = CV_IMIN( len, mat->rows );
+ submat->data.ptr = mat->data.ptr + diag*pix_size;
+ }
+ else
+ {
+ len = mat->rows + diag;
+
+ if( len <= 0 )
+ CV_Error( CV_StsOutOfRange, "" );
+
+ len = CV_IMIN( len, mat->cols );
+ submat->data.ptr = mat->data.ptr - diag*mat->step;
+ }
+
+ submat->rows = len;
+ submat->cols = 1;
+ submat->step = mat->step + (submat->rows > 1 ? pix_size : 0);
+ submat->type = mat->type;
+ if( submat->rows > 1 )
+ submat->type &= ~CV_MAT_CONT_FLAG;
+ else
+ submat->type |= CV_MAT_CONT_FLAG;
+ submat->refcount = 0;
+ submat->hdr_refcount = 0;
+ res = submat;
+
+ return res;
+}
+
+
+/****************************************************************************************\
+* Operations on CvScalar and accessing array elements *
+\****************************************************************************************/
+
+// Converts CvScalar to specified type
+CV_IMPL void
+cvScalarToRawData( const CvScalar* scalar, void* data, int type, int extend_to_12 )
+{
+ type = CV_MAT_TYPE(type);
+ int cn = CV_MAT_CN( type );
+ int depth = type & CV_MAT_DEPTH_MASK;
+
+ assert( scalar && data );
+ if( (unsigned)(cn - 1) >= 4 )
+ CV_Error( CV_StsOutOfRange, "The number of channels must be 1, 2, 3 or 4" );
+
+ switch( depth )
+ {
+ case CV_8UC1:
+ while( cn-- )
+ {
+ int t = cvRound( scalar->val[cn] );
+ ((uchar*)data)[cn] = CV_CAST_8U(t);
+ }
+ break;
+ case CV_8SC1:
+ while( cn-- )
+ {
+ int t = cvRound( scalar->val[cn] );
+ ((char*)data)[cn] = CV_CAST_8S(t);
+ }
+ break;
+ case CV_16UC1:
+ while( cn-- )
+ {
+ int t = cvRound( scalar->val[cn] );
+ ((ushort*)data)[cn] = CV_CAST_16U(t);
+ }
+ break;
+ case CV_16SC1:
+ while( cn-- )
+ {
+ int t = cvRound( scalar->val[cn] );
+ ((short*)data)[cn] = CV_CAST_16S(t);
+ }
+ break;
+ case CV_32SC1:
+ while( cn-- )
+ ((int*)data)[cn] = cvRound( scalar->val[cn] );
+ break;
+ case CV_32FC1:
+ while( cn-- )
+ ((float*)data)[cn] = (float)(scalar->val[cn]);
+ break;
+ case CV_64FC1:
+ while( cn-- )
+ ((double*)data)[cn] = (double)(scalar->val[cn]);
+ break;
+ default:
+ assert(0);
+ CV_Error( CV_BadDepth, "" );
+ }
+
+ if( extend_to_12 )
+ {
+ int pix_size = CV_ELEM_SIZE(type);
+ int offset = CV_ELEM_SIZE1(depth)*12;
+
+ do
+ {
+ offset -= pix_size;
+ CV_MEMCPY_AUTO( (char*)data + offset, data, pix_size );
+ }
+ while( offset > pix_size );
+ }
+}
+
+
+// Converts data of specified type to CvScalar
+CV_IMPL void
+cvRawDataToScalar( const void* data, int flags, CvScalar* scalar )
+{
+ int cn = CV_MAT_CN( flags );
+
+ assert( scalar && data );
+
+ if( (unsigned)(cn - 1) >= 4 )
+ CV_Error( CV_StsOutOfRange, "The number of channels must be 1, 2, 3 or 4" );
+
+ memset( scalar->val, 0, sizeof(scalar->val));
+
+ switch( CV_MAT_DEPTH( flags ))
+ {
+ case CV_8U:
+ while( cn-- )
+ scalar->val[cn] = CV_8TO32F(((uchar*)data)[cn]);
+ break;
+ case CV_8S:
+ while( cn-- )
+ scalar->val[cn] = CV_8TO32F(((char*)data)[cn]);
+ break;
+ case CV_16U:
+ while( cn-- )
+ scalar->val[cn] = ((ushort*)data)[cn];
+ break;
+ case CV_16S:
+ while( cn-- )
+ scalar->val[cn] = ((short*)data)[cn];
+ break;
+ case CV_32S:
+ while( cn-- )
+ scalar->val[cn] = ((int*)data)[cn];
+ break;
+ case CV_32F:
+ while( cn-- )
+ scalar->val[cn] = ((float*)data)[cn];
+ break;
+ case CV_64F:
+ while( cn-- )
+ scalar->val[cn] = ((double*)data)[cn];
+ break;
+ default:
+ assert(0);
+ CV_Error( CV_BadDepth, "" );
+ }
+}
+
+
+static double icvGetReal( const void* data, int type )
+{
+ switch( type )
+ {
+ case CV_8U:
+ return *(uchar*)data;
+ case CV_8S:
+ return *(char*)data;
+ case CV_16U:
+ return *(ushort*)data;
+ case CV_16S:
+ return *(short*)data;
+ case CV_32S:
+ return *(int*)data;
+ case CV_32F:
+ return *(float*)data;
+ case CV_64F:
+ return *(double*)data;
+ }
+
+ return 0;
+}
+
+
+static void icvSetReal( double value, const void* data, int type )
+{
+ if( type < CV_32F )
+ {
+ int ivalue = cvRound(value);
+ switch( type )
+ {
+ case CV_8U:
+ *(uchar*)data = CV_CAST_8U(ivalue);
+ break;
+ case CV_8S:
+ *(char*)data = CV_CAST_8S(ivalue);
+ break;
+ case CV_16U:
+ *(ushort*)data = CV_CAST_16U(ivalue);
+ break;
+ case CV_16S:
+ *(short*)data = CV_CAST_16S(ivalue);
+ break;
+ case CV_32S:
+ *(int*)data = CV_CAST_32S(ivalue);
+ break;
+ }
+ }
+ else
+ {
+ switch( type )
+ {
+ case CV_32F:
+ *(float*)data = (float)value;
+ break;
+ case CV_64F:
+ *(double*)data = value;
+ break;
+ }
+ }
+}
+
+
+// Returns pointer to specified element of array (linear index is used)
+CV_IMPL uchar*
+cvPtr1D( const CvArr* arr, int idx, int* _type )
+{
+ uchar* ptr = 0;
+ if( CV_IS_MAT( arr ))
+ {
+ CvMat* mat = (CvMat*)arr;
+
+ int type = CV_MAT_TYPE(mat->type);
+ int pix_size = CV_ELEM_SIZE(type);
+
+ if( _type )
+ *_type = type;
+
+ // the first part is mul-free sufficient check
+ // that the index is within the matrix
+ if( (unsigned)idx >= (unsigned)(mat->rows + mat->cols - 1) &&
+ (unsigned)idx >= (unsigned)(mat->rows*mat->cols))
+ CV_Error( CV_StsOutOfRange, "index is out of range" );
+
+ if( CV_IS_MAT_CONT(mat->type))
+ {
+ ptr = mat->data.ptr + (size_t)idx*pix_size;
+ }
+ else
+ {
+ int row, col;
+ if( mat->cols == 1 )
+ row = idx, col = 0;
+ else
+ row = idx/mat->cols, col = idx - row*mat->cols;
+ ptr = mat->data.ptr + (size_t)row*mat->step + col*pix_size;
+ }
+ }
+ else if( CV_IS_IMAGE_HDR( arr ))
+ {
+ IplImage* img = (IplImage*)arr;
+ int width = !img->roi ? img->width : img->roi->width;
+ int y = idx/width, x = idx - y*width;
+
+ ptr = cvPtr2D( arr, y, x, _type );
+ }
+ else if( CV_IS_MATND( arr ))
+ {
+ CvMatND* mat = (CvMatND*)arr;
+ int j, type = CV_MAT_TYPE(mat->type);
+ size_t size = mat->dim[0].size;
+
+ if( _type )
+ *_type = type;
+
+ for( j = 1; j < mat->dims; j++ )
+ size *= mat->dim[j].size;
+
+ if((unsigned)idx >= (unsigned)size )
+ CV_Error( CV_StsOutOfRange, "index is out of range" );
+
+ if( CV_IS_MAT_CONT(mat->type))
+ {
+ int pix_size = CV_ELEM_SIZE(type);
+ ptr = mat->data.ptr + (size_t)idx*pix_size;
+ }
+ else
+ {
+ ptr = mat->data.ptr;
+ for( j = mat->dims - 1; j >= 0; j-- )
+ {
+ int sz = mat->dim[j].size;
+ if( sz )
+ {
+ int t = idx/sz;
+ ptr += (idx - t*sz)*mat->dim[j].step;
+ idx = t;
+ }
+ }
+ }
+ }
+ else if( CV_IS_SPARSE_MAT( arr ))
+ {
+ CvSparseMat* m = (CvSparseMat*)arr;
+ if( m->dims == 1 )
+ ptr = icvGetNodePtr( (CvSparseMat*)arr, &idx, _type, 1, 0 );
+ else
+ {
+ int i, n = m->dims;
+ int* _idx = (int*)cvStackAlloc(n*sizeof(_idx[0]));
+
+ for( i = n - 1; i >= 0; i-- )
+ {
+ int t = idx / m->size[i];
+ _idx[i] = idx - t*m->size[i];
+ idx = t;
+ }
+ ptr = icvGetNodePtr( (CvSparseMat*)arr, _idx, _type, 1, 0 );
+ }
+ }
+ else
+ {
+ CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
+ }
+
+ return ptr;
+}
+
+
+// Returns pointer to specified element of 2d array
+CV_IMPL uchar*
+cvPtr2D( const CvArr* arr, int y, int x, int* _type )
+{
+ uchar* ptr = 0;
+ if( CV_IS_MAT( arr ))
+ {
+ CvMat* mat = (CvMat*)arr;
+ int type;
+
+ if( (unsigned)y >= (unsigned)(mat->rows) ||
+ (unsigned)x >= (unsigned)(mat->cols) )
+ CV_Error( CV_StsOutOfRange, "index is out of range" );
+
+ type = CV_MAT_TYPE(mat->type);
+ if( _type )
+ *_type = type;
+
+ ptr = mat->data.ptr + (size_t)y*mat->step + x*CV_ELEM_SIZE(type);
+ }
+ else if( CV_IS_IMAGE( arr ))
+ {
+ IplImage* img = (IplImage*)arr;
+ int pix_size = (img->depth & 255) >> 3;
+ int width, height;
+ ptr = (uchar*)img->imageData;
+
+ if( img->dataOrder == 0 )
+ pix_size *= img->nChannels;
+
+ if( img->roi )
+ {
+ width = img->roi->width;
+ height = img->roi->height;
+
+ ptr += img->roi->yOffset*img->widthStep +
+ img->roi->xOffset*pix_size;
+
+ if( img->dataOrder )
+ {
+ int coi = img->roi->coi;
+ if( !coi )
+ CV_Error( CV_BadCOI,
+ "COI must be non-null in case of planar images" );
+ ptr += (coi - 1)*img->imageSize;
+ }
+ }
+ else
+ {
+ width = img->width;
+ height = img->height;
+ }
+
+ if( (unsigned)y >= (unsigned)height ||
+ (unsigned)x >= (unsigned)width )
+ CV_Error( CV_StsOutOfRange, "index is out of range" );
+
+ ptr += y*img->widthStep + x*pix_size;
+
+ if( _type )
+ {
+ int type = IPL2CV_DEPTH(img->depth);
+ if( type < 0 || (unsigned)(img->nChannels - 1) > 3 )
+ CV_Error( CV_StsUnsupportedFormat, "" );
+
+ *_type = CV_MAKETYPE( type, img->nChannels );
+ }
+ }
+ else if( CV_IS_MATND( arr ))
+ {
+ CvMatND* mat = (CvMatND*)arr;
+
+ if( mat->dims != 2 ||
+ (unsigned)y >= (unsigned)(mat->dim[0].size) ||
+ (unsigned)x >= (unsigned)(mat->dim[1].size) )
+ CV_Error( CV_StsOutOfRange, "index is out of range" );
+
+ ptr = mat->data.ptr + (size_t)y*mat->dim[0].step + x*mat->dim[1].step;
+ if( _type )
+ *_type = CV_MAT_TYPE(mat->type);
+ }
+ else if( CV_IS_SPARSE_MAT( arr ))
+ {
+ int idx[] = { y, x };
+ ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, _type, 1, 0 );
+ }
+ else
+ {
+ CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
+ }
+
+ return ptr;
+}
+
+
+// Returns pointer to specified element of 3d array
+CV_IMPL uchar*
+cvPtr3D( const CvArr* arr, int z, int y, int x, int* _type )
+{
+ uchar* ptr = 0;
+ if( CV_IS_MATND( arr ))
+ {
+ CvMatND* mat = (CvMatND*)arr;
+
+ if( mat->dims != 3 ||
+ (unsigned)z >= (unsigned)(mat->dim[0].size) ||
+ (unsigned)y >= (unsigned)(mat->dim[1].size) ||
+ (unsigned)x >= (unsigned)(mat->dim[2].size) )
+ CV_Error( CV_StsOutOfRange, "index is out of range" );
+
+ ptr = mat->data.ptr + (size_t)z*mat->dim[0].step +
+ (size_t)y*mat->dim[1].step + x*mat->dim[2].step;
+
+ if( _type )
+ *_type = CV_MAT_TYPE(mat->type);
+ }
+ else if( CV_IS_SPARSE_MAT( arr ))
+ {
+ int idx[] = { z, y, x };
+ ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, _type, 1, 0 );
+ }
+ else
+ {
+ CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
+ }
+
+ return ptr;
+}
+
+
+// Returns pointer to specified element of n-d array
+CV_IMPL uchar*
+cvPtrND( const CvArr* arr, const int* idx, int* _type,
+ int create_node, unsigned* precalc_hashval )
+{
+ uchar* ptr = 0;
+ if( !idx )
+ CV_Error( CV_StsNullPtr, "NULL pointer to indices" );
+
+ if( CV_IS_SPARSE_MAT( arr ))
+ ptr = icvGetNodePtr( (CvSparseMat*)arr, idx,
+ _type, create_node, precalc_hashval );
+ else if( CV_IS_MATND( arr ))
+ {
+ CvMatND* mat = (CvMatND*)arr;
+ int i;
+ ptr = mat->data.ptr;
+
+ for( i = 0; i < mat->dims; i++ )
+ {
+ if( (unsigned)idx[i] >= (unsigned)(mat->dim[i].size) )
+ CV_Error( CV_StsOutOfRange, "index is out of range" );
+ ptr += (size_t)idx[i]*mat->dim[i].step;
+ }
+
+ if( _type )
+ *_type = CV_MAT_TYPE(mat->type);
+ }
+ else if( CV_IS_MAT_HDR(arr) || CV_IS_IMAGE_HDR(arr) )
+ ptr = cvPtr2D( arr, idx[0], idx[1], _type );
+ else
+ CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
+
+ return ptr;
+}
+
+
+// Returns specifed element of n-D array given linear index
+CV_IMPL CvScalar
+cvGet1D( const CvArr* arr, int idx )
+{
+ CvScalar scalar = {{0,0,0,0}};
+ int type = 0;
+ uchar* ptr;
+
+ if( CV_IS_MAT( arr ) && CV_IS_MAT_CONT( ((CvMat*)arr)->type ))
+ {
+ CvMat* mat = (CvMat*)arr;
+
+ type = CV_MAT_TYPE(mat->type);
+ int pix_size = CV_ELEM_SIZE(type);
+
+ // the first part is mul-free sufficient check
+ // that the index is within the matrix
+ if( (unsigned)idx >= (unsigned)(mat->rows + mat->cols - 1) &&
+ (unsigned)idx >= (unsigned)(mat->rows*mat->cols))
+ CV_Error( CV_StsOutOfRange, "index is out of range" );
+
+ ptr = mat->data.ptr + (size_t)idx*pix_size;
+ }
+ else if( !CV_IS_SPARSE_MAT( arr ) || ((CvSparseMat*)arr)->dims > 1 )
+ ptr = cvPtr1D( arr, idx, &type );
+ else
+ ptr = icvGetNodePtr( (CvSparseMat*)arr, &idx, &type, 0, 0 );
+
+ if( ptr )
+ cvRawDataToScalar( ptr, type, &scalar );
+
+ return scalar;
+}
+
+
+// Returns specifed element of 2D array
+CV_IMPL CvScalar
+cvGet2D( const CvArr* arr, int y, int x )
+{
+ CvScalar scalar = {{0,0,0,0}};
+ int type = 0;
+ uchar* ptr;
+
+ if( CV_IS_MAT( arr ))
+ {
+ CvMat* mat = (CvMat*)arr;
+
+ if( (unsigned)y >= (unsigned)(mat->rows) ||
+ (unsigned)x >= (unsigned)(mat->cols) )
+ CV_Error( CV_StsOutOfRange, "index is out of range" );
+
+ type = CV_MAT_TYPE(mat->type);
+ ptr = mat->data.ptr + (size_t)y*mat->step + x*CV_ELEM_SIZE(type);
+ }
+ else if( !CV_IS_SPARSE_MAT( arr ))
+ ptr = cvPtr2D( arr, y, x, &type );
+ else
+ {
+ int idx[] = { y, x };
+ ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, 0, 0 );
+ }
+
+ if( ptr )
+ cvRawDataToScalar( ptr, type, &scalar );
+
+ return scalar;
+}
+
+
+// Returns specifed element of 3D array
+CV_IMPL CvScalar
+cvGet3D( const CvArr* arr, int z, int y, int x )
+{
+ CvScalar scalar = {{0,0,0,0}};
+ int type = 0;
+ uchar* ptr;
+
+ if( !CV_IS_SPARSE_MAT( arr ))
+ ptr = cvPtr3D( arr, z, y, x, &type );
+ else
+ {
+ int idx[] = { z, y, x };
+ ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, 0, 0 );
+ }
+
+ if( ptr )
+ cvRawDataToScalar( ptr, type, &scalar );
+ return scalar;
+}
+
+
+// Returns specifed element of nD array
+CV_IMPL CvScalar
+cvGetND( const CvArr* arr, const int* idx )
+{
+ CvScalar scalar = {{0,0,0,0}};
+ int type = 0;
+ uchar* ptr;
+
+ if( !CV_IS_SPARSE_MAT( arr ))
+ ptr = cvPtrND( arr, idx, &type );
+ else
+ ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, 0, 0 );
+
+ if( ptr )
+ cvRawDataToScalar( ptr, type, &scalar );
+
+ return scalar;
+}
+
+
+// Returns specifed element of n-D array given linear index
+CV_IMPL double
+cvGetReal1D( const CvArr* arr, int idx )
+{
+ double value = 0;
+ int type = 0;
+ uchar* ptr;
+
+ if( CV_IS_MAT( arr ) && CV_IS_MAT_CONT( ((CvMat*)arr)->type ))
+ {
+ CvMat* mat = (CvMat*)arr;
+
+ type = CV_MAT_TYPE(mat->type);
+ int pix_size = CV_ELEM_SIZE(type);
+
+ // the first part is mul-free sufficient check
+ // that the index is within the matrix
+ if( (unsigned)idx >= (unsigned)(mat->rows + mat->cols - 1) &&
+ (unsigned)idx >= (unsigned)(mat->rows*mat->cols))
+ CV_Error( CV_StsOutOfRange, "index is out of range" );
+
+ ptr = mat->data.ptr + (size_t)idx*pix_size;
+ }
+ else if( !CV_IS_SPARSE_MAT( arr ) || ((CvSparseMat*)arr)->dims > 1 )
+ ptr = cvPtr1D( arr, idx, &type );
+ else
+ ptr = icvGetNodePtr( (CvSparseMat*)arr, &idx, &type, 0, 0 );
+
+ if( ptr )
+ {
+ if( CV_MAT_CN( type ) > 1 )
+ CV_Error( CV_BadNumChannels, "cvGetReal* support only single-channel arrays" );
+
+ value = icvGetReal( ptr, type );
+ }
+ return value;
+}
+
+
+// Returns specifed element of 2D array
+CV_IMPL double
+cvGetReal2D( const CvArr* arr, int y, int x )
+{
+ double value = 0;
+ int type = 0;
+ uchar* ptr;
+
+ if( CV_IS_MAT( arr ))
+ {
+ CvMat* mat = (CvMat*)arr;
+
+ if( (unsigned)y >= (unsigned)(mat->rows) ||
+ (unsigned)x >= (unsigned)(mat->cols) )
+ CV_Error( CV_StsOutOfRange, "index is out of range" );
+
+ type = CV_MAT_TYPE(mat->type);
+ ptr = mat->data.ptr + (size_t)y*mat->step + x*CV_ELEM_SIZE(type);
+ }
+ else if( !CV_IS_SPARSE_MAT( arr ))
+ ptr = cvPtr2D( arr, y, x, &type );
+ else
+ {
+ int idx[] = { y, x };
+ ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, 0, 0 );
+ }
+
+ if( ptr )
+ {
+ if( CV_MAT_CN( type ) > 1 )
+ CV_Error( CV_BadNumChannels, "cvGetReal* support only single-channel arrays" );
+
+ value = icvGetReal( ptr, type );
+ }
+
+ return value;
+}
+
+
+// Returns specifed element of 3D array
+CV_IMPL double
+cvGetReal3D( const CvArr* arr, int z, int y, int x )
+{
+ double value = 0;
+ int type = 0;
+ uchar* ptr;
+
+ if( !CV_IS_SPARSE_MAT( arr ))
+ ptr = cvPtr3D( arr, z, y, x, &type );
+ else
+ {
+ int idx[] = { z, y, x };
+ ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, 0, 0 );
+ }
+
+ if( ptr )
+ {
+ if( CV_MAT_CN( type ) > 1 )
+ CV_Error( CV_BadNumChannels, "cvGetReal* support only single-channel arrays" );
+
+ value = icvGetReal( ptr, type );
+ }
+
+ return value;
+}
+
+
+// Returns specifed element of nD array
+CV_IMPL double
+cvGetRealND( const CvArr* arr, const int* idx )
+{
+ double value = 0;
+ int type = 0;
+ uchar* ptr;
+
+ if( !CV_IS_SPARSE_MAT( arr ))
+ ptr = cvPtrND( arr, idx, &type );
+ else
+ ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, 0, 0 );
+
+ if( ptr )
+ {
+ if( CV_MAT_CN( type ) > 1 )
+ CV_Error( CV_BadNumChannels, "cvGetReal* support only single-channel arrays" );
+
+ value = icvGetReal( ptr, type );
+ }
+
+ return value;
+}
+
+
+// Assigns new value to specifed element of nD array given linear index
+CV_IMPL void
+cvSet1D( CvArr* arr, int idx, CvScalar scalar )
+{
+ int type = 0;
+ uchar* ptr;
+
+ if( CV_IS_MAT( arr ) && CV_IS_MAT_CONT( ((CvMat*)arr)->type ))
+ {
+ CvMat* mat = (CvMat*)arr;
+
+ type = CV_MAT_TYPE(mat->type);
+ int pix_size = CV_ELEM_SIZE(type);
+
+ // the first part is mul-free sufficient check
+ // that the index is within the matrix
+ if( (unsigned)idx >= (unsigned)(mat->rows + mat->cols - 1) &&
+ (unsigned)idx >= (unsigned)(mat->rows*mat->cols))
+ CV_Error( CV_StsOutOfRange, "index is out of range" );
+
+ ptr = mat->data.ptr + (size_t)idx*pix_size;
+ }
+ else if( !CV_IS_SPARSE_MAT( arr ) || ((CvSparseMat*)arr)->dims > 1 )
+ ptr = cvPtr1D( arr, idx, &type );
+ else
+ ptr = icvGetNodePtr( (CvSparseMat*)arr, &idx, &type, -1, 0 );
+
+ cvScalarToRawData( &scalar, ptr, type );
+}
+
+
+// Assigns new value to specifed element of 2D array
+CV_IMPL void
+cvSet2D( CvArr* arr, int y, int x, CvScalar scalar )
+{
+ int type = 0;
+ uchar* ptr;
+
+ if( CV_IS_MAT( arr ))
+ {
+ CvMat* mat = (CvMat*)arr;
+
+ if( (unsigned)y >= (unsigned)(mat->rows) ||
+ (unsigned)x >= (unsigned)(mat->cols) )
+ CV_Error( CV_StsOutOfRange, "index is out of range" );
+
+ type = CV_MAT_TYPE(mat->type);
+ ptr = mat->data.ptr + (size_t)y*mat->step + x*CV_ELEM_SIZE(type);
+ }
+ else if( !CV_IS_SPARSE_MAT( arr ))
+ ptr = cvPtr2D( arr, y, x, &type );
+ else
+ {
+ int idx[] = { y, x };
+ ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, -1, 0 );
+ }
+ cvScalarToRawData( &scalar, ptr, type );
+}
+
+
+// Assigns new value to specifed element of 3D array
+CV_IMPL void
+cvSet3D( CvArr* arr, int z, int y, int x, CvScalar scalar )
+{
+ int type = 0;
+ uchar* ptr;
+
+ if( !CV_IS_SPARSE_MAT( arr ))
+ ptr = cvPtr3D( arr, z, y, x, &type );
+ else
+ {
+ int idx[] = { z, y, x };
+ ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, -1, 0 );
+ }
+ cvScalarToRawData( &scalar, ptr, type );
+}
+
+
+// Assigns new value to specifed element of nD array
+CV_IMPL void
+cvSetND( CvArr* arr, const int* idx, CvScalar scalar )
+{
+ int type = 0;
+ uchar* ptr;
+
+ if( !CV_IS_SPARSE_MAT( arr ))
+ ptr = cvPtrND( arr, idx, &type );
+ else
+ ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, -1, 0 );
+ cvScalarToRawData( &scalar, ptr, type );
+}
+
+
+CV_IMPL void
+cvSetReal1D( CvArr* arr, int idx, double value )
+{
+ int type = 0;
+ uchar* ptr;
+
+ if( CV_IS_MAT( arr ) && CV_IS_MAT_CONT( ((CvMat*)arr)->type ))
+ {
+ CvMat* mat = (CvMat*)arr;
+
+ type = CV_MAT_TYPE(mat->type);
+ int pix_size = CV_ELEM_SIZE(type);
+
+ // the first part is mul-free sufficient check
+ // that the index is within the matrix
+ if( (unsigned)idx >= (unsigned)(mat->rows + mat->cols - 1) &&
+ (unsigned)idx >= (unsigned)(mat->rows*mat->cols))
+ CV_Error( CV_StsOutOfRange, "index is out of range" );
+
+ ptr = mat->data.ptr + (size_t)idx*pix_size;
+ }
+ else if( !CV_IS_SPARSE_MAT( arr ) || ((CvSparseMat*)arr)->dims > 1 )
+ ptr = cvPtr1D( arr, idx, &type );
+ else
+ ptr = icvGetNodePtr( (CvSparseMat*)arr, &idx, &type, -1, 0 );
+
+ if( CV_MAT_CN( type ) > 1 )
+ CV_Error( CV_BadNumChannels, "cvSetReal* support only single-channel arrays" );
+
+ if( ptr )
+ icvSetReal( value, ptr, type );
+}
+
+
+CV_IMPL void
+cvSetReal2D( CvArr* arr, int y, int x, double value )
+{
+ int type = 0;
+ uchar* ptr;
+
+ if( CV_IS_MAT( arr ))
+ {
+ CvMat* mat = (CvMat*)arr;
+
+ if( (unsigned)y >= (unsigned)(mat->rows) ||
+ (unsigned)x >= (unsigned)(mat->cols) )
+ CV_Error( CV_StsOutOfRange, "index is out of range" );
+
+ type = CV_MAT_TYPE(mat->type);
+ ptr = mat->data.ptr + (size_t)y*mat->step + x*CV_ELEM_SIZE(type);
+ }
+ else if( !CV_IS_SPARSE_MAT( arr ))
+ {
+ ptr = cvPtr2D( arr, y, x, &type );
+ }
+ else
+ {
+ int idx[] = { y, x };
+ ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, -1, 0 );
+ }
+ if( CV_MAT_CN( type ) > 1 )
+ CV_Error( CV_BadNumChannels, "cvSetReal* support only single-channel arrays" );
+
+ if( ptr )
+ icvSetReal( value, ptr, type );
+}
+
+
+CV_IMPL void
+cvSetReal3D( CvArr* arr, int z, int y, int x, double value )
+{
+ int type = 0;
+ uchar* ptr;
+
+ if( !CV_IS_SPARSE_MAT( arr ))
+ ptr = cvPtr3D( arr, z, y, x, &type );
+ else
+ {
+ int idx[] = { z, y, x };
+ ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, -1, 0 );
+ }
+ if( CV_MAT_CN( type ) > 1 )
+ CV_Error( CV_BadNumChannels, "cvSetReal* support only single-channel arrays" );
+
+ if( ptr )
+ icvSetReal( value, ptr, type );
+}
+
+
+CV_IMPL void
+cvSetRealND( CvArr* arr, const int* idx, double value )
+{
+ int type = 0;
+ uchar* ptr;
+
+ if( !CV_IS_SPARSE_MAT( arr ))
+ ptr = cvPtrND( arr, idx, &type );
+ else
+ ptr = icvGetNodePtr( (CvSparseMat*)arr, idx, &type, -1, 0 );
+
+ if( CV_MAT_CN( type ) > 1 )
+ CV_Error( CV_BadNumChannels, "cvSetReal* support only single-channel arrays" );
+
+ if( ptr )
+ icvSetReal( value, ptr, type );
+}
+
+
+CV_IMPL void
+cvClearND( CvArr* arr, const int* idx )
+{
+ if( !CV_IS_SPARSE_MAT( arr ))
+ {
+ int type;
+ uchar* ptr;
+ ptr = cvPtrND( arr, idx, &type );
+ if( ptr )
+ CV_ZERO_CHAR( ptr, CV_ELEM_SIZE(type) );
+ }
+ else
+ icvDeleteNode( (CvSparseMat*)arr, idx, 0 );
+}
+
+
+/****************************************************************************************\
+* Conversion to CvMat or IplImage *
+\****************************************************************************************/
+
+// convert array (CvMat or IplImage) to CvMat
+CV_IMPL CvMat*
+cvGetMat( const CvArr* array, CvMat* mat,
+ int* pCOI, int allowND )
+{
+ CvMat* result = 0;
+ CvMat* src = (CvMat*)array;
+ int coi = 0;
+
+ if( !mat || !src )
+ CV_Error( CV_StsNullPtr, "NULL array pointer is passed" );
+
+ if( CV_IS_MAT_HDR(src))
+ {
+ if( !src->data.ptr )
+ CV_Error( CV_StsNullPtr, "The matrix has NULL data pointer" );
+
+ result = (CvMat*)src;
+ }
+ else if( CV_IS_IMAGE_HDR(src) )
+ {
+ const IplImage* img = (const IplImage*)src;
+ int depth, order;
+
+ if( img->imageData == 0 )
+ CV_Error( CV_StsNullPtr, "The image has NULL data pointer" );
+
+ depth = IPL2CV_DEPTH( img->depth );
+ if( depth < 0 )
+ CV_Error( CV_BadDepth, "" );
+
+ order = img->dataOrder & (img->nChannels > 1 ? -1 : 0);
+
+ if( img->roi )
+ {
+ if( order == IPL_DATA_ORDER_PLANE )
+ {
+ int type = depth;
+
+ if( img->roi->coi == 0 )
+ CV_Error( CV_StsBadFlag,
+ "Images with planar data layout should be used with COI selected" );
+
+ cvInitMatHeader( mat, img->roi->height,
+ img->roi->width, type,
+ img->imageData + (img->roi->coi-1)*img->imageSize +
+ img->roi->yOffset*img->widthStep +
+ img->roi->xOffset*CV_ELEM_SIZE(type),
+ img->widthStep );
+ }
+ else /* pixel order */
+ {
+ int type = CV_MAKETYPE( depth, img->nChannels );
+ coi = img->roi->coi;
+
+ if( img->nChannels > CV_CN_MAX )
+ CV_Error( CV_BadNumChannels,
+ "The image is interleaved and has over CV_CN_MAX channels" );
+
+ cvInitMatHeader( mat, img->roi->height, img->roi->width,
+ type, img->imageData +
+ img->roi->yOffset*img->widthStep +
+ img->roi->xOffset*CV_ELEM_SIZE(type),
+ img->widthStep );
+ }
+ }
+ else
+ {
+ int type = CV_MAKETYPE( depth, img->nChannels );
+
+ if( order != IPL_DATA_ORDER_PIXEL )
+ CV_Error( CV_StsBadFlag, "Pixel order should be used with coi == 0" );
+
+ cvInitMatHeader( mat, img->height, img->width, type,
+ img->imageData, img->widthStep );
+ }
+
+ result = mat;
+ }
+ else if( allowND && CV_IS_MATND_HDR(src) )
+ {
+ CvMatND* matnd = (CvMatND*)src;
+ int i;
+ int size1 = matnd->dim[0].size, size2 = 1;
+
+ if( !src->data.ptr )
+ CV_Error( CV_StsNullPtr, "Input array has NULL data pointer" );
+
+ if( !CV_IS_MAT_CONT( matnd->type ))
+ CV_Error( CV_StsBadArg, "Only continuous nD arrays are supported here" );
+
+ if( matnd->dims > 2 )
+ for( i = 1; i < matnd->dims; i++ )
+ size2 *= matnd->dim[i].size;
+ else
+ size2 = matnd->dims == 1 ? 1 : matnd->dim[1].size;
+
+ mat->refcount = 0;
+ mat->hdr_refcount = 0;
+ mat->data.ptr = matnd->data.ptr;
+ mat->rows = size1;
+ mat->cols = size2;
+ mat->type = CV_MAT_TYPE(matnd->type) | CV_MAT_MAGIC_VAL | CV_MAT_CONT_FLAG;
+ mat->step = size2*CV_ELEM_SIZE(matnd->type);
+ mat->step &= size1 > 1 ? -1 : 0;
+
+ icvCheckHuge( mat );
+ result = mat;
+ }
+ else
+ CV_Error( CV_StsBadFlag, "Unrecognized or unsupported array type" );
+
+ if( pCOI )
+ *pCOI = coi;
+
+ return result;
+}
+
+
+CV_IMPL CvArr*
+cvReshapeMatND( const CvArr* arr,
+ int sizeof_header, CvArr* _header,
+ int new_cn, int new_dims, int* new_sizes )
+{
+ CvArr* result = 0;
+ int dims, coi = 0;
+
+ if( !arr || !_header )
+ CV_Error( CV_StsNullPtr, "NULL pointer to array or destination header" );
+
+ if( new_cn == 0 && new_dims == 0 )
+ CV_Error( CV_StsBadArg, "None of array parameters is changed: dummy call?" );
+
+ dims = cvGetDims( arr );
+
+ if( new_dims == 0 )
+ {
+ new_sizes = 0;
+ new_dims = dims;
+ }
+ else if( new_dims == 1 )
+ {
+ new_sizes = 0;
+ }
+ else
+ {
+ if( new_dims <= 0 || new_dims > CV_MAX_DIM )
+ CV_Error( CV_StsOutOfRange, "Non-positive or too large number of dimensions" );
+ if( !new_sizes )
+ CV_Error( CV_StsNullPtr, "New dimension sizes are not specified" );
+ }
+
+ if( new_dims <= 2 )
+ {
+ CvMat* mat = (CvMat*)arr;
+ CvMat header;
+ int* refcount = 0;
+ int hdr_refcount = 0;
+ int total_width, new_rows, cn;
+
+ if( sizeof_header != sizeof(CvMat) && sizeof_header != sizeof(CvMatND) )
+ CV_Error( CV_StsBadArg, "The output header should be CvMat or CvMatND" );
+
+ if( mat == (CvMat*)_header )
+ {
+ refcount = mat->refcount;
+ hdr_refcount = mat->hdr_refcount;
+ }
+
+ if( !CV_IS_MAT( mat ))
+ mat = cvGetMat( mat, &header, &coi, 1 );
+
+ cn = CV_MAT_CN( mat->type );
+ total_width = mat->cols * cn;
+
+ if( new_cn == 0 )
+ new_cn = cn;
+
+ if( new_sizes )
+ new_rows = new_sizes[0];
+ else if( new_dims == 1 )
+ new_rows = total_width*mat->rows/new_cn;
+ else
+ {
+ new_rows = mat->rows;
+ if( new_cn > total_width )
+ new_rows = mat->rows * total_width / new_cn;
+ }
+
+ if( new_rows != mat->rows )
+ {
+ int total_size = total_width * mat->rows;
+
+ if( !CV_IS_MAT_CONT( mat->type ))
+ CV_Error( CV_BadStep,
+ "The matrix is not continuous so the number of rows can not be changed" );
+
+ total_width = total_size / new_rows;
+
+ if( total_width * new_rows != total_size )
+ CV_Error( CV_StsBadArg, "The total number of matrix elements "
+ "is not divisible by the new number of rows" );
+ }
+
+ header.rows = new_rows;
+ header.cols = total_width / new_cn;
+
+ if( header.cols * new_cn != total_width ||
+ (new_sizes && header.cols != new_sizes[1]) )
+ CV_Error( CV_StsBadArg, "The total matrix width is not "
+ "divisible by the new number of columns" );
+
+ header.type = (mat->type & ~CV_MAT_TYPE_MASK) | CV_MAKETYPE(mat->type, new_cn);
+ header.step = header.cols * CV_ELEM_SIZE(mat->type);
+ header.step &= new_rows > 1 ? -1 : 0;
+ header.refcount = refcount;
+ header.hdr_refcount = hdr_refcount;
+
+ if( sizeof_header == sizeof(CvMat) )
+ *(CvMat*)_header = header;
+ else
+ {
+ CvMatND* __header = (CvMatND*)_header;
+ cvGetMatND(&header, __header, 0);
+ if( new_dims > 0 )
+ __header->dims = new_dims;
+ }
+ }
+ else
+ {
+ CvMatND* header = (CvMatND*)_header;
+
+ if( sizeof_header != sizeof(CvMatND))
+ CV_Error( CV_StsBadSize, "The output header should be CvMatND" );
+
+ if( !new_sizes )
+ {
+ if( !CV_IS_MATND( arr ))
+ CV_Error( CV_StsBadArg, "The input array must be CvMatND" );
+
+ {
+ CvMatND* mat = (CvMatND*)arr;
+ assert( new_cn > 0 );
+ int last_dim_size = mat->dim[mat->dims-1].size*CV_MAT_CN(mat->type);
+ int new_size = last_dim_size/new_cn;
+
+ if( new_size*new_cn != last_dim_size )
+ CV_Error( CV_StsBadArg,
+ "The last dimension full size is not divisible by new number of channels");
+
+ if( mat != header )
+ {
+ memcpy( header, mat, sizeof(*header));
+ header->refcount = 0;
+ header->hdr_refcount = 0;
+ }
+
+ header->dim[header->dims-1].size = new_size;
+ header->type = (header->type & ~CV_MAT_TYPE_MASK) | CV_MAKETYPE(header->type, new_cn);
+ }
+ }
+ else
+ {
+ CvMatND stub;
+ CvMatND* mat = (CvMatND*)arr;
+ int i, size1, size2;
+ int step;
+
+ if( new_cn != 0 )
+ CV_Error( CV_StsBadArg,
+ "Simultaneous change of shape and number of channels is not supported. "
+ "Do it by 2 separate calls" );
+
+ if( !CV_IS_MATND( mat ))
+ {
+ cvGetMatND( mat, &stub, &coi );
+ mat = &stub;
+ }
+
+ if( CV_IS_MAT_CONT( mat->type ))
+ CV_Error( CV_StsBadArg, "Non-continuous nD arrays are not supported" );
+
+ size1 = mat->dim[0].size;
+ for( i = 1; i < dims; i++ )
+ size1 *= mat->dim[i].size;
+
+ size2 = 1;
+ for( i = 0; i < new_dims; i++ )
+ {
+ if( new_sizes[i] <= 0 )
+ CV_Error( CV_StsBadSize,
+ "One of new dimension sizes is non-positive" );
+ size2 *= new_sizes[i];
+ }
+
+ if( size1 != size2 )
+ CV_Error( CV_StsBadSize,
+ "Number of elements in the original and reshaped array is different" );
+
+ if( header != mat )
+ {
+ header->refcount = 0;
+ header->hdr_refcount = 0;
+ }
+
+ header->dims = new_dims;
+ header->type = mat->type;
+ header->data.ptr = mat->data.ptr;
+ step = CV_ELEM_SIZE(header->type);
+
+ for( i = new_dims - 1; i >= 0; i-- )
+ {
+ header->dim[i].size = new_sizes[i];
+ header->dim[i].step = step;
+ step *= new_sizes[i];
+ }
+ }
+ }
+
+ if( coi )
+ CV_Error( CV_BadCOI, "COI is not supported by this operation" );
+
+ result = _header;
+ return result;
+}
+
+
+CV_IMPL CvMat*
+cvReshape( const CvArr* array, CvMat* header,
+ int new_cn, int new_rows )
+{
+ CvMat* result = 0;
+ CvMat *mat = (CvMat*)array;
+ int total_width, new_width;
+
+ if( !header )
+ CV_Error( CV_StsNullPtr, "" );
+
+ if( !CV_IS_MAT( mat ))
+ {
+ int coi = 0;
+ mat = cvGetMat( mat, header, &coi, 1 );
+ if( coi )
+ CV_Error( CV_BadCOI, "COI is not supported" );
+ }
+
+ if( new_cn == 0 )
+ new_cn = CV_MAT_CN(mat->type);
+ else if( (unsigned)(new_cn - 1) > 3 )
+ CV_Error( CV_BadNumChannels, "" );
+
+ if( mat != header )
+ {
+ int hdr_refcount = header->hdr_refcount;
+ *header = *mat;
+ header->refcount = 0;
+ header->hdr_refcount = hdr_refcount;
+ }
+
+ total_width = mat->cols * CV_MAT_CN( mat->type );
+
+ if( (new_cn > total_width || total_width % new_cn != 0) && new_rows == 0 )
+ new_rows = mat->rows * total_width / new_cn;
+
+ if( new_rows == 0 || new_rows == mat->rows )
+ {
+ header->rows = mat->rows;
+ header->step = mat->step;
+ }
+ else
+ {
+ int total_size = total_width * mat->rows;
+ if( !CV_IS_MAT_CONT( mat->type ))
+ CV_Error( CV_BadStep,
+ "The matrix is not continuous, thus its number of rows can not be changed" );
+
+ if( (unsigned)new_rows > (unsigned)total_size )
+ CV_Error( CV_StsOutOfRange, "Bad new number of rows" );
+
+ total_width = total_size / new_rows;
+
+ if( total_width * new_rows != total_size )
+ CV_Error( CV_StsBadArg, "The total number of matrix elements "
+ "is not divisible by the new number of rows" );
+
+ header->rows = new_rows;
+ header->step = total_width * CV_ELEM_SIZE1(mat->type);
+ }
+
+ new_width = total_width / new_cn;
+
+ if( new_width * new_cn != total_width )
+ CV_Error( CV_BadNumChannels,
+ "The total width is not divisible by the new number of channels" );
+
+ header->cols = new_width;
+ header->type = (mat->type & ~CV_MAT_TYPE_MASK) | CV_MAKETYPE(mat->type, new_cn);
+
+ result = header;
+ return result;
+}
+
+
+// convert array (CvMat or IplImage) to IplImage
+CV_IMPL IplImage*
+cvGetImage( const CvArr* array, IplImage* img )
+{
+ IplImage* result = 0;
+ const IplImage* src = (const IplImage*)array;
+ int depth;
+
+ if( !img )
+ CV_Error( CV_StsNullPtr, "" );
+
+ if( !CV_IS_IMAGE_HDR(src) )
+ {
+ const CvMat* mat = (const CvMat*)src;
+
+ if( !CV_IS_MAT_HDR(mat))
+ CV_Error( CV_StsBadFlag, "" );
+
+ if( mat->data.ptr == 0 )
+ CV_Error( CV_StsNullPtr, "" );
+
+ depth = cvIplDepth(mat->type);
+
+ cvInitImageHeader( img, cvSize(mat->cols, mat->rows),
+ depth, CV_MAT_CN(mat->type) );
+ cvSetData( img, mat->data.ptr, mat->step );
+
+ result = img;
+ }
+ else
+ {
+ result = (IplImage*)src;
+ }
+
+ return result;
+}
+
+
+/****************************************************************************************\
+* IplImage-specific functions *
+\****************************************************************************************/
+
+static IplROI* icvCreateROI( int coi, int xOffset, int yOffset, int width, int height )
+{
+ IplROI *roi = 0;
+ if( !CvIPL.createROI )
+ {
+ roi = (IplROI*)cvAlloc( sizeof(*roi));
+
+ roi->coi = coi;
+ roi->xOffset = xOffset;
+ roi->yOffset = yOffset;
+ roi->width = width;
+ roi->height = height;
+ }
+ else
+ {
+ roi = CvIPL.createROI( coi, xOffset, yOffset, width, height );
+ }
+
+ return roi;
+}
+
+static void
+icvGetColorModel( int nchannels, const char** colorModel, const char** channelSeq )
+{
+ static const char* tab[][2] =
+ {
+ {"GRAY", "GRAY"},
+ {"",""},
+ {"RGB","BGR"},
+ {"RGB","BGRA"}
+ };
+
+ nchannels--;
+ *colorModel = *channelSeq = "";
+
+ if( (unsigned)nchannels <= 3 )
+ {
+ *colorModel = tab[nchannels][0];
+ *channelSeq = tab[nchannels][1];
+ }
+}
+
+
+// create IplImage header
+CV_IMPL IplImage *
+cvCreateImageHeader( CvSize size, int depth, int channels )
+{
+ IplImage *img = 0;
+
+ if( !CvIPL.createHeader )
+ {
+ img = (IplImage *)cvAlloc( sizeof( *img ));
+ cvInitImageHeader( img, size, depth, channels, IPL_ORIGIN_TL,
+ CV_DEFAULT_IMAGE_ROW_ALIGN );
+ }
+ else
+ {
+ const char *colorModel, *channelSeq;
+
+ icvGetColorModel( channels, &colorModel, &channelSeq );
+
+ img = CvIPL.createHeader( channels, 0, depth, (char*)colorModel, (char*)channelSeq,
+ IPL_DATA_ORDER_PIXEL, IPL_ORIGIN_TL,
+ CV_DEFAULT_IMAGE_ROW_ALIGN,
+ size.width, size.height, 0, 0, 0, 0 );
+ }
+
+ return img;
+}
+
+
+// create IplImage header and allocate underlying data
+CV_IMPL IplImage *
+cvCreateImage( CvSize size, int depth, int channels )
+{
+ IplImage *img = cvCreateImageHeader( size, depth, channels );
+ assert( img );
+ cvCreateData( img );
+
+ return img;
+}
+
+
+// initalize IplImage header, allocated by the user
+CV_IMPL IplImage*
+cvInitImageHeader( IplImage * image, CvSize size, int depth,
+ int channels, int origin, int align )
+{
+ const char *colorModel, *channelSeq;
+
+ if( !image )
+ CV_Error( CV_HeaderIsNull, "null pointer to header" );
+
+ memset( image, 0, sizeof( *image ));
+ image->nSize = sizeof( *image );
+
+ icvGetColorModel( channels, &colorModel, &channelSeq );
+ strncpy( image->colorModel, colorModel, 4 );
+ strncpy( image->channelSeq, channelSeq, 4 );
+
+ if( size.width < 0 || size.height < 0 )
+ CV_Error( CV_BadROISize, "Bad input roi" );
+
+ if( (depth != (int)IPL_DEPTH_1U && depth != (int)IPL_DEPTH_8U &&
+ depth != (int)IPL_DEPTH_8S && depth != (int)IPL_DEPTH_16U &&
+ depth != (int)IPL_DEPTH_16S && depth != (int)IPL_DEPTH_32S &&
+ depth != (int)IPL_DEPTH_32F && depth != (int)IPL_DEPTH_64F) ||
+ channels < 0 )
+ CV_Error( CV_BadDepth, "Unsupported format" );
+ if( origin != CV_ORIGIN_BL && origin != CV_ORIGIN_TL )
+ CV_Error( CV_BadOrigin, "Bad input origin" );
+
+ if( align != 4 && align != 8 )
+ CV_Error( CV_BadAlign, "Bad input align" );
+
+ image->width = size.width;
+ image->height = size.height;
+
+ if( image->roi )
+ {
+ image->roi->coi = 0;
+ image->roi->xOffset = image->roi->yOffset = 0;
+ image->roi->width = size.width;
+ image->roi->height = size.height;
+ }
+
+ image->nChannels = MAX( channels, 1 );
+ image->depth = depth;
+ image->align = align;
+ image->widthStep = (((image->width * image->nChannels *
+ (image->depth & ~IPL_DEPTH_SIGN) + 7)/8)+ align - 1) & (~(align - 1));
+ image->origin = origin;
+ image->imageSize = image->widthStep * image->height;
+
+ return image;
+}
+
+
+CV_IMPL void
+cvReleaseImageHeader( IplImage** image )
+{
+ if( !image )
+ CV_Error( CV_StsNullPtr, "" );
+
+ if( *image )
+ {
+ IplImage* img = *image;
+ *image = 0;
+
+ if( !CvIPL.deallocate )
+ {
+ cvFree( &img->roi );
+ cvFree( &img );
+ }
+ else
+ {
+ CvIPL.deallocate( img, IPL_IMAGE_HEADER | IPL_IMAGE_ROI );
+ }
+ }
+}
+
+
+CV_IMPL void
+cvReleaseImage( IplImage ** image )
+{
+ if( !image )
+ CV_Error( CV_StsNullPtr, "" );
+
+ if( *image )
+ {
+ IplImage* img = *image;
+ *image = 0;
+
+ cvReleaseData( img );
+ cvReleaseImageHeader( &img );
+ }
+}
+
+
+CV_IMPL void
+cvSetImageROI( IplImage* image, CvRect rect )
+{
+ if( !image )
+ CV_Error( CV_HeaderIsNull, "" );
+
+ // allow zero ROI width or height
+ CV_Assert( rect.width >= 0 && rect.height >= 0 &&
+ rect.x < image->width && rect.y < image->height &&
+ rect.x + rect.width >= (int)(rect.width > 0) &&
+ rect.y + rect.height >= (int)(rect.height > 0) );
+
+ rect.width += rect.x;
+ rect.height += rect.y;
+
+ rect.x = std::max(rect.x, 0);
+ rect.y = std::max(rect.y, 0);
+ rect.width = std::min(rect.width, image->width);
+ rect.height = std::min(rect.height, image->height);
+
+ rect.width -= rect.x;
+ rect.height -= rect.y;
+
+ if( image->roi )
+ {
+ image->roi->xOffset = rect.x;
+ image->roi->yOffset = rect.y;
+ image->roi->width = rect.width;
+ image->roi->height = rect.height;
+ }
+ else
+ image->roi = icvCreateROI( 0, rect.x, rect.y, rect.width, rect.height );
+}
+
+
+CV_IMPL void
+cvResetImageROI( IplImage* image )
+{
+ if( !image )
+ CV_Error( CV_HeaderIsNull, "" );
+
+ if( image->roi )
+ {
+ if( !CvIPL.deallocate )
+ {
+ cvFree( &image->roi );
+ }
+ else
+ {
+ CvIPL.deallocate( image, IPL_IMAGE_ROI );
+ image->roi = 0;
+ }
+ }
+}
+
+
+CV_IMPL CvRect
+cvGetImageROI( const IplImage* img )
+{
+ CvRect rect = { 0, 0, 0, 0 };
+ if( !img )
+ CV_Error( CV_StsNullPtr, "Null pointer to image" );
+
+ if( img->roi )
+ rect = cvRect( img->roi->xOffset, img->roi->yOffset,
+ img->roi->width, img->roi->height );
+ else
+ rect = cvRect( 0, 0, img->width, img->height );
+
+ return rect;
+}
+
+
+CV_IMPL void
+cvSetImageCOI( IplImage* image, int coi )
+{
+ if( !image )
+ CV_Error( CV_HeaderIsNull, "" );
+
+ if( (unsigned)coi > (unsigned)(image->nChannels) )
+ CV_Error( CV_BadCOI, "" );
+
+ if( image->roi || coi != 0 )
+ {
+ if( image->roi )
+ {
+ image->roi->coi = coi;
+ }
+ else
+ {
+ image->roi = icvCreateROI( coi, 0, 0, image->width, image->height );
+ }
+ }
+}
+
+
+CV_IMPL int
+cvGetImageCOI( const IplImage* image )
+{
+ if( !image )
+ CV_Error( CV_HeaderIsNull, "" );
+
+ return image->roi ? image->roi->coi : 0;
+}
+
+
+CV_IMPL IplImage*
+cvCloneImage( const IplImage* src )
+{
+ IplImage* dst = 0;
+
+ if( !CV_IS_IMAGE_HDR( src ))
+ CV_Error( CV_StsBadArg, "Bad image header" );
+
+ if( !CvIPL.cloneImage )
+ {
+ dst = (IplImage*)cvAlloc( sizeof(*dst));
+
+ memcpy( dst, src, sizeof(*src));
+ dst->imageData = dst->imageDataOrigin = 0;
+ dst->roi = 0;
+
+ if( src->roi )
+ {
+ dst->roi = icvCreateROI( src->roi->coi, src->roi->xOffset,
+ src->roi->yOffset, src->roi->width, src->roi->height );
+ }
+
+ if( src->imageData )
+ {
+ int size = src->imageSize;
+ cvCreateData( dst );
+ memcpy( dst->imageData, src->imageData, size );
+ }
+ }
+ else
+ dst = CvIPL.cloneImage( src );
+
+ return dst;
+}
+
+
+/****************************************************************************************\
+* Additional operations on CvTermCriteria *
+\****************************************************************************************/
+
+CV_IMPL CvTermCriteria
+cvCheckTermCriteria( CvTermCriteria criteria, double default_eps,
+ int default_max_iters )
+{
+ CvTermCriteria crit;
+
+ crit.type = CV_TERMCRIT_ITER|CV_TERMCRIT_EPS;
+ crit.max_iter = default_max_iters;
+ crit.epsilon = (float)default_eps;
+
+ if( (criteria.type & ~(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER)) != 0 )
+ CV_Error( CV_StsBadArg,
+ "Unknown type of term criteria" );
+
+ if( (criteria.type & CV_TERMCRIT_ITER) != 0 )
+ {
+ if( criteria.max_iter <= 0 )
+ CV_Error( CV_StsBadArg,
+ "Iterations flag is set and maximum number of iterations is <= 0" );
+ crit.max_iter = criteria.max_iter;
+ }
+
+ if( (criteria.type & CV_TERMCRIT_EPS) != 0 )
+ {
+ if( criteria.epsilon < 0 )
+ CV_Error( CV_StsBadArg, "Accuracy flag is set and epsilon is < 0" );
+
+ crit.epsilon = criteria.epsilon;
+ }
+
+ if( (criteria.type & (CV_TERMCRIT_EPS | CV_TERMCRIT_ITER)) == 0 )
+ CV_Error( CV_StsBadArg,
+ "Neither accuracy nor maximum iterations "
+ "number flags are set in criteria type" );
+
+ crit.epsilon = (float)MAX( 0, crit.epsilon );
+ crit.max_iter = MAX( 1, crit.max_iter );
+
+ return crit;
+}
+
+
+/* End of file. */