Update the changelog
[opencv] / cxcore / src / cxcopy.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 basic operations: cvCopy, cvSet
45 //
46 // */
47
48 #include "_cxcore.h"
49
50 /////////////////////////////////////////////////////////////////////////////////////////
51 //                                                                                     //
52 //                                  L/L COPY & SET FUNCTIONS                           //
53 //                                                                                     //
54 /////////////////////////////////////////////////////////////////////////////////////////
55
56
57 IPCVAPI_IMPL( CvStatus, icvCopy_8u_C1R, ( const uchar* src, int srcstep,
58                                           uchar* dst, int dststep, CvSize size ),
59                                           (src, srcstep, dst, dststep, size) )
60 {
61     for( ; size.height--; src += srcstep, dst += dststep )
62         memcpy( dst, src, size.width );
63
64     return  CV_OK;
65 }
66
67
68 static CvStatus CV_STDCALL
69 icvSet_8u_C1R( uchar* dst, int dst_step, CvSize size,
70                const void* scalar, int pix_size )
71 {
72     int copy_len = 12*pix_size;
73     uchar* dst_limit = dst + size.width;
74     
75     if( size.height-- )
76     {
77         while( dst + copy_len <= dst_limit )
78         {
79             memcpy( dst, scalar, copy_len );
80             dst += copy_len;
81         }
82
83         memcpy( dst, scalar, dst_limit - dst );
84     }
85
86     if( size.height )
87     {
88         dst = dst_limit - size.width + dst_step;
89
90         for( ; size.height--; dst += dst_step )
91             memcpy( dst, dst - dst_step, size.width );
92     }
93
94     return CV_OK;
95 }
96
97
98 /////////////////////////////////////////////////////////////////////////////////////////
99 //                                                                                     //
100 //                                L/L COPY WITH MASK FUNCTIONS                         //
101 //                                                                                     //
102 /////////////////////////////////////////////////////////////////////////////////////////
103
104
105 #define ICV_DEF_COPY_MASK_C1_CASE( type )   \
106     for( i = 0; i <= size.width-2; i += 2 ) \
107     {                                       \
108         if( mask[i] )                       \
109             dst[i] = src[i];                \
110         if( mask[i+1] )                     \
111             dst[i+1] = src[i+1];            \
112     }                                       \
113                                             \
114     for( ; i < size.width; i++ )            \
115     {                                       \
116         if( mask[i] )                       \
117             dst[i] = src[i];                \
118     }
119
120 #define ICV_DEF_COPY_MASK_C3_CASE( type )   \
121     for( i = 0; i < size.width; i++ )       \
122         if( mask[i] )                       \
123         {                                   \
124             type t0 = src[i*3];             \
125             type t1 = src[i*3+1];           \
126             type t2 = src[i*3+2];           \
127                                             \
128             dst[i*3] = t0;                  \
129             dst[i*3+1] = t1;                \
130             dst[i*3+2] = t2;                \
131         }
132
133
134
135 #define ICV_DEF_COPY_MASK_C4_CASE( type )   \
136     for( i = 0; i < size.width; i++ )       \
137         if( mask[i] )                       \
138         {                                   \
139             type t0 = src[i*4];             \
140             type t1 = src[i*4+1];           \
141             dst[i*4] = t0;                  \
142             dst[i*4+1] = t1;                \
143                                             \
144             t0 = src[i*4+2];                \
145             t1 = src[i*4+3];                \
146             dst[i*4+2] = t0;                \
147             dst[i*4+3] = t1;                \
148         }
149
150
151 #define ICV_DEF_COPY_MASK_2D( name, type, cn )              \
152 IPCVAPI_IMPL( CvStatus,                                     \
153 name,( const type* src, int srcstep, type* dst, int dststep,\
154        CvSize size, const uchar* mask, int maskstep ),      \
155        (src, srcstep, dst, dststep, size, mask, maskstep))  \
156 {                                                           \
157     srcstep /= sizeof(src[0]); dststep /= sizeof(dst[0]);   \
158     for( ; size.height--; src += srcstep,                   \
159             dst += dststep, mask += maskstep )              \
160     {                                                       \
161         int i;                                              \
162         ICV_DEF_COPY_MASK_C##cn##_CASE( type )              \
163     }                                                       \
164                                                             \
165     return  CV_OK;                                          \
166 }
167
168
169 #define ICV_DEF_SET_MASK_C1_CASE( type )    \
170     for( i = 0; i <= size.width-2; i += 2 ) \
171     {                                       \
172         if( mask[i] )                       \
173             dst[i] = s0;                    \
174         if( mask[i+1] )                     \
175             dst[i+1] = s0;                  \
176     }                                       \
177                                             \
178     for( ; i < size.width; i++ )            \
179     {                                       \
180         if( mask[i] )                       \
181             dst[i] = s0;                    \
182     }
183
184
185 #define ICV_DEF_SET_MASK_C3_CASE( type )    \
186     for( i = 0; i < size.width; i++ )       \
187         if( mask[i] )                       \
188         {                                   \
189             dst[i*3] = s0;                  \
190             dst[i*3+1] = s1;                \
191             dst[i*3+2] = s2;                \
192         }
193
194 #define ICV_DEF_SET_MASK_C4_CASE( type )    \
195     for( i = 0; i < size.width; i++ )       \
196         if( mask[i] )                       \
197         {                                   \
198             dst[i*4] = s0;                  \
199             dst[i*4+1] = s1;                \
200             dst[i*4+2] = s2;                \
201             dst[i*4+3] = s3;                \
202         }
203
204 #define ICV_DEF_SET_MASK_2D( name, type, cn )       \
205 IPCVAPI_IMPL( CvStatus,                             \
206 name,( type* dst, int dststep,                      \
207        const uchar* mask, int maskstep,             \
208        CvSize size, const type* scalar ),           \
209        (dst, dststep, mask, maskstep, size, scalar))\
210 {                                                   \
211     CV_UN_ENTRY_C##cn( type );                      \
212     dststep /= sizeof(dst[0]);                      \
213                                                     \
214     for( ; size.height--; mask += maskstep,         \
215                           dst += dststep )          \
216     {                                               \
217         int i;                                      \
218         ICV_DEF_SET_MASK_C##cn##_CASE( type )       \
219     }                                               \
220                                                     \
221     return CV_OK;                                   \
222 }
223
224
225 ICV_DEF_SET_MASK_2D( icvSet_8u_C1MR, uchar, 1 )
226 ICV_DEF_SET_MASK_2D( icvSet_16s_C1MR, ushort, 1 )
227 ICV_DEF_SET_MASK_2D( icvSet_8u_C3MR, uchar, 3 )
228 ICV_DEF_SET_MASK_2D( icvSet_8u_C4MR, int, 1 )
229 ICV_DEF_SET_MASK_2D( icvSet_16s_C3MR, ushort, 3 )
230 ICV_DEF_SET_MASK_2D( icvSet_16s_C4MR, int64, 1 )
231 ICV_DEF_SET_MASK_2D( icvSet_32f_C3MR, int, 3 )
232 ICV_DEF_SET_MASK_2D( icvSet_32f_C4MR, int, 4 )
233 ICV_DEF_SET_MASK_2D( icvSet_64s_C3MR, int64, 3 )
234 ICV_DEF_SET_MASK_2D( icvSet_64s_C4MR, int64, 4 )
235
236 ICV_DEF_COPY_MASK_2D( icvCopy_8u_C1MR, uchar, 1 )
237 ICV_DEF_COPY_MASK_2D( icvCopy_16s_C1MR, ushort, 1 )
238 ICV_DEF_COPY_MASK_2D( icvCopy_8u_C3MR, uchar, 3 )
239 ICV_DEF_COPY_MASK_2D( icvCopy_8u_C4MR, int, 1 )
240 ICV_DEF_COPY_MASK_2D( icvCopy_16s_C3MR, ushort, 3 )
241 ICV_DEF_COPY_MASK_2D( icvCopy_16s_C4MR, int64, 1 )
242 ICV_DEF_COPY_MASK_2D( icvCopy_32f_C3MR, int, 3 )
243 ICV_DEF_COPY_MASK_2D( icvCopy_32f_C4MR, int, 4 )
244 ICV_DEF_COPY_MASK_2D( icvCopy_64s_C3MR, int64, 3 )
245 ICV_DEF_COPY_MASK_2D( icvCopy_64s_C4MR, int64, 4 )
246
247 #define CV_DEF_INIT_COPYSET_TAB_2D( FUNCNAME, FLAG )                \
248 static void icvInit##FUNCNAME##FLAG##Table( CvBtFuncTable* table )  \
249 {                                                                   \
250     table->fn_2d[1]  = (void*)icv##FUNCNAME##_8u_C1##FLAG;          \
251     table->fn_2d[2]  = (void*)icv##FUNCNAME##_16s_C1##FLAG;         \
252     table->fn_2d[3]  = (void*)icv##FUNCNAME##_8u_C3##FLAG;          \
253     table->fn_2d[4]  = (void*)icv##FUNCNAME##_8u_C4##FLAG;          \
254     table->fn_2d[6]  = (void*)icv##FUNCNAME##_16s_C3##FLAG;         \
255     table->fn_2d[8]  = (void*)icv##FUNCNAME##_16s_C4##FLAG;         \
256     table->fn_2d[12] = (void*)icv##FUNCNAME##_32f_C3##FLAG;         \
257     table->fn_2d[16] = (void*)icv##FUNCNAME##_32f_C4##FLAG;         \
258     table->fn_2d[24] = (void*)icv##FUNCNAME##_64s_C3##FLAG;         \
259     table->fn_2d[32] = (void*)icv##FUNCNAME##_64s_C4##FLAG;         \
260 }
261
262 CV_DEF_INIT_COPYSET_TAB_2D( Set, MR )
263 CV_DEF_INIT_COPYSET_TAB_2D( Copy, MR )
264
265 /////////////////////////////////////////////////////////////////////////////////////////
266 //                                                                                     //
267 //                                H/L COPY & SET FUNCTIONS                             //
268 //                                                                                     //
269 /////////////////////////////////////////////////////////////////////////////////////////
270
271
272 CvCopyMaskFunc
273 icvGetCopyMaskFunc( int elem_size )
274 {
275     static CvBtFuncTable copym_tab;
276     static int inittab = 0;
277
278     if( !inittab )
279     {
280         icvInitCopyMRTable( &copym_tab );
281         inittab = 1;
282     }
283     return (CvCopyMaskFunc)copym_tab.fn_2d[elem_size];
284 }
285
286
287 /* dst = src */
288 CV_IMPL void
289 cvCopy( const void* srcarr, void* dstarr, const void* maskarr )
290 {
291     CV_FUNCNAME( "cvCopy" );
292     
293     __BEGIN__;
294
295     int pix_size;
296     CvMat srcstub, *src = (CvMat*)srcarr;
297     CvMat dststub, *dst = (CvMat*)dstarr;
298     CvSize size;
299
300     if( !CV_IS_MAT(src) || !CV_IS_MAT(dst) )
301     {
302         if( CV_IS_SPARSE_MAT(src) && CV_IS_SPARSE_MAT(dst))
303         {
304             CvSparseMat* src1 = (CvSparseMat*)src;
305             CvSparseMat* dst1 = (CvSparseMat*)dst;
306             CvSparseMatIterator iterator;
307             CvSparseNode* node;
308
309             dst1->dims = src1->dims;
310             memcpy( dst1->size, src1->size, src1->dims*sizeof(src1->size[0]));
311             dst1->valoffset = src1->valoffset;
312             dst1->idxoffset = src1->idxoffset;
313             cvClearSet( dst1->heap );
314
315             if( src1->heap->active_count >= dst1->hashsize*CV_SPARSE_HASH_RATIO )
316             {
317                 CV_CALL( cvFree( &dst1->hashtable ));
318                 dst1->hashsize = src1->hashsize;
319                 CV_CALL( dst1->hashtable =
320                     (void**)cvAlloc( dst1->hashsize*sizeof(dst1->hashtable[0])));
321             }
322
323             memset( dst1->hashtable, 0, dst1->hashsize*sizeof(dst1->hashtable[0]));
324
325             for( node = cvInitSparseMatIterator( src1, &iterator );
326                  node != 0; node = cvGetNextSparseNode( &iterator ))
327             {
328                 CvSparseNode* node_copy = (CvSparseNode*)cvSetNew( dst1->heap );
329                 int tabidx = node->hashval & (dst1->hashsize - 1);
330                 CV_MEMCPY_AUTO( node_copy, node, dst1->heap->elem_size );
331                 node_copy->next = (CvSparseNode*)dst1->hashtable[tabidx];
332                 dst1->hashtable[tabidx] = node_copy;
333             }
334             EXIT;
335         }
336         else if( CV_IS_MATND(src) || CV_IS_MATND(dst) )
337         {
338             CvArr* arrs[] = { src, dst };
339             CvMatND stubs[3];
340             CvNArrayIterator iterator;
341
342             CV_CALL( cvInitNArrayIterator( 2, arrs, maskarr, stubs, &iterator ));
343             pix_size = CV_ELEM_SIZE(iterator.hdr[0]->type);
344
345             if( !maskarr )
346             {
347                 iterator.size.width *= pix_size;
348                 if( iterator.size.width <= CV_MAX_INLINE_MAT_OP_SIZE*(int)sizeof(double))
349                 {
350                     do
351                     {
352                         memcpy( iterator.ptr[1], iterator.ptr[0], iterator.size.width );
353                     }
354                     while( cvNextNArraySlice( &iterator ));
355                 }
356                 else
357                 {
358                     do
359                     {
360                         icvCopy_8u_C1R( iterator.ptr[0], CV_STUB_STEP,
361                                         iterator.ptr[1], CV_STUB_STEP, iterator.size );
362                     }
363                     while( cvNextNArraySlice( &iterator ));
364                 }
365             }
366             else
367             {
368                 CvCopyMaskFunc func = icvGetCopyMaskFunc( pix_size );
369                 if( !func )
370                     CV_ERROR( CV_StsUnsupportedFormat, "" );
371
372                 do
373                 {
374                     func( iterator.ptr[0], CV_STUB_STEP,
375                           iterator.ptr[1], CV_STUB_STEP,
376                           iterator.size,
377                           iterator.ptr[2], CV_STUB_STEP );
378                 }
379                 while( cvNextNArraySlice( &iterator ));
380             }
381             EXIT;
382         }
383         else
384         {
385             int coi1 = 0, coi2 = 0;
386             CV_CALL( src = cvGetMat( src, &srcstub, &coi1 ));
387             CV_CALL( dst = cvGetMat( dst, &dststub, &coi2 ));
388
389             if( coi1 )
390             {
391                 CvArr* planes[] = { 0, 0, 0, 0 };
392
393                 if( maskarr )
394                     CV_ERROR( CV_StsBadArg, "COI + mask are not supported" );
395
396                 planes[coi1-1] = dst;
397                 CV_CALL( cvSplit( src, planes[0], planes[1], planes[2], planes[3] ));
398                 EXIT;
399             }
400             else if( coi2 )
401             {
402                 CvArr* planes[] = { 0, 0, 0, 0 };
403             
404                 if( maskarr )
405                     CV_ERROR( CV_StsBadArg, "COI + mask are not supported" );
406
407                 planes[coi2-1] = src;
408                 CV_CALL( cvMerge( planes[0], planes[1], planes[2], planes[3], dst ));
409                 EXIT;
410             }
411         }
412     }
413
414     if( !CV_ARE_TYPES_EQ( src, dst ))
415         CV_ERROR_FROM_CODE( CV_StsUnmatchedFormats );
416
417     if( !CV_ARE_SIZES_EQ( src, dst ))
418         CV_ERROR_FROM_CODE( CV_StsUnmatchedSizes );
419
420     size = cvGetMatSize( src );
421     pix_size = CV_ELEM_SIZE(src->type);
422
423     if( !maskarr )
424     {
425         int src_step = src->step, dst_step = dst->step;
426         size.width *= pix_size;
427         if( CV_IS_MAT_CONT( src->type & dst->type ) && (src_step == dst_step) && (src_step == src->width * pix_size))
428         {
429             size.width *= size.height;
430
431             if( size.width <= CV_MAX_INLINE_MAT_OP_SIZE*
432                               CV_MAX_INLINE_MAT_OP_SIZE*(int)sizeof(double))
433             {
434                 memcpy( dst->data.ptr, src->data.ptr, size.width );
435                 EXIT;
436             }
437
438             size.height = 1;
439             src_step = dst_step = CV_STUB_STEP;
440         }
441
442         if( src->data.ptr != dst->data.ptr )
443             icvCopy_8u_C1R( src->data.ptr, src_step,
444                             dst->data.ptr, dst_step, size );
445     }
446     else
447     {
448         CvCopyMaskFunc func = icvGetCopyMaskFunc(pix_size);
449         CvMat maskstub, *mask = (CvMat*)maskarr;
450         int src_step = src->step;
451         int dst_step = dst->step;
452         int mask_step;
453
454         if( !CV_IS_MAT( mask ))
455             CV_CALL( mask = cvGetMat( mask, &maskstub ));
456         if( !CV_IS_MASK_ARR( mask ))
457             CV_ERROR( CV_StsBadMask, "" );
458
459         if( !CV_ARE_SIZES_EQ( src, mask ))
460             CV_ERROR( CV_StsUnmatchedSizes, "" );
461
462         mask_step = mask->step;
463         
464         if( CV_IS_MAT_CONT( src->type & dst->type & mask->type ))
465         {
466             size.width *= size.height;
467             size.height = 1;
468             src_step = dst_step = mask_step = CV_STUB_STEP;
469         }
470
471         if( !func )
472             CV_ERROR( CV_StsUnsupportedFormat, "" );
473
474         IPPI_CALL( func( src->data.ptr, src_step, dst->data.ptr, dst_step,
475                          size, mask->data.ptr, mask_step ));
476     }
477
478     __END__;
479 }
480
481
482 /* dst(idx) = value */
483 CV_IMPL void
484 cvSet( void* arr, CvScalar value, const void* maskarr )
485 {
486     static CvBtFuncTable setm_tab;
487     static int inittab = 0;
488     
489     CV_FUNCNAME( "cvSet" );
490
491     __BEGIN__;
492
493     CvMat stub, *mat = (CvMat*)arr;
494     int pix_size, type;
495     double buf[12];
496     int mat_step;
497     CvSize size;
498
499     if( !value.val[0] && !value.val[1] &&
500         !value.val[2] && !value.val[3] && !maskarr )
501     {
502         cvZero( arr );
503         EXIT;
504     }
505
506     if( !CV_IS_MAT(mat))
507     {
508         if( CV_IS_MATND(mat))
509         {
510             CvMatND nstub;
511             CvNArrayIterator iterator;
512             int pix_size1;
513             
514             CV_CALL( cvInitNArrayIterator( 1, &arr, maskarr, &nstub, &iterator ));
515
516             type = CV_MAT_TYPE(iterator.hdr[0]->type);
517             pix_size1 = CV_ELEM_SIZE1(type);
518             pix_size = pix_size1*CV_MAT_CN(type);
519
520             CV_CALL( cvScalarToRawData( &value, buf, type, maskarr == 0 ));
521
522             if( !maskarr )
523             {
524                 iterator.size.width *= pix_size;
525                 do
526                 {
527                     icvSet_8u_C1R( iterator.ptr[0], CV_STUB_STEP,
528                                    iterator.size, buf, pix_size1 );
529                 }
530                 while( cvNextNArraySlice( &iterator ));
531             }
532             else
533             {
534                 CvFunc2D_2A1P func = (CvFunc2D_2A1P)(setm_tab.fn_2d[pix_size]);
535                 if( !func )
536                     CV_ERROR( CV_StsUnsupportedFormat, "" );
537
538                 do
539                 {
540                     func( iterator.ptr[0], CV_STUB_STEP,
541                           iterator.ptr[1], CV_STUB_STEP,
542                           iterator.size, buf );
543                 }
544                 while( cvNextNArraySlice( &iterator ));
545             }
546             EXIT;
547         }    
548         else
549         {
550             int coi = 0;
551             CV_CALL( mat = cvGetMat( mat, &stub, &coi ));
552
553             if( coi != 0 )
554                 CV_ERROR( CV_BadCOI, "" );
555         }
556     }
557
558     type = CV_MAT_TYPE( mat->type );
559     pix_size = CV_ELEM_SIZE(type);
560     size = cvGetMatSize( mat );
561     mat_step = mat->step;
562
563     if( !maskarr )
564     {
565         if( CV_IS_MAT_CONT( mat->type ))
566         {
567             size.width *= size.height;
568         
569             if( size.width <= (int)(CV_MAX_INLINE_MAT_OP_SIZE*sizeof(double)))
570             {
571                 if( type == CV_32FC1 )
572                 {
573                     float* dstdata = (float*)(mat->data.ptr);
574                     float val = (float)value.val[0];
575
576                     do
577                     {
578                         dstdata[size.width-1] = val;
579                     }
580                     while( --size.width );
581
582                     EXIT;
583                 }
584
585                 if( type == CV_64FC1 )
586                 {
587                     double* dstdata = (double*)(mat->data.ptr);
588                     double val = value.val[0];
589
590                     do
591                     {
592                         dstdata[size.width-1] = val;
593                     }
594                     while( --size.width );
595
596                     EXIT;
597                 }
598             }
599
600             mat_step = CV_STUB_STEP;
601             size.height = 1;
602         }
603         
604         size.width *= pix_size;
605         CV_CALL( cvScalarToRawData( &value, buf, type, 1 ));
606
607         IPPI_CALL( icvSet_8u_C1R( mat->data.ptr, mat_step, size, buf,
608                                   CV_ELEM_SIZE1(type)));
609     }
610     else
611     {
612         CvFunc2D_2A1P func;
613         CvMat maskstub, *mask = (CvMat*)maskarr;
614         int mask_step;
615
616         CV_CALL( mask = cvGetMat( mask, &maskstub ));
617
618         if( !CV_IS_MASK_ARR( mask ))
619             CV_ERROR( CV_StsBadMask, "" );
620
621         if( !inittab )
622         {
623             icvInitSetMRTable( &setm_tab );
624             inittab = 1;
625         }
626
627         if( !CV_ARE_SIZES_EQ( mat, mask ))
628             CV_ERROR( CV_StsUnmatchedSizes, "" );
629
630         mask_step = mask->step;
631
632         if( CV_IS_MAT_CONT( mat->type & mask->type ))
633         {
634             size.width *= size.height;
635             mat_step = mask_step = CV_STUB_STEP;
636             size.height = 1;
637         }
638
639         func = (CvFunc2D_2A1P)(setm_tab.fn_2d[pix_size]);
640         if( !func )
641             CV_ERROR( CV_StsUnsupportedFormat, "" );
642
643         CV_CALL( cvScalarToRawData( &value, buf, type, 0 ));
644
645         IPPI_CALL( func( mat->data.ptr, mat_step, mask->data.ptr,
646                          mask_step, size, buf ));
647     }
648
649     __END__;
650 }
651
652
653 /****************************************************************************************\
654 *                                          Clearing                                      *
655 \****************************************************************************************/
656
657 icvSetByte_8u_C1R_t icvSetByte_8u_C1R_p = 0;
658
659 CvStatus CV_STDCALL
660 icvSetZero_8u_C1R( uchar* dst, int dststep, CvSize size )
661 {
662     if( size.width + size.height > 256 && icvSetByte_8u_C1R_p )
663         return icvSetByte_8u_C1R_p( 0, dst, dststep, size );
664
665     for( ; size.height--; dst += dststep )
666         memset( dst, 0, size.width );
667
668     return CV_OK;
669 }
670
671 CV_IMPL void
672 cvSetZero( CvArr* arr )
673 {
674     CV_FUNCNAME( "cvSetZero" );
675     
676     __BEGIN__;
677
678     CvMat stub, *mat = (CvMat*)arr;
679     CvSize size;
680     int mat_step;
681
682     if( !CV_IS_MAT( mat ))
683     {
684         if( CV_IS_MATND(mat))
685         {
686             CvMatND nstub;
687             CvNArrayIterator iterator;
688             
689             CV_CALL( cvInitNArrayIterator( 1, &arr, 0, &nstub, &iterator ));
690             iterator.size.width *= CV_ELEM_SIZE(iterator.hdr[0]->type);
691
692             if( iterator.size.width <= CV_MAX_INLINE_MAT_OP_SIZE*(int)sizeof(double) )
693             {
694                 do
695                 {
696                     memset( iterator.ptr[0], 0, iterator.size.width );
697                 }
698                 while( cvNextNArraySlice( &iterator ));
699             }
700             else
701             {
702                 do
703                 {
704                     icvSetZero_8u_C1R( iterator.ptr[0], CV_STUB_STEP, iterator.size );
705                 }
706                 while( cvNextNArraySlice( &iterator ));
707             }
708             EXIT;
709         }    
710         else if( CV_IS_SPARSE_MAT(mat))
711         {
712             CvSparseMat* mat1 = (CvSparseMat*)mat;
713             cvClearSet( mat1->heap );
714             if( mat1->hashtable )
715                 memset( mat1->hashtable, 0, mat1->hashsize*sizeof(mat1->hashtable[0]));
716             EXIT;
717         }
718         else
719         {
720             int coi = 0;
721             CV_CALL( mat = cvGetMat( mat, &stub, &coi ));
722             if( coi != 0 )
723                 CV_ERROR( CV_BadCOI, "coi is not supported" );
724         }
725     }
726
727     size = cvGetMatSize( mat );
728     size.width *= CV_ELEM_SIZE(mat->type);
729     mat_step = mat->step;
730
731     if( CV_IS_MAT_CONT( mat->type ))
732     {
733         size.width *= size.height;
734
735         if( size.width <= CV_MAX_INLINE_MAT_OP_SIZE*(int)sizeof(double) )
736         {
737             memset( mat->data.ptr, 0, size.width );
738             EXIT;
739         }
740
741         mat_step = CV_STUB_STEP;
742         size.height = 1;
743     }
744
745     IPPI_CALL( icvSetZero_8u_C1R( mat->data.ptr, mat_step, size ));
746
747     __END__;
748 }
749
750
751 /****************************************************************************************\
752 *                                          Flipping                                      *
753 \****************************************************************************************/
754
755 #define ICV_DEF_FLIP_HZ_CASE_C1( type ) \
756     for( i = 0; i < (len+1)/2; i++ )    \
757     {                                   \
758         type t0 = src[i];               \
759         type t1 = src[len - i - 1];     \
760         dst[i] = t1;                    \
761         dst[len - i - 1] = t0;          \
762     }
763
764
765 #define ICV_DEF_FLIP_HZ_CASE_C3( type ) \
766     for( i = 0; i < (len+1)/2; i++ )    \
767     {                                   \
768         type t0 = src[i*3];             \
769         type t1 = src[(len - i)*3 - 3]; \
770         dst[i*3] = t1;                  \
771         dst[(len - i)*3 - 3] = t0;      \
772         t0 = src[i*3 + 1];              \
773         t1 = src[(len - i)*3 - 2];      \
774         dst[i*3 + 1] = t1;              \
775         dst[(len - i)*3 - 2] = t0;      \
776         t0 = src[i*3 + 2];              \
777         t1 = src[(len - i)*3 - 1];      \
778         dst[i*3 + 2] = t1;              \
779         dst[(len - i)*3 - 1] = t0;      \
780     }
781
782
783 #define ICV_DEF_FLIP_HZ_CASE_C4( type ) \
784     for( i = 0; i < (len+1)/2; i++ )    \
785     {                                   \
786         type t0 = src[i*4];             \
787         type t1 = src[(len - i)*4 - 4]; \
788         dst[i*4] = t1;                  \
789         dst[(len - i)*4 - 4] = t0;      \
790         t0 = src[i*4 + 1];              \
791         t1 = src[(len - i)*4 - 3];      \
792         dst[i*4 + 1] = t1;              \
793         dst[(len - i)*4 - 3] = t0;      \
794         t0 = src[i*4 + 2];              \
795         t1 = src[(len - i)*4 - 2];      \
796         dst[i*4 + 2] = t1;              \
797         dst[(len - i)*4 - 2] = t0;      \
798         t0 = src[i*4 + 3];              \
799         t1 = src[(len - i)*4 - 1];      \
800         dst[i*4 + 3] = t1;              \
801         dst[(len - i)*4 - 1] = t0;      \
802     }
803
804
805 #define ICV_DEF_FLIP_HZ_FUNC( flavor, arrtype, cn )                 \
806 static CvStatus CV_STDCALL                                          \
807 icvFlipHorz_##flavor( const arrtype* src, int srcstep,              \
808                       arrtype* dst, int dststep, CvSize size )      \
809 {                                                                   \
810     int i, len = size.width;                                        \
811     srcstep /= sizeof(src[0]); dststep /= sizeof(dst[0]);           \
812                                                                     \
813     for( ; size.height--; src += srcstep, dst += dststep )          \
814     {                                                               \
815         ICV_DEF_FLIP_HZ_CASE_C##cn( arrtype )                       \
816     }                                                               \
817                                                                     \
818     return CV_OK;                                                   \
819 }
820
821
822 ICV_DEF_FLIP_HZ_FUNC( 8u_C1R, uchar, 1 )
823 ICV_DEF_FLIP_HZ_FUNC( 8u_C2R, ushort, 1 )
824 ICV_DEF_FLIP_HZ_FUNC( 8u_C3R, uchar, 3 )
825 ICV_DEF_FLIP_HZ_FUNC( 16u_C2R, int, 1 )
826 ICV_DEF_FLIP_HZ_FUNC( 16u_C3R, ushort, 3 )
827 ICV_DEF_FLIP_HZ_FUNC( 32s_C2R, int64, 1 )
828 ICV_DEF_FLIP_HZ_FUNC( 32s_C3R, int, 3 )
829 ICV_DEF_FLIP_HZ_FUNC( 64s_C2R, int, 4 )
830 ICV_DEF_FLIP_HZ_FUNC( 64s_C3R, int64, 3 )
831 ICV_DEF_FLIP_HZ_FUNC( 64s_C4R, int64, 4 )
832
833 CV_DEF_INIT_PIXSIZE_TAB_2D( FlipHorz, R )
834
835
836 static CvStatus
837 icvFlipVert_8u_C1R( const uchar* src, int srcstep,
838                     uchar* dst, int dststep, CvSize size )
839 {
840     int y, i;
841     const uchar* src1 = src + (size.height - 1)*srcstep;
842     uchar* dst1 = dst + (size.height - 1)*dststep;
843
844     for( y = 0; y < (size.height + 1)/2; y++, src += srcstep, src1 -= srcstep,
845                                               dst += dststep, dst1 -= dststep )
846     {
847         i = 0;
848         if( ((size_t)(src)|(size_t)(dst)|(size_t)src1|(size_t)dst1) % sizeof(int) == 0 )
849         {
850             for( ; i <= size.width - 16; i += 16 )
851             {
852                 int t0 = ((int*)(src + i))[0];
853                 int t1 = ((int*)(src1 + i))[0];
854
855                 ((int*)(dst + i))[0] = t1;
856                 ((int*)(dst1 + i))[0] = t0;
857
858                 t0 = ((int*)(src + i))[1];
859                 t1 = ((int*)(src1 + i))[1];
860
861                 ((int*)(dst + i))[1] = t1;
862                 ((int*)(dst1 + i))[1] = t0;
863
864                 t0 = ((int*)(src + i))[2];
865                 t1 = ((int*)(src1 + i))[2];
866
867                 ((int*)(dst + i))[2] = t1;
868                 ((int*)(dst1 + i))[2] = t0;
869
870                 t0 = ((int*)(src + i))[3];
871                 t1 = ((int*)(src1 + i))[3];
872
873                 ((int*)(dst + i))[3] = t1;
874                 ((int*)(dst1 + i))[3] = t0;
875             }
876
877             for( ; i <= size.width - 4; i += 4 )
878             {
879                 int t0 = ((int*)(src + i))[0];
880                 int t1 = ((int*)(src1 + i))[0];
881
882                 ((int*)(dst + i))[0] = t1;
883                 ((int*)(dst1 + i))[0] = t0;
884             }
885         }
886
887         for( ; i < size.width; i++ )
888         {
889             uchar t0 = src[i];
890             uchar t1 = src1[i];
891
892             dst[i] = t1;
893             dst1[i] = t0;
894         }
895     }
896
897     return CV_OK;
898 }
899
900
901 CV_IMPL void
902 cvFlip( const CvArr* srcarr, CvArr* dstarr, int flip_mode )
903 {
904     static CvBtFuncTable tab;
905     static int inittab = 0;
906     
907     CV_FUNCNAME( "cvFlip" );
908     
909     __BEGIN__;
910
911     CvMat sstub, *src = (CvMat*)srcarr;
912     CvMat dstub, *dst = (CvMat*)dstarr;
913     CvSize size;
914     CvFunc2D_2A func = 0;
915     int pix_size;
916
917     if( !inittab )
918     {
919         icvInitFlipHorzRTable( &tab );
920         inittab = 1;
921     }
922
923     if( !CV_IS_MAT( src ))
924     {
925         int coi = 0;
926         CV_CALL( src = cvGetMat( src, &sstub, &coi ));
927         if( coi != 0 )
928             CV_ERROR( CV_BadCOI, "coi is not supported" );
929     }
930
931     if( !dst )
932         dst = src;
933     else if( !CV_IS_MAT( dst ))
934     {
935         int coi = 0;
936         CV_CALL( dst = cvGetMat( dst, &dstub, &coi ));
937         if( coi != 0 )
938             CV_ERROR( CV_BadCOI, "coi is not supported" );
939     }
940
941     if( !CV_ARE_TYPES_EQ( src, dst ))
942         CV_ERROR( CV_StsUnmatchedFormats, "" );
943
944     if( !CV_ARE_SIZES_EQ( src, dst ))
945         CV_ERROR( CV_StsUnmatchedSizes, "" );
946
947     size = cvGetMatSize( src );
948     pix_size = CV_ELEM_SIZE( src->type );
949
950     if( flip_mode == 0 )
951     {
952         size.width *= pix_size;
953         
954         IPPI_CALL( icvFlipVert_8u_C1R( src->data.ptr, src->step,
955                                        dst->data.ptr, dst->step, size ));
956     }
957     else
958     {
959         int inplace = src->data.ptr == dst->data.ptr;
960         uchar* dst_data = dst->data.ptr;
961         int dst_step = dst->step;
962
963         func = (CvFunc2D_2A)(tab.fn_2d[pix_size]);
964
965         if( !func )
966             CV_ERROR( CV_StsUnsupportedFormat, "" );
967
968         if( flip_mode < 0 && !inplace )
969         {
970             dst_data += dst_step * (dst->height - 1);
971             dst_step = -dst_step;
972         }
973
974         IPPI_CALL( func( src->data.ptr, src->step, dst_data, dst_step, size ));
975         
976         if( flip_mode < 0 && inplace )
977         {
978             size.width *= pix_size;
979             IPPI_CALL( icvFlipVert_8u_C1R( dst->data.ptr, dst->step,
980                                            dst->data.ptr, dst->step, size ));
981         }
982     }
983
984     __END__;
985 }
986
987
988 CV_IMPL void
989 cvRepeat( const CvArr* srcarr, CvArr* dstarr )
990 {
991     CV_FUNCNAME( "cvRepeat" );
992     
993     __BEGIN__;
994
995     CvMat sstub, *src = (CvMat*)srcarr;
996     CvMat dstub, *dst = (CvMat*)dstarr;
997     CvSize srcsize, dstsize;
998     int pix_size;
999     int x, y, k, l;
1000
1001     if( !CV_IS_MAT( src ))
1002     {
1003         int coi = 0;
1004         CV_CALL( src = cvGetMat( src, &sstub, &coi ));
1005         if( coi != 0 )
1006             CV_ERROR( CV_BadCOI, "coi is not supported" );
1007     }
1008
1009     if( !CV_IS_MAT( dst ))
1010     {
1011         int coi = 0;
1012         CV_CALL( dst = cvGetMat( dst, &dstub, &coi ));
1013         if( coi != 0 )
1014             CV_ERROR( CV_BadCOI, "coi is not supported" );
1015     }
1016
1017     if( !CV_ARE_TYPES_EQ( src, dst ))
1018         CV_ERROR( CV_StsUnmatchedFormats, "" );
1019
1020     srcsize = cvGetMatSize( src );
1021     dstsize = cvGetMatSize( dst );
1022     pix_size = CV_ELEM_SIZE( src->type );
1023
1024     for( y = 0, k = 0; y < dstsize.height; y++ )
1025     {
1026         for( x = 0; x < dstsize.width; x += srcsize.width )
1027         {
1028             l = srcsize.width;
1029             if( l > dstsize.width - x )
1030                 l = dstsize.width - x;
1031             memcpy( dst->data.ptr + y*dst->step + x*pix_size,
1032                     src->data.ptr + k*src->step, l*pix_size );
1033         }
1034         if( ++k == srcsize.height )
1035             k = 0;
1036     }
1037
1038     __END__;
1039 }
1040
1041 /* End of file. */
1042