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