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
57IPCVAPI_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
68static CvStatus CV_STDCALL
69icvSet_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 )              \
152IPCVAPI_IMPL( CvStatus,                                     \
153name,( 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 )       \
205IPCVAPI_IMPL( CvStatus,                             \
206name,( 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
225ICV_DEF_SET_MASK_2D( icvSet_8u_C1MR, uchar, 1 )
226ICV_DEF_SET_MASK_2D( icvSet_16s_C1MR, ushort, 1 )
227ICV_DEF_SET_MASK_2D( icvSet_8u_C3MR, uchar, 3 )
228ICV_DEF_SET_MASK_2D( icvSet_8u_C4MR, int, 1 )
229ICV_DEF_SET_MASK_2D( icvSet_16s_C3MR, ushort, 3 )
230ICV_DEF_SET_MASK_2D( icvSet_16s_C4MR, int64, 1 )
231ICV_DEF_SET_MASK_2D( icvSet_32f_C3MR, int, 3 )
232ICV_DEF_SET_MASK_2D( icvSet_32f_C4MR, int, 4 )
233ICV_DEF_SET_MASK_2D( icvSet_64s_C3MR, int64, 3 )
234ICV_DEF_SET_MASK_2D( icvSet_64s_C4MR, int64, 4 )
235
236ICV_DEF_COPY_MASK_2D( icvCopy_8u_C1MR, uchar, 1 )
237ICV_DEF_COPY_MASK_2D( icvCopy_16s_C1MR, ushort, 1 )
238ICV_DEF_COPY_MASK_2D( icvCopy_8u_C3MR, uchar, 3 )
239ICV_DEF_COPY_MASK_2D( icvCopy_8u_C4MR, int, 1 )
240ICV_DEF_COPY_MASK_2D( icvCopy_16s_C3MR, ushort, 3 )
241ICV_DEF_COPY_MASK_2D( icvCopy_16s_C4MR, int64, 1 )
242ICV_DEF_COPY_MASK_2D( icvCopy_32f_C3MR, int, 3 )
243ICV_DEF_COPY_MASK_2D( icvCopy_32f_C4MR, int, 4 )
244ICV_DEF_COPY_MASK_2D( icvCopy_64s_C3MR, int64, 3 )
245ICV_DEF_COPY_MASK_2D( icvCopy_64s_C4MR, int64, 4 )
246
247#define CV_DEF_INIT_COPYSET_TAB_2D( FUNCNAME, FLAG )                \
248static 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
262CV_DEF_INIT_COPYSET_TAB_2D( Set, MR )
263CV_DEF_INIT_COPYSET_TAB_2D( Copy, MR )
264
265/////////////////////////////////////////////////////////////////////////////////////////
266//                                                                                     //
267//                                H/L COPY & SET FUNCTIONS                             //
268//                                                                                     //
269/////////////////////////////////////////////////////////////////////////////////////////
270
271
272CvCopyMaskFunc
273icvGetCopyMaskFunc( 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 */
288CV_IMPL void
289cvCopy( 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 */
483CV_IMPL void
484cvSet( 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
657icvSetByte_8u_C1R_t icvSetByte_8u_C1R_p = 0;
658
659CvStatus CV_STDCALL
660icvSetZero_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
671CV_IMPL void
672cvSetZero( 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 )                 \
806static CvStatus CV_STDCALL                                          \
807icvFlipHorz_##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
822ICV_DEF_FLIP_HZ_FUNC( 8u_C1R, uchar, 1 )
823ICV_DEF_FLIP_HZ_FUNC( 8u_C2R, ushort, 1 )
824ICV_DEF_FLIP_HZ_FUNC( 8u_C3R, uchar, 3 )
825ICV_DEF_FLIP_HZ_FUNC( 16u_C2R, int, 1 )
826ICV_DEF_FLIP_HZ_FUNC( 16u_C3R, ushort, 3 )
827ICV_DEF_FLIP_HZ_FUNC( 32s_C2R, int64, 1 )
828ICV_DEF_FLIP_HZ_FUNC( 32s_C3R, int, 3 )
829ICV_DEF_FLIP_HZ_FUNC( 64s_C2R, int, 4 )
830ICV_DEF_FLIP_HZ_FUNC( 64s_C3R, int64, 3 )
831ICV_DEF_FLIP_HZ_FUNC( 64s_C4R, int64, 4 )
832
833CV_DEF_INIT_PIXSIZE_TAB_2D( FlipHorz, R )
834
835
836static CvStatus
837icvFlipVert_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
901CV_IMPL void
902cvFlip( 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
988CV_IMPL void
989cvRepeat( 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
1043