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