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 #ifndef OPENCV_EXCLUDE_C_API
52 
53 #define  CV_ORIGIN_TL  0
54 #define  CV_ORIGIN_BL  1
55 
56 /* default image row align (in bytes) */
57 #define  CV_DEFAULT_IMAGE_ROW_ALIGN  4
58 
59 
60 static struct
61 {
62     Cv_iplCreateImageHeader  createHeader;
63     Cv_iplAllocateImageData  allocateData;
64     Cv_iplDeallocate  deallocate;
65     Cv_iplCreateROI  createROI;
66     Cv_iplCloneImage  cloneImage;
67 }
68 CvIPL;
69 
70 // Makes the library use native IPL image allocators
71 CV_IMPL void
cvSetIPLAllocators(Cv_iplCreateImageHeader createHeader,Cv_iplAllocateImageData allocateData,Cv_iplDeallocate deallocate,Cv_iplCreateROI createROI,Cv_iplCloneImage cloneImage)72 cvSetIPLAllocators( Cv_iplCreateImageHeader createHeader,
73                     Cv_iplAllocateImageData allocateData,
74                     Cv_iplDeallocate deallocate,
75                     Cv_iplCreateROI createROI,
76                     Cv_iplCloneImage cloneImage )
77 {
78     int count = (createHeader != 0) + (allocateData != 0) + (deallocate != 0) +
79         (createROI != 0) + (cloneImage != 0);
80 
81     if( count != 0 && count != 5 )
82         CV_Error( CV_StsBadArg, "Either all the pointers should be null or "
83                                  "they all should be non-null" );
84 
85     CvIPL.createHeader = createHeader;
86     CvIPL.allocateData = allocateData;
87     CvIPL.deallocate = deallocate;
88     CvIPL.createROI = createROI;
89     CvIPL.cloneImage = cloneImage;
90 }
91 
92 
93 /****************************************************************************************\
94 *                               CvMat creation and basic operations                      *
95 \****************************************************************************************/
96 
97 // Creates CvMat and underlying data
98 CV_IMPL CvMat*
cvCreateMat(int height,int width,int type)99 cvCreateMat( int height, int width, int type )
100 {
101     CvMat* arr = cvCreateMatHeader( height, width, type );
102     cvCreateData( arr );
103 
104     return arr;
105 }
106 
107 
icvCheckHuge(CvMat * arr)108 static void icvCheckHuge( CvMat* arr )
109 {
110     if( (int64)arr->step*arr->rows > INT_MAX )
111         arr->type &= ~CV_MAT_CONT_FLAG;
112 }
113 
114 // Creates CvMat header only
115 CV_IMPL CvMat*
cvCreateMatHeader(int rows,int cols,int type)116 cvCreateMatHeader( int rows, int cols, int type )
117 {
118     type = CV_MAT_TYPE(type);
119 
120     if( rows < 0 || cols < 0 )
121         CV_Error( CV_StsBadSize, "Non-positive width or height" );
122 
123     int min_step = CV_ELEM_SIZE(type);
124     if( min_step <= 0 )
125         CV_Error( CV_StsUnsupportedFormat, "Invalid matrix type" );
126     min_step *= cols;
127 
128     CvMat* arr = (CvMat*)cvAlloc( sizeof(*arr));
129 
130     arr->step = min_step;
131     arr->type = CV_MAT_MAGIC_VAL | type | CV_MAT_CONT_FLAG;
132     arr->rows = rows;
133     arr->cols = cols;
134     arr->data.ptr = 0;
135     arr->refcount = 0;
136     arr->hdr_refcount = 1;
137 
138     icvCheckHuge( arr );
139     return arr;
140 }
141 
142 
143 // Initializes CvMat header, allocated by the user
144 CV_IMPL CvMat*
cvInitMatHeader(CvMat * arr,int rows,int cols,int type,void * data,int step)145 cvInitMatHeader( CvMat* arr, int rows, int cols,
146                  int type, void* data, int step )
147 {
148     if( !arr )
149         CV_Error( CV_StsNullPtr, "" );
150 
151     if( (unsigned)CV_MAT_DEPTH(type) > CV_DEPTH_MAX )
152         CV_Error( CV_BadNumChannels, "" );
153 
154     if( rows < 0 || cols < 0 )
155         CV_Error( CV_StsBadSize, "Non-positive cols or rows" );
156 
157     type = CV_MAT_TYPE( type );
158     arr->type = type | CV_MAT_MAGIC_VAL;
159     arr->rows = rows;
160     arr->cols = cols;
161     arr->data.ptr = (uchar*)data;
162     arr->refcount = 0;
163     arr->hdr_refcount = 0;
164 
165     int pix_size = CV_ELEM_SIZE(type);
166     int min_step = arr->cols*pix_size;
167 
168     if( step != CV_AUTOSTEP && step != 0 )
169     {
170         if( step < min_step )
171             CV_Error( CV_BadStep, "" );
172         arr->step = step;
173     }
174     else
175     {
176         arr->step = min_step;
177     }
178 
179     arr->type = CV_MAT_MAGIC_VAL | type |
180         (arr->rows == 1 || arr->step == min_step ? CV_MAT_CONT_FLAG : 0);
181 
182     icvCheckHuge( arr );
183     return arr;
184 }
185 
186 
187 // Deallocates the CvMat structure and underlying data
188 CV_IMPL void
cvReleaseMat(CvMat ** array)189 cvReleaseMat( CvMat** array )
190 {
191     if( !array )
192         CV_Error( CV_HeaderIsNull, "" );
193 
194     if( *array )
195     {
196         CvMat* arr = *array;
197 
198         if( !CV_IS_MAT_HDR_Z(arr) && !CV_IS_MATND_HDR(arr) )
199             CV_Error( CV_StsBadFlag, "" );
200 
201         *array = 0;
202 
203         cvDecRefData( arr );
204         cvFree( &arr );
205     }
206 }
207 
208 
209 // Creates a copy of matrix
210 CV_IMPL CvMat*
cvCloneMat(const CvMat * src)211 cvCloneMat( const CvMat* src )
212 {
213     if( !CV_IS_MAT_HDR( src ))
214         CV_Error( CV_StsBadArg, "Bad CvMat header" );
215 
216     CvMat* dst = cvCreateMatHeader( src->rows, src->cols, src->type );
217 
218     if( src->data.ptr )
219     {
220         cvCreateData( dst );
221         cvCopy( src, dst );
222     }
223 
224     return dst;
225 }
226 
227 
228 /****************************************************************************************\
229 *                               CvMatND creation and basic operations                    *
230 \****************************************************************************************/
231 
232 CV_IMPL CvMatND*
cvInitMatNDHeader(CvMatND * mat,int dims,const int * sizes,int type,void * data)233 cvInitMatNDHeader( CvMatND* mat, int dims, const int* sizes,
234                    int type, void* data )
235 {
236     type = CV_MAT_TYPE(type);
237     int64 step = CV_ELEM_SIZE(type);
238 
239     if( !mat )
240         CV_Error( CV_StsNullPtr, "NULL matrix header pointer" );
241 
242     if( step == 0 )
243         CV_Error( CV_StsUnsupportedFormat, "invalid array data type" );
244 
245     if( !sizes )
246         CV_Error( CV_StsNullPtr, "NULL <sizes> pointer" );
247 
248     if( dims <= 0 || dims > CV_MAX_DIM )
249         CV_Error( CV_StsOutOfRange,
250         "non-positive or too large number of dimensions" );
251 
252     for( int i = dims - 1; i >= 0; i-- )
253     {
254         if( sizes[i] < 0 )
255             CV_Error( CV_StsBadSize, "one of dimension sizes is non-positive" );
256         mat->dim[i].size = sizes[i];
257         if( step > INT_MAX )
258             CV_Error( CV_StsOutOfRange, "The array is too big" );
259         mat->dim[i].step = (int)step;
260         step *= sizes[i];
261     }
262 
263     mat->type = CV_MATND_MAGIC_VAL | (step <= INT_MAX ? CV_MAT_CONT_FLAG : 0) | type;
264     mat->dims = dims;
265     mat->data.ptr = (uchar*)data;
266     mat->refcount = 0;
267     mat->hdr_refcount = 0;
268     return mat;
269 }
270 
271 
272 // Creates CvMatND and underlying data
273 CV_IMPL CvMatND*
cvCreateMatND(int dims,const int * sizes,int type)274 cvCreateMatND( int dims, const int* sizes, int type )
275 {
276     CvMatND* arr = cvCreateMatNDHeader( dims, sizes, type );
277     cvCreateData( arr );
278 
279     return arr;
280 }
281 
282 
283 // Creates CvMatND header only
284 CV_IMPL CvMatND*
cvCreateMatNDHeader(int dims,const int * sizes,int type)285 cvCreateMatNDHeader( int dims, const int* sizes, int type )
286 {
287     if( dims <= 0 || dims > CV_MAX_DIM )
288         CV_Error( CV_StsOutOfRange,
289         "non-positive or too large number of dimensions" );
290 
291     CvMatND* arr = (CvMatND*)cvAlloc( sizeof(*arr) );
292 
293     cvInitMatNDHeader( arr, dims, sizes, type, 0 );
294     arr->hdr_refcount = 1;
295     return arr;
296 }
297 
298 
299 // Creates a copy of nD array
300 CV_IMPL CvMatND*
cvCloneMatND(const CvMatND * src)301 cvCloneMatND( const CvMatND* src )
302 {
303     if( !CV_IS_MATND_HDR( src ))
304         CV_Error( CV_StsBadArg, "Bad CvMatND header" );
305 
306     CV_Assert( src->dims <= CV_MAX_DIM );
307     int sizes[CV_MAX_DIM];
308 
309     for( int i = 0; i < src->dims; i++ )
310         sizes[i] = src->dim[i].size;
311 
312     CvMatND* dst = cvCreateMatNDHeader( src->dims, sizes, src->type );
313 
314     if( src->data.ptr )
315     {
316         cvCreateData( dst );
317         cv::Mat _src = cv::cvarrToMat(src);
318         cv::Mat _dst = cv::cvarrToMat(dst);
319         uchar* data0 = dst->data.ptr;
320         _src.copyTo(_dst);
321         CV_Assert(_dst.data == data0);
322         //cvCopy( src, dst );
323     }
324 
325     return dst;
326 }
327 
328 
329 static CvMatND*
cvGetMatND(const CvArr * arr,CvMatND * matnd,int * coi)330 cvGetMatND( const CvArr* arr, CvMatND* matnd, int* coi )
331 {
332     CvMatND* result = 0;
333 
334     if( coi )
335         *coi = 0;
336 
337     if( !matnd || !arr )
338         CV_Error( CV_StsNullPtr, "NULL array pointer is passed" );
339 
340     if( CV_IS_MATND_HDR(arr))
341     {
342         if( !((CvMatND*)arr)->data.ptr )
343             CV_Error( CV_StsNullPtr, "The matrix has NULL data pointer" );
344 
345         result = (CvMatND*)arr;
346     }
347     else
348     {
349         CvMat stub, *mat = (CvMat*)arr;
350 
351         if( CV_IS_IMAGE_HDR( mat ))
352             mat = cvGetMat( mat, &stub, coi );
353 
354         if( !CV_IS_MAT_HDR( mat ))
355             CV_Error( CV_StsBadArg, "Unrecognized or unsupported array type" );
356 
357         if( !mat->data.ptr )
358             CV_Error( CV_StsNullPtr, "Input array has NULL data pointer" );
359 
360         matnd->data.ptr = mat->data.ptr;
361         matnd->refcount = 0;
362         matnd->hdr_refcount = 0;
363         matnd->type = mat->type;
364         matnd->dims = 2;
365         matnd->dim[0].size = mat->rows;
366         matnd->dim[0].step = mat->step;
367         matnd->dim[1].size = mat->cols;
368         matnd->dim[1].step = CV_ELEM_SIZE(mat->type);
369         result = matnd;
370     }
371 
372     return result;
373 }
374 
375 
376 // returns number of dimensions to iterate.
377 /*
378 Checks whether <count> arrays have equal type, sizes (mask is optional array
379 that needs to have the same size, but 8uC1 or 8sC1 type - feature has been disabled).
380 Returns number of dimensions to iterate through:
381 0 means that all arrays are continuous,
382 1 means that all arrays are vectors of continuous arrays etc.
383 and the size of largest common continuous part of the arrays
384 */
385 CV_IMPL int
cvInitNArrayIterator(int count,CvArr ** arrs,const CvArr * mask,CvMatND * stubs,CvNArrayIterator * iterator,int flags)386 cvInitNArrayIterator( int count, CvArr** arrs,
387                       const CvArr* mask, CvMatND* stubs,
388                       CvNArrayIterator* iterator, int flags )
389 {
390     int dims = -1;
391     int i, j, size, dim0 = -1;
392     int64 step;
393     CvMatND* hdr0 = 0;
394 
395     if( count < 1 || count > CV_MAX_ARR )
396         CV_Error( CV_StsOutOfRange, "Incorrect number of arrays" );
397 
398     if( !arrs || !stubs )
399         CV_Error( CV_StsNullPtr, "Some of required array pointers is NULL" );
400 
401     if( !iterator )
402         CV_Error( CV_StsNullPtr, "Iterator pointer is NULL" );
403 
404     if (mask)
405         CV_Error( CV_StsBadArg, "Iterator with mask is not supported" );
406 
407     for( i = 0; i < count; i++ )
408     {
409         const CvArr* arr = arrs[i];
410         CvMatND* hdr;
411 
412         if( !arr )
413             CV_Error( CV_StsNullPtr, "Some of required array pointers is NULL" );
414 
415         if( CV_IS_MATND( arr ))
416             hdr = (CvMatND*)arr;
417         else
418         {
419             int coi = 0;
420             hdr = cvGetMatND( arr, stubs + i, &coi );
421             if( coi != 0 )
422                 CV_Error( CV_BadCOI, "COI set is not allowed here" );
423         }
424 
425         iterator->hdr[i] = hdr;
426 
427         if( i > 0 )
428         {
429             if( hdr->dims != hdr0->dims )
430                 CV_Error( CV_StsUnmatchedSizes,
431                           "Number of dimensions is the same for all arrays" );
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             if( !(flags & CV_NO_SIZE_CHECK) )
453             {
454                 for( j = 0; j < hdr->dims; j++ )
455                     if( hdr->dim[j].size != hdr0->dim[j].size )
456                         CV_Error( CV_StsUnmatchedSizes,
457                                   "Dimension sizes are the same for all arrays" );
458             }
459         }
460         else
461             hdr0 = hdr;
462 
463         step = CV_ELEM_SIZE(hdr->type);
464         for( j = hdr->dims - 1; j > dim0; j-- )
465         {
466             if( step != hdr->dim[j].step )
467                 break;
468             step *= hdr->dim[j].size;
469         }
470 
471         if( j == dim0 && step > INT_MAX )
472             j++;
473 
474         if( j > dim0 )
475             dim0 = j;
476 
477         iterator->hdr[i] = (CvMatND*)hdr;
478         iterator->ptr[i] = (uchar*)hdr->data.ptr;
479     }
480 
481     size = 1;
482     for( j = hdr0->dims - 1; j > dim0; j-- )
483         size *= hdr0->dim[j].size;
484 
485     dims = dim0 + 1;
486     iterator->dims = dims;
487     iterator->count = count;
488     iterator->size = cvSize(size,1);
489 
490     for( i = 0; i < dims; i++ )
491         iterator->stack[i] = hdr0->dim[i].size;
492 
493     return dims;
494 }
495 
496 
497 // returns zero value if iteration is finished, non-zero otherwise
cvNextNArraySlice(CvNArrayIterator * iterator)498 CV_IMPL int cvNextNArraySlice( CvNArrayIterator* iterator )
499 {
500     assert( iterator != 0 );
501     int i, dims;
502 
503     for( dims = iterator->dims; dims > 0; dims-- )
504     {
505         for( i = 0; i < iterator->count; i++ )
506             iterator->ptr[i] += iterator->hdr[i]->dim[dims-1].step;
507 
508         if( --iterator->stack[dims-1] > 0 )
509             break;
510 
511         const int size = iterator->hdr[0]->dim[dims-1].size;
512 
513         for( i = 0; i < iterator->count; i++ )
514             iterator->ptr[i] -= (size_t)size*iterator->hdr[i]->dim[dims-1].step;
515 
516         iterator->stack[dims-1] = size;
517     }
518 
519     return dims > 0;
520 }
521 
522 
523 /****************************************************************************************\
524 *                            CvSparseMat creation and basic operations                   *
525 \****************************************************************************************/
526 
527 
528 // Creates CvMatND and underlying data
529 CV_IMPL CvSparseMat*
cvCreateSparseMat(int dims,const int * sizes,int type)530 cvCreateSparseMat( int dims, const int* sizes, int type )
531 {
532     type = CV_MAT_TYPE( type );
533     int pix_size1 = CV_ELEM_SIZE1(type);
534     int pix_size = pix_size1*CV_MAT_CN(type);
535     int i, size;
536     CvMemStorage* storage;
537 
538     if( pix_size == 0 )
539         CV_Error( CV_StsUnsupportedFormat, "invalid array data type" );
540 
541     if( dims <= 0 || dims > CV_MAX_DIM )
542         CV_Error( CV_StsOutOfRange, "bad number of dimensions" );
543 
544     if( !sizes )
545         CV_Error( CV_StsNullPtr, "NULL <sizes> pointer" );
546 
547     for( i = 0; i < dims; i++ )
548     {
549         if( sizes[i] <= 0 )
550             CV_Error( CV_StsBadSize, "one of dimension sizes is non-positive" );
551     }
552 
553     CvSparseMat* arr = (CvSparseMat*)cvAlloc(sizeof(*arr)+MAX(0,dims-CV_MAX_DIM)*sizeof(arr->size[0]));
554 
555     arr->type = CV_SPARSE_MAT_MAGIC_VAL | type;
556     arr->dims = dims;
557     arr->refcount = 0;
558     arr->hdr_refcount = 1;
559     memcpy( arr->size, sizes, dims*sizeof(sizes[0]));
560 
561     arr->valoffset = (int)cvAlign(sizeof(CvSparseNode), pix_size1);
562     arr->idxoffset = (int)cvAlign(arr->valoffset + pix_size, sizeof(int));
563     size = (int)cvAlign(arr->idxoffset + dims*sizeof(int), sizeof(CvSetElem));
564 
565     storage = cvCreateMemStorage( CV_SPARSE_MAT_BLOCK );
566     arr->heap = cvCreateSet( 0, sizeof(CvSet), size, storage );
567 
568     arr->hashsize = CV_SPARSE_HASH_SIZE0;
569     size = arr->hashsize*sizeof(arr->hashtable[0]);
570 
571     arr->hashtable = (void**)cvAlloc( size );
572     memset( arr->hashtable, 0, size );
573 
574     return arr;
575 }
576 
577 
578 // Creates CvMatND and underlying data
579 CV_IMPL void
cvReleaseSparseMat(CvSparseMat ** array)580 cvReleaseSparseMat( CvSparseMat** array )
581 {
582     if( !array )
583         CV_Error( CV_HeaderIsNull, "" );
584 
585     if( *array )
586     {
587         CvSparseMat* arr = *array;
588 
589         if( !CV_IS_SPARSE_MAT_HDR(arr) )
590             CV_Error( CV_StsBadFlag, "" );
591 
592         *array = 0;
593 
594         CvMemStorage* storage = arr->heap->storage;
595         cvReleaseMemStorage( &storage );
596         cvFree( &arr->hashtable );
597         cvFree( &arr );
598     }
599 }
600 
601 
602 // Creates CvMatND and underlying data
603 CV_IMPL CvSparseMat*
cvCloneSparseMat(const CvSparseMat * src)604 cvCloneSparseMat( const CvSparseMat* src )
605 {
606     if( !CV_IS_SPARSE_MAT_HDR(src) )
607         CV_Error( CV_StsBadArg, "Invalid sparse array header" );
608 
609     CvSparseMat* dst = cvCreateSparseMat( src->dims, src->size, src->type );
610     cvCopy( src, dst );
611     return dst;
612 }
613 
614 
615 CvSparseNode*
cvInitSparseMatIterator(const CvSparseMat * mat,CvSparseMatIterator * iterator)616 cvInitSparseMatIterator( const CvSparseMat* mat, CvSparseMatIterator* iterator )
617 {
618     CvSparseNode* node = 0;
619     int idx;
620 
621     if( !CV_IS_SPARSE_MAT( mat ))
622         CV_Error( CV_StsBadArg, "Invalid sparse matrix header" );
623 
624     if( !iterator )
625         CV_Error( CV_StsNullPtr, "NULL iterator pointer" );
626 
627     iterator->mat = (CvSparseMat*)mat;
628     iterator->node = 0;
629 
630     for( idx = 0; idx < mat->hashsize; idx++ )
631         if( mat->hashtable[idx] )
632         {
633             node = iterator->node = (CvSparseNode*)mat->hashtable[idx];
634             break;
635         }
636 
637     iterator->curidx = idx;
638     return node;
639 }
640 
641 #define ICV_SPARSE_MAT_HASH_MULTIPLIER  cv::SparseMat::HASH_SCALE
642 
643 static uchar*
icvGetNodePtr(CvSparseMat * mat,const int * idx,int * _type,int create_node,unsigned * precalc_hashval)644 icvGetNodePtr( CvSparseMat* mat, const int* idx, int* _type,
645                int create_node, unsigned* precalc_hashval )
646 {
647     uchar* ptr = 0;
648     int i, tabidx;
649     unsigned hashval = 0;
650     CvSparseNode *node;
651     assert( CV_IS_SPARSE_MAT( mat ));
652 
653     if( !precalc_hashval )
654     {
655         for( i = 0; i < mat->dims; i++ )
656         {
657             int t = idx[i];
658             if( (unsigned)t >= (unsigned)mat->size[i] )
659                 CV_Error( CV_StsOutOfRange, "One of indices is out of range" );
660             hashval = hashval*ICV_SPARSE_MAT_HASH_MULTIPLIER + t;
661         }
662     }
663     else
664     {
665         hashval = *precalc_hashval;
666     }
667 
668     tabidx = hashval & (mat->hashsize - 1);
669     hashval &= INT_MAX;
670 
671     if( create_node >= -1 )
672     {
673         for( node = (CvSparseNode*)mat->hashtable[tabidx];
674              node != 0; node = node->next )
675         {
676             if( node->hashval == hashval )
677             {
678                 int* nodeidx = CV_NODE_IDX(mat,node);
679                 for( i = 0; i < mat->dims; i++ )
680                     if( idx[i] != nodeidx[i] )
681                         break;
682                 if( i == mat->dims )
683                 {
684                     ptr = (uchar*)CV_NODE_VAL(mat,node);
685                     break;
686                 }
687             }
688         }
689     }
690 
691     if( !ptr && create_node )
692     {
693         if( mat->heap->active_count >= mat->hashsize*CV_SPARSE_HASH_RATIO )
694         {
695             void** newtable;
696             int newsize = MAX( mat->hashsize*2, CV_SPARSE_HASH_SIZE0);
697             int newrawsize = newsize*sizeof(newtable[0]);
698 
699             CvSparseMatIterator iterator;
700             assert( (newsize & (newsize - 1)) == 0 );
701 
702             // resize hash table
703             newtable = (void**)cvAlloc( newrawsize );
704             memset( newtable, 0, newrawsize );
705 
706             node = cvInitSparseMatIterator( mat, &iterator );
707             while( node )
708             {
709                 CvSparseNode* next = cvGetNextSparseNode( &iterator );
710                 int newidx = node->hashval & (newsize - 1);
711                 node->next = (CvSparseNode*)newtable[newidx];
712                 newtable[newidx] = node;
713                 node = next;
714             }
715 
716             cvFree( &mat->hashtable );
717             mat->hashtable = newtable;
718             mat->hashsize = newsize;
719             tabidx = hashval & (newsize - 1);
720         }
721 
722         node = (CvSparseNode*)cvSetNew( mat->heap );
723         node->hashval = hashval;
724         node->next = (CvSparseNode*)mat->hashtable[tabidx];
725         mat->hashtable[tabidx] = node;
726         memcpy(CV_NODE_IDX(mat,node), idx, mat->dims*sizeof(idx[0]));
727         ptr = (uchar*)CV_NODE_VAL(mat,node);
728         if( create_node > 0 )
729             memset( ptr, 0, CV_ELEM_SIZE(mat->type));
730     }
731 
732     if( _type )
733         *_type = CV_MAT_TYPE(mat->type);
734 
735     return ptr;
736 }
737 
738 
739 static void
icvDeleteNode(CvSparseMat * mat,const int * idx,unsigned * precalc_hashval)740 icvDeleteNode( CvSparseMat* mat, const int* idx, unsigned* precalc_hashval )
741 {
742     int i, tabidx;
743     unsigned hashval = 0;
744     CvSparseNode *node, *prev = 0;
745     assert( CV_IS_SPARSE_MAT( mat ));
746 
747     if( !precalc_hashval )
748     {
749         for( i = 0; i < mat->dims; i++ )
750         {
751             int t = idx[i];
752             if( (unsigned)t >= (unsigned)mat->size[i] )
753                 CV_Error( CV_StsOutOfRange, "One of indices is out of range" );
754             hashval = hashval*ICV_SPARSE_MAT_HASH_MULTIPLIER + t;
755         }
756     }
757     else
758     {
759         hashval = *precalc_hashval;
760     }
761 
762     tabidx = hashval & (mat->hashsize - 1);
763     hashval &= INT_MAX;
764 
765     for( node = (CvSparseNode*)mat->hashtable[tabidx];
766          node != 0; prev = node, node = node->next )
767     {
768         if( node->hashval == hashval )
769         {
770             int* nodeidx = CV_NODE_IDX(mat,node);
771             for( i = 0; i < mat->dims; i++ )
772                 if( idx[i] != nodeidx[i] )
773                     break;
774             if( i == mat->dims )
775                 break;
776         }
777     }
778 
779     if( node )
780     {
781         if( prev )
782             prev->next = node->next;
783         else
784             mat->hashtable[tabidx] = node->next;
785         cvSetRemoveByPtr( mat->heap, node );
786     }
787 }
788 
789 
790 /****************************************************************************************\
791 *                          Common for multiple array types operations                    *
792 \****************************************************************************************/
793 
794 // Allocates underlying array data
795 CV_IMPL void
cvCreateData(CvArr * arr)796 cvCreateData( CvArr* arr )
797 {
798     if( CV_IS_MAT_HDR_Z( arr ))
799     {
800         size_t step, total_size;
801         CvMat* mat = (CvMat*)arr;
802         step = mat->step;
803 
804         if( mat->rows == 0 || mat->cols == 0 )
805             return;
806 
807         if( mat->data.ptr != 0 )
808             CV_Error( CV_StsError, "Data is already allocated" );
809 
810         if( step == 0 )
811             step = CV_ELEM_SIZE(mat->type)*mat->cols;
812 
813         int64 _total_size = (int64)step*mat->rows + sizeof(int) + CV_MALLOC_ALIGN;
814         total_size = (size_t)_total_size;
815         if(_total_size != (int64)total_size)
816             CV_Error(CV_StsNoMem, "Too big buffer is allocated" );
817         mat->refcount = (int*)cvAlloc( (size_t)total_size );
818         mat->data.ptr = (uchar*)cvAlignPtr( mat->refcount + 1, CV_MALLOC_ALIGN );
819         *mat->refcount = 1;
820     }
821     else if( CV_IS_IMAGE_HDR(arr))
822     {
823         IplImage* img = (IplImage*)arr;
824 
825         if( img->imageData != 0 )
826             CV_Error( CV_StsError, "Data is already allocated" );
827 
828         if( !CvIPL.allocateData )
829         {
830             const int64 imageSize_tmp = (int64)img->widthStep*(int64)img->height;
831             if( (int64)img->imageSize != imageSize_tmp )
832                 CV_Error( CV_StsNoMem, "Overflow for imageSize" );
833             img->imageData = img->imageDataOrigin =
834                         (char*)cvAlloc( (size_t)img->imageSize );
835         }
836         else
837         {
838             int depth = img->depth;
839             int width = img->width;
840 
841             if( img->depth == IPL_DEPTH_32F || img->depth == IPL_DEPTH_64F )
842             {
843                 img->width *= img->depth == IPL_DEPTH_32F ? sizeof(float) : sizeof(double);
844                 img->depth = IPL_DEPTH_8U;
845             }
846 
847             CvIPL.allocateData( img, 0, 0 );
848 
849             img->width = width;
850             img->depth = depth;
851         }
852     }
853     else if( CV_IS_MATND_HDR( arr ))
854     {
855         CvMatND* mat = (CvMatND*)arr;
856         size_t total_size = CV_ELEM_SIZE(mat->type);
857 
858         if( mat->dim[0].size == 0 )
859             return;
860 
861         if( mat->data.ptr != 0 )
862             CV_Error( CV_StsError, "Data is already allocated" );
863 
864         if( CV_IS_MAT_CONT( mat->type ))
865         {
866             total_size = (size_t)mat->dim[0].size*(mat->dim[0].step != 0 ?
867                          (size_t)mat->dim[0].step : total_size);
868         }
869         else
870         {
871             int i;
872             for( i = mat->dims - 1; i >= 0; i-- )
873             {
874                 size_t size = (size_t)mat->dim[i].step*mat->dim[i].size;
875 
876                 if( total_size < size )
877                     total_size = size;
878             }
879         }
880 
881         mat->refcount = (int*)cvAlloc( total_size +
882                                         sizeof(int) + CV_MALLOC_ALIGN );
883         mat->data.ptr = (uchar*)cvAlignPtr( mat->refcount + 1, CV_MALLOC_ALIGN );
884         *mat->refcount = 1;
885     }
886     else
887         CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
888 }
889 
890 
891 // Assigns external data to array
892 CV_IMPL void
cvSetData(CvArr * arr,void * data,int step)893 cvSetData( CvArr* arr, void* data, int step )
894 {
895     int pix_size, min_step;
896 
897     if( CV_IS_MAT_HDR(arr) || CV_IS_MATND_HDR(arr) )
898         cvReleaseData( arr );
899 
900     if( CV_IS_MAT_HDR( arr ))
901     {
902         CvMat* mat = (CvMat*)arr;
903 
904         int type = CV_MAT_TYPE(mat->type);
905         pix_size = CV_ELEM_SIZE(type);
906         min_step = mat->cols*pix_size;
907 
908         if( step != CV_AUTOSTEP && step != 0 )
909         {
910             if( step < min_step && data != 0 )
911                 CV_Error( CV_BadStep, "" );
912             mat->step = step;
913         }
914         else
915             mat->step = min_step;
916 
917         mat->data.ptr = (uchar*)data;
918         mat->type = CV_MAT_MAGIC_VAL | type |
919                     (mat->rows == 1 || mat->step == min_step ? CV_MAT_CONT_FLAG : 0);
920         icvCheckHuge( mat );
921     }
922     else if( CV_IS_IMAGE_HDR( arr ))
923     {
924         IplImage* img = (IplImage*)arr;
925 
926         pix_size = ((img->depth & 255) >> 3)*img->nChannels;
927         min_step = img->width*pix_size;
928 
929         if( step != CV_AUTOSTEP && img->height > 1 )
930         {
931             if( step < min_step && data != 0 )
932                 CV_Error( CV_BadStep, "" );
933             img->widthStep = step;
934         }
935         else
936         {
937             img->widthStep = min_step;
938         }
939 
940         const int64 imageSize_tmp = (int64)img->widthStep*(int64)img->height;
941         img->imageSize = (int)imageSize_tmp;
942         if( (int64)img->imageSize != imageSize_tmp )
943             CV_Error( CV_StsNoMem, "Overflow for imageSize" );
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 = cvSize(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 = {0, 0};
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 *                      Operations on CvScalar and accessing array elements               *
1455 \****************************************************************************************/
1456 
1457 // Converts CvScalar to specified type
1458 CV_IMPL void
cvScalarToRawData(const CvScalar * scalar,void * data,int type,int extend_to_12)1459 cvScalarToRawData( const CvScalar* scalar, void* data, int type, int extend_to_12 )
1460 {
1461     type = CV_MAT_TYPE(type);
1462     int cn = CV_MAT_CN( type );
1463     int depth = type & CV_MAT_DEPTH_MASK;
1464 
1465     assert( scalar && data );
1466     if( (unsigned)(cn - 1) >= 4 )
1467         CV_Error( CV_StsOutOfRange, "The number of channels must be 1, 2, 3 or 4" );
1468 
1469     switch( depth )
1470     {
1471     case CV_8UC1:
1472         while( cn-- )
1473         {
1474             int t = cvRound( scalar->val[cn] );
1475             ((uchar*)data)[cn] = cv::saturate_cast<uchar>(t);
1476         }
1477         break;
1478     case CV_8SC1:
1479         while( cn-- )
1480         {
1481             int t = cvRound( scalar->val[cn] );
1482             ((char*)data)[cn] = cv::saturate_cast<schar>(t);
1483         }
1484         break;
1485     case CV_16UC1:
1486         while( cn-- )
1487         {
1488             int t = cvRound( scalar->val[cn] );
1489             ((ushort*)data)[cn] = cv::saturate_cast<ushort>(t);
1490         }
1491         break;
1492     case CV_16SC1:
1493         while( cn-- )
1494         {
1495             int t = cvRound( scalar->val[cn] );
1496             ((short*)data)[cn] = cv::saturate_cast<short>(t);
1497         }
1498         break;
1499     case CV_32SC1:
1500         while( cn-- )
1501             ((int*)data)[cn] = cvRound( scalar->val[cn] );
1502         break;
1503     case CV_32FC1:
1504         while( cn-- )
1505             ((float*)data)[cn] = (float)(scalar->val[cn]);
1506         break;
1507     case CV_64FC1:
1508         while( cn-- )
1509             ((double*)data)[cn] = (double)(scalar->val[cn]);
1510         break;
1511     default:
1512         assert(0);
1513         CV_Error( CV_BadDepth, "" );
1514     }
1515 
1516     if( extend_to_12 )
1517     {
1518         int pix_size = CV_ELEM_SIZE(type);
1519         int offset = CV_ELEM_SIZE1(depth)*12;
1520 
1521         do
1522         {
1523             offset -= pix_size;
1524             memcpy((char*)data + offset, data, pix_size);
1525         }
1526         while( offset > pix_size );
1527     }
1528 }
1529 
1530 
1531 // Converts data of specified type to CvScalar
1532 CV_IMPL void
cvRawDataToScalar(const void * data,int flags,CvScalar * scalar)1533 cvRawDataToScalar( const void* data, int flags, CvScalar* scalar )
1534 {
1535     int cn = CV_MAT_CN( flags );
1536 
1537     assert( scalar && data );
1538 
1539     if( (unsigned)(cn - 1) >= 4 )
1540         CV_Error( CV_StsOutOfRange, "The number of channels must be 1, 2, 3 or 4" );
1541 
1542     memset( scalar->val, 0, sizeof(scalar->val));
1543 
1544     switch( CV_MAT_DEPTH( flags ))
1545     {
1546     case CV_8U:
1547         while( cn-- )
1548             scalar->val[cn] = CV_8TO32F(((uchar*)data)[cn]);
1549         break;
1550     case CV_8S:
1551         while( cn-- )
1552             scalar->val[cn] = CV_8TO32F(((char*)data)[cn]);
1553         break;
1554     case CV_16U:
1555         while( cn-- )
1556             scalar->val[cn] = ((ushort*)data)[cn];
1557         break;
1558     case CV_16S:
1559         while( cn-- )
1560             scalar->val[cn] = ((short*)data)[cn];
1561         break;
1562     case CV_32S:
1563         while( cn-- )
1564             scalar->val[cn] = ((int*)data)[cn];
1565         break;
1566     case CV_32F:
1567         while( cn-- )
1568             scalar->val[cn] = ((float*)data)[cn];
1569         break;
1570     case CV_64F:
1571         while( cn-- )
1572             scalar->val[cn] = ((double*)data)[cn];
1573         break;
1574     default:
1575         assert(0);
1576         CV_Error( CV_BadDepth, "" );
1577     }
1578 }
1579 
1580 
icvGetReal(const void * data,int type)1581 static double icvGetReal( const void* data, int type )
1582 {
1583     switch( type )
1584     {
1585     case CV_8U:
1586         return *(uchar*)data;
1587     case CV_8S:
1588         return *(char*)data;
1589     case CV_16U:
1590         return *(ushort*)data;
1591     case CV_16S:
1592         return *(short*)data;
1593     case CV_32S:
1594         return *(int*)data;
1595     case CV_32F:
1596         return *(float*)data;
1597     case CV_64F:
1598         return *(double*)data;
1599     }
1600 
1601     return 0;
1602 }
1603 
1604 
icvSetReal(double value,const void * data,int type)1605 static void icvSetReal( double value, const void* data, int type )
1606 {
1607     if( type < CV_32F )
1608     {
1609         int ivalue = cvRound(value);
1610         switch( type )
1611         {
1612         case CV_8U:
1613             *(uchar*)data = cv::saturate_cast<uchar>(ivalue);
1614             break;
1615         case CV_8S:
1616             *(schar*)data = cv::saturate_cast<schar>(ivalue);
1617             break;
1618         case CV_16U:
1619             *(ushort*)data = cv::saturate_cast<ushort>(ivalue);
1620             break;
1621         case CV_16S:
1622             *(short*)data = cv::saturate_cast<short>(ivalue);
1623             break;
1624         case CV_32S:
1625             *(int*)data = cv::saturate_cast<int>(ivalue);
1626             break;
1627         }
1628     }
1629     else
1630     {
1631         switch( type )
1632         {
1633         case CV_32F:
1634             *(float*)data = (float)value;
1635             break;
1636         case CV_64F:
1637             *(double*)data = value;
1638             break;
1639         }
1640     }
1641 }
1642 
1643 
1644 // Returns pointer to specified element of array (linear index is used)
1645 CV_IMPL  uchar*
cvPtr1D(const CvArr * arr,int idx,int * _type)1646 cvPtr1D( const CvArr* arr, int idx, int* _type )
1647 {
1648     uchar* ptr = 0;
1649     if( CV_IS_MAT( arr ))
1650     {
1651         CvMat* mat = (CvMat*)arr;
1652 
1653         int type = CV_MAT_TYPE(mat->type);
1654         int pix_size = CV_ELEM_SIZE(type);
1655 
1656         if( _type )
1657             *_type = type;
1658 
1659         // the first part is mul-free sufficient check
1660         // that the index is within the matrix
1661         if( (unsigned)idx >= (unsigned)(mat->rows + mat->cols - 1) &&
1662             (unsigned)idx >= (unsigned)(mat->rows*mat->cols))
1663             CV_Error( CV_StsOutOfRange, "index is out of range" );
1664 
1665         if( CV_IS_MAT_CONT(mat->type))
1666         {
1667             ptr = mat->data.ptr + (size_t)idx*pix_size;
1668         }
1669         else
1670         {
1671             int row, col;
1672             if( mat->cols == 1 )
1673                 row = idx, col = 0;
1674             else
1675                 row = idx/mat->cols, col = idx - row*mat->cols;
1676             ptr = mat->data.ptr + (size_t)row*mat->step + col*pix_size;
1677         }
1678     }
1679     else if( CV_IS_IMAGE_HDR( arr ))
1680     {
1681         IplImage* img = (IplImage*)arr;
1682         int width = !img->roi ? img->width : img->roi->width;
1683         int y = idx/width, x = idx - y*width;
1684 
1685         ptr = cvPtr2D( arr, y, x, _type );
1686     }
1687     else if( CV_IS_MATND( arr ))
1688     {
1689         CvMatND* mat = (CvMatND*)arr;
1690         int j, type = CV_MAT_TYPE(mat->type);
1691         size_t size = mat->dim[0].size;
1692 
1693         if( _type )
1694             *_type = type;
1695 
1696         for( j = 1; j < mat->dims; j++ )
1697             size *= mat->dim[j].size;
1698 
1699         if((unsigned)idx >= (unsigned)size )
1700             CV_Error( CV_StsOutOfRange, "index is out of range" );
1701 
1702         if( CV_IS_MAT_CONT(mat->type))
1703         {
1704             int pix_size = CV_ELEM_SIZE(type);
1705             ptr = mat->data.ptr + (size_t)idx*pix_size;
1706         }
1707         else
1708         {
1709             ptr = mat->data.ptr;
1710             for( j = mat->dims - 1; j >= 0; j-- )
1711             {
1712                 int sz = mat->dim[j].size;
1713                 if( sz )
1714                 {
1715                     int t = idx/sz;
1716                     ptr += (idx - t*sz)*mat->dim[j].step;
1717                     idx = t;
1718                 }
1719             }
1720         }
1721     }
1722     else if( CV_IS_SPARSE_MAT( arr ))
1723     {
1724         CvSparseMat* m = (CvSparseMat*)arr;
1725         if( m->dims == 1 )
1726             ptr = icvGetNodePtr( (CvSparseMat*)arr, &idx, _type, 1, 0 );
1727         else
1728         {
1729             int i, n = m->dims;
1730             CV_DbgAssert( n <= CV_MAX_DIM );
1731             int _idx[CV_MAX_DIM];
1732 
1733             for( i = n - 1; i >= 0; i-- )
1734             {
1735                 int t = idx / m->size[i];
1736                 _idx[i] = idx - t*m->size[i];
1737                 idx = t;
1738             }
1739             ptr = icvGetNodePtr( (CvSparseMat*)arr, _idx, _type, 1, 0 );
1740         }
1741     }
1742     else
1743     {
1744         CV_Error( CV_StsBadArg, "unrecognized or unsupported array type" );
1745     }
1746 
1747     return ptr;
1748 }
1749 
1750 
1751 // Returns pointer to specified element of 2d array
1752 CV_IMPL  uchar*
cvPtr2D(const CvArr * arr,int y,int x,int * _type)1753 cvPtr2D( const CvArr* arr, int y, int x, int* _type )
1754 {
1755     uchar* ptr = 0;
1756     if( CV_IS_MAT( arr ))
1757     {
1758         CvMat* mat = (CvMat*)arr;
1759         int type;
1760 
1761         if( (unsigned)y >= (unsigned)(mat->rows) ||
1762             (unsigned)x >= (unsigned)(mat->cols) )
1763             CV_Error( CV_StsOutOfRange, "index is out of range" );
1764 
1765         type = CV_MAT_TYPE(mat->type);
1766         if( _type )
1767             *_type = type;
1768 
1769         ptr = mat->data.ptr + (size_t)y*mat->step + x*CV_ELEM_SIZE(type);
1770     }
1771     else if( CV_IS_IMAGE( arr ))
1772     {
1773         IplImage* img = (IplImage*)arr;
1774         int pix_size = (img->depth & 255) >> 3;
1775         int width, height;
1776         ptr = (uchar*)img->imageData;
1777 
1778         if( img->dataOrder == 0 )
1779             pix_size *= img->nChannels;
1780 
1781         if( img->roi )
1782         {
1783             width = img->roi->width;
1784             height = img->roi->height;
1785 
1786             ptr += img->roi->yOffset*img->widthStep +
1787                    img->roi->xOffset*pix_size;
1788 
1789             if( img->dataOrder )
1790             {
1791                 int coi = img->roi->coi;
1792                 if( !coi )
1793                     CV_Error( CV_BadCOI,
1794                         "COI must be non-null in case of planar images" );
1795                 ptr += (coi - 1)*img->imageSize;
1796             }
1797         }
1798         else
1799         {
1800             width = img->width;
1801             height = img->height;
1802         }
1803 
1804         if( (unsigned)y >= (unsigned)height ||
1805             (unsigned)x >= (unsigned)width )
1806             CV_Error( CV_StsOutOfRange, "index is out of range" );
1807 
1808         ptr += y*img->widthStep + x*pix_size;
1809 
1810         if( _type )
1811         {
1812             int type = IPL2CV_DEPTH(img->depth);
1813             if( type < 0 || (unsigned)(img->nChannels - 1) > 3 )
1814                 CV_Error( CV_StsUnsupportedFormat, "" );
1815 
1816             *_type = CV_MAKETYPE( type, img->nChannels );
1817         }
1818     }
1819     else if( CV_IS_MATND( arr ))
1820     {
1821         CvMatND* mat = (CvMatND*)arr;
1822 
1823         if( mat->dims != 2 ||
1824             (unsigned)y >= (unsigned)(mat->dim[0].size) ||
1825             (unsigned)x >= (unsigned)(mat->dim[1].size) )
1826             CV_Error( CV_StsOutOfRange, "index is out of range" );
1827 
1828         ptr = mat->data.ptr + (size_t)y*mat->dim[0].step + x*mat->dim[1].step;
1829         if( _type )
1830             *_type = CV_MAT_TYPE(mat->type);
1831     }
1832     else if( CV_IS_SPARSE_MAT( arr ))
1833     {
1834         CV_Assert(((CvSparseMat*)arr)->dims == 2);
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 specified 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 = cvScalar();
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 specified 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 = cvScalar();
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 specified 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 = cvScalar();
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 specified 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 = cvScalar();
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 specified 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 specified 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 specified 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 specified 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 specified 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 specified 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 specified 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 specified 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     *image = cvIplImage();
2922 
2923     icvGetColorModel( channels, &colorModel, &channelSeq );
2924     for (int i = 0; i < 4; i++)
2925     {
2926         image->colorModel[i] = colorModel[i];
2927         if (colorModel[i] == 0)
2928             break;
2929     }
2930     for (int i = 0; i < 4; i++)
2931     {
2932         image->channelSeq[i] = channelSeq[i];
2933         if (channelSeq[i] == 0)
2934             break;
2935     }
2936 
2937     if( size.width < 0 || size.height < 0 )
2938         CV_Error( CV_BadROISize, "Bad input roi" );
2939 
2940     if( (depth != (int)IPL_DEPTH_1U && depth != (int)IPL_DEPTH_8U &&
2941          depth != (int)IPL_DEPTH_8S && depth != (int)IPL_DEPTH_16U &&
2942          depth != (int)IPL_DEPTH_16S && depth != (int)IPL_DEPTH_32S &&
2943          depth != (int)IPL_DEPTH_32F && depth != (int)IPL_DEPTH_64F) ||
2944          channels < 0 )
2945         CV_Error( CV_BadDepth, "Unsupported format" );
2946     if( origin != CV_ORIGIN_BL && origin != CV_ORIGIN_TL )
2947         CV_Error( CV_BadOrigin, "Bad input origin" );
2948 
2949     if( align != 4 && align != 8 )
2950         CV_Error( CV_BadAlign, "Bad input align" );
2951 
2952     image->width = size.width;
2953     image->height = size.height;
2954 
2955     if( image->roi )
2956     {
2957         image->roi->coi = 0;
2958         image->roi->xOffset = image->roi->yOffset = 0;
2959         image->roi->width = size.width;
2960         image->roi->height = size.height;
2961     }
2962 
2963     image->nChannels = MAX( channels, 1 );
2964     image->depth = depth;
2965     image->align = align;
2966     image->widthStep = (((image->width * image->nChannels *
2967          (image->depth & ~IPL_DEPTH_SIGN) + 7)/8)+ align - 1) & (~(align - 1));
2968     image->origin = origin;
2969     const int64 imageSize_tmp = (int64)image->widthStep*(int64)image->height;
2970     image->imageSize = (int)imageSize_tmp;
2971     if( (int64)image->imageSize != imageSize_tmp )
2972         CV_Error( CV_StsNoMem, "Overflow for imageSize" );
2973 
2974     return image;
2975 }
2976 
2977 
2978 CV_IMPL void
cvReleaseImageHeader(IplImage ** image)2979 cvReleaseImageHeader( IplImage** image )
2980 {
2981     if( !image )
2982         CV_Error( CV_StsNullPtr, "" );
2983 
2984     if( *image )
2985     {
2986         IplImage* img = *image;
2987         *image = 0;
2988 
2989         if( !CvIPL.deallocate )
2990         {
2991             cvFree( &img->roi );
2992             cvFree( &img );
2993         }
2994         else
2995         {
2996             CvIPL.deallocate( img, IPL_IMAGE_HEADER | IPL_IMAGE_ROI );
2997         }
2998     }
2999 }
3000 
3001 
3002 CV_IMPL void
cvReleaseImage(IplImage ** image)3003 cvReleaseImage( IplImage ** image )
3004 {
3005     if( !image )
3006         CV_Error( CV_StsNullPtr, "" );
3007 
3008     if( *image )
3009     {
3010         IplImage* img = *image;
3011         *image = 0;
3012 
3013         cvReleaseData( img );
3014         cvReleaseImageHeader( &img );
3015     }
3016 }
3017 
3018 
3019 CV_IMPL void
cvSetImageROI(IplImage * image,CvRect rect)3020 cvSetImageROI( IplImage* image, CvRect rect )
3021 {
3022     if( !image )
3023         CV_Error( CV_HeaderIsNull, "" );
3024 
3025     // allow zero ROI width or height
3026     CV_Assert( rect.width >= 0 && rect.height >= 0 &&
3027                rect.x < image->width && rect.y < image->height &&
3028                rect.x + rect.width >= (int)(rect.width > 0) &&
3029                rect.y + rect.height >= (int)(rect.height > 0) );
3030 
3031     rect.width += rect.x;
3032     rect.height += rect.y;
3033 
3034     rect.x = std::max(rect.x, 0);
3035     rect.y = std::max(rect.y, 0);
3036     rect.width = std::min(rect.width, image->width);
3037     rect.height = std::min(rect.height, image->height);
3038 
3039     rect.width -= rect.x;
3040     rect.height -= rect.y;
3041 
3042     if( image->roi )
3043     {
3044         image->roi->xOffset = rect.x;
3045         image->roi->yOffset = rect.y;
3046         image->roi->width = rect.width;
3047         image->roi->height = rect.height;
3048     }
3049     else
3050         image->roi = icvCreateROI( 0, rect.x, rect.y, rect.width, rect.height );
3051 }
3052 
3053 
3054 CV_IMPL void
cvResetImageROI(IplImage * image)3055 cvResetImageROI( IplImage* image )
3056 {
3057     if( !image )
3058         CV_Error( CV_HeaderIsNull, "" );
3059 
3060     if( image->roi )
3061     {
3062         if( !CvIPL.deallocate )
3063         {
3064             cvFree( &image->roi );
3065         }
3066         else
3067         {
3068             CvIPL.deallocate( image, IPL_IMAGE_ROI );
3069             image->roi = 0;
3070         }
3071     }
3072 }
3073 
3074 
3075 CV_IMPL CvRect
cvGetImageROI(const IplImage * img)3076 cvGetImageROI( const IplImage* img )
3077 {
3078     CvRect rect = {0, 0, 0, 0};
3079     if( !img )
3080         CV_Error( CV_StsNullPtr, "Null pointer to image" );
3081 
3082     if( img->roi )
3083         rect = cvRect( img->roi->xOffset, img->roi->yOffset,
3084                        img->roi->width, img->roi->height );
3085     else
3086         rect = cvRect( 0, 0, img->width, img->height );
3087 
3088     return rect;
3089 }
3090 
3091 
3092 CV_IMPL void
cvSetImageCOI(IplImage * image,int coi)3093 cvSetImageCOI( IplImage* image, int coi )
3094 {
3095     if( !image )
3096         CV_Error( CV_HeaderIsNull, "" );
3097 
3098     if( (unsigned)coi > (unsigned)(image->nChannels) )
3099         CV_Error( CV_BadCOI, "" );
3100 
3101     if( image->roi || coi != 0 )
3102     {
3103         if( image->roi )
3104         {
3105             image->roi->coi = coi;
3106         }
3107         else
3108         {
3109             image->roi = icvCreateROI( coi, 0, 0, image->width, image->height );
3110         }
3111     }
3112 }
3113 
3114 
3115 CV_IMPL int
cvGetImageCOI(const IplImage * image)3116 cvGetImageCOI( const IplImage* image )
3117 {
3118     if( !image )
3119         CV_Error( CV_HeaderIsNull, "" );
3120 
3121     return image->roi ? image->roi->coi : 0;
3122 }
3123 
3124 
3125 CV_IMPL IplImage*
cvCloneImage(const IplImage * src)3126 cvCloneImage( const IplImage* src )
3127 {
3128     IplImage* dst = 0;
3129 
3130     if( !CV_IS_IMAGE_HDR( src ))
3131         CV_Error( CV_StsBadArg, "Bad image header" );
3132 
3133     if( !CvIPL.cloneImage )
3134     {
3135         dst = (IplImage*)cvAlloc( sizeof(*dst));
3136 
3137         memcpy( dst, src, sizeof(*src));
3138         dst->nSize = sizeof(IplImage);
3139         dst->imageData = dst->imageDataOrigin = 0;
3140         dst->roi = 0;
3141 
3142         if( src->roi )
3143         {
3144             dst->roi = icvCreateROI( src->roi->coi, src->roi->xOffset,
3145                           src->roi->yOffset, src->roi->width, src->roi->height );
3146         }
3147 
3148         if( src->imageData )
3149         {
3150             int size = src->imageSize;
3151             cvCreateData( dst );
3152             memcpy( dst->imageData, src->imageData, size );
3153         }
3154     }
3155     else
3156         dst = CvIPL.cloneImage( src );
3157 
3158     return dst;
3159 }
3160 
3161 
3162 /****************************************************************************************\
3163 *                            Additional operations on CvTermCriteria                     *
3164 \****************************************************************************************/
3165 
3166 CV_IMPL CvTermCriteria
cvCheckTermCriteria(CvTermCriteria criteria,double default_eps,int default_max_iters)3167 cvCheckTermCriteria( CvTermCriteria criteria, double default_eps,
3168                      int default_max_iters )
3169 {
3170     CvTermCriteria crit;
3171 
3172     crit.type = CV_TERMCRIT_ITER|CV_TERMCRIT_EPS;
3173     crit.max_iter = default_max_iters;
3174     crit.epsilon = (float)default_eps;
3175 
3176     if( (criteria.type & ~(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER)) != 0 )
3177         CV_Error( CV_StsBadArg,
3178                   "Unknown type of term criteria" );
3179 
3180     if( (criteria.type & CV_TERMCRIT_ITER) != 0 )
3181     {
3182         if( criteria.max_iter <= 0 )
3183             CV_Error( CV_StsBadArg,
3184                   "Iterations flag is set and maximum number of iterations is <= 0" );
3185         crit.max_iter = criteria.max_iter;
3186     }
3187 
3188     if( (criteria.type & CV_TERMCRIT_EPS) != 0 )
3189     {
3190         if( criteria.epsilon < 0 )
3191             CV_Error( CV_StsBadArg, "Accuracy flag is set and epsilon is < 0" );
3192 
3193         crit.epsilon = criteria.epsilon;
3194     }
3195 
3196     if( (criteria.type & (CV_TERMCRIT_EPS | CV_TERMCRIT_ITER)) == 0 )
3197         CV_Error( CV_StsBadArg,
3198                   "Neither accuracy nor maximum iterations "
3199                   "number flags are set in criteria type" );
3200 
3201     crit.epsilon = (float)MAX( 0, crit.epsilon );
3202     crit.max_iter = MAX( 1, crit.max_iter );
3203 
3204     return crit;
3205 }
3206 
3207 namespace cv
3208 {
3209 
operator ()(CvMat * obj) const3210 void DefaultDeleter<CvMat>::operator ()(CvMat* obj) const { cvReleaseMat(&obj); }
operator ()(IplImage * obj) const3211 void DefaultDeleter<IplImage>::operator ()(IplImage* obj) const { cvReleaseImage(&obj); }
operator ()(CvMatND * obj) const3212 void DefaultDeleter<CvMatND>::operator ()(CvMatND* obj) const { cvReleaseMatND(&obj); }
operator ()(CvSparseMat * obj) const3213 void DefaultDeleter<CvSparseMat>::operator ()(CvSparseMat* obj) const { cvReleaseSparseMat(&obj); }
operator ()(CvMemStorage * obj) const3214 void DefaultDeleter<CvMemStorage>::operator ()(CvMemStorage* obj) const { cvReleaseMemStorage(&obj); }
3215 
3216 } // cv::
3217 
3218 
3219 /* universal functions */
3220 CV_IMPL void
cvRelease(void ** struct_ptr)3221 cvRelease( void** struct_ptr )
3222 {
3223     if( !struct_ptr )
3224         CV_Error( CV_StsNullPtr, "NULL double pointer" );
3225 
3226     if( *struct_ptr )
3227     {
3228         if( CV_IS_MAT(*struct_ptr) )
3229             cvReleaseMat((CvMat**)struct_ptr);
3230         else if( CV_IS_IMAGE(*struct_ptr))
3231             cvReleaseImage((IplImage**)struct_ptr);
3232         else
3233             CV_Error( CV_StsError, "Unknown object type" );
3234     }
3235 }
3236 
cvClone(const void * struct_ptr)3237 void* cvClone( const void* struct_ptr )
3238 {
3239     void* ptr = 0;
3240     if( !struct_ptr )
3241         CV_Error( CV_StsNullPtr, "NULL structure pointer" );
3242 
3243     if( CV_IS_MAT(struct_ptr) )
3244         ptr = cvCloneMat((const CvMat*)struct_ptr);
3245     else if( CV_IS_IMAGE(struct_ptr))
3246         ptr = cvCloneImage((const IplImage*)struct_ptr);
3247     else
3248         CV_Error( CV_StsError, "Unknown object type" );
3249     return ptr;
3250 }
3251 
3252 
3253 #endif  // OPENCV_EXCLUDE_C_API
3254 /* End of file. */
3255