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