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