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