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