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