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