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