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