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