Added more strict checks for empty inputs to compare, meanStdDev and RNG::fill
[platform/upstream/opencv.git] / modules / core / src / copy.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 //                           License Agreement
10 //                For Open Source Computer Vision Library
11 //
12 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
13 // Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
14 // Copyright (C) 2014, Itseez Inc., all rights reserved.
15 // Third party copyrights are property of their respective owners.
16 //
17 // Redistribution and use in source and binary forms, with or without modification,
18 // are permitted provided that the following conditions are met:
19 //
20 //   * Redistribution's of source code must retain the above copyright notice,
21 //     this list of conditions and the following disclaimer.
22 //
23 //   * Redistribution's in binary form must reproduce the above copyright notice,
24 //     this list of conditions and the following disclaimer in the documentation
25 //     and/or other materials provided with the distribution.
26 //
27 //   * The name of the copyright holders may not be used to endorse or promote products
28 //     derived from this software without specific prior written permission.
29 //
30 // This software is provided by the copyright holders and contributors "as is" and
31 // any express or implied warranties, including, but not limited to, the implied
32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
33 // In no event shall the Intel Corporation or contributors be liable for any direct,
34 // indirect, incidental, special, exemplary, or consequential damages
35 // (including, but not limited to, procurement of substitute goods or services;
36 // loss of use, data, or profits; or business interruption) however caused
37 // and on any theory of liability, whether in contract, strict liability,
38 // or tort (including negligence or otherwise) arising in any way out of
39 // the use of this software, even if advised of the possibility of such damage.
40 //
41 //M*/
42
43 /* ////////////////////////////////////////////////////////////////////
44 //
45 //  Mat basic operations: Copy, Set
46 //
47 // */
48
49 #include "precomp.hpp"
50 #include "opencl_kernels_core.hpp"
51
52
53 namespace cv
54 {
55
56 template<typename T> static void
57 copyMask_(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size)
58 {
59     for( ; size.height--; mask += mstep, _src += sstep, _dst += dstep )
60     {
61         const T* src = (const T*)_src;
62         T* dst = (T*)_dst;
63         int x = 0;
64          #if CV_ENABLE_UNROLLED
65         for( ; x <= size.width - 4; x += 4 )
66         {
67             if( mask[x] )
68                 dst[x] = src[x];
69             if( mask[x+1] )
70                 dst[x+1] = src[x+1];
71             if( mask[x+2] )
72                 dst[x+2] = src[x+2];
73             if( mask[x+3] )
74                 dst[x+3] = src[x+3];
75         }
76         #endif
77         for( ; x < size.width; x++ )
78             if( mask[x] )
79                 dst[x] = src[x];
80     }
81 }
82
83 template<> void
84 copyMask_<uchar>(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size)
85 {
86     CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippiCopy_8u_C1MR, _src, (int)sstep, _dst, (int)dstep, ippiSize(size), mask, (int)mstep) >= 0)
87
88     for( ; size.height--; mask += mstep, _src += sstep, _dst += dstep )
89     {
90         const uchar* src = (const uchar*)_src;
91         uchar* dst = (uchar*)_dst;
92         int x = 0;
93         #if CV_SIMD128
94         {
95             v_uint8x16 v_zero = v_setzero_u8();
96
97             for( ; x <= size.width - 16; x += 16 )
98             {
99                 v_uint8x16 v_src   = v_load(src  + x),
100                            v_dst   = v_load(dst  + x),
101                            v_nmask = v_load(mask + x) == v_zero;
102
103                 v_dst = v_select(v_nmask, v_dst, v_src);
104                 v_store(dst + x, v_dst);
105             }
106         }
107         #endif
108         for( ; x < size.width; x++ )
109             if( mask[x] )
110                 dst[x] = src[x];
111     }
112 }
113
114 template<> void
115 copyMask_<ushort>(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size)
116 {
117     CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippiCopy_16u_C1MR, (const Ipp16u *)_src, (int)sstep, (Ipp16u *)_dst, (int)dstep, ippiSize(size), mask, (int)mstep) >= 0)
118
119     for( ; size.height--; mask += mstep, _src += sstep, _dst += dstep )
120     {
121         const ushort* src = (const ushort*)_src;
122         ushort* dst = (ushort*)_dst;
123         int x = 0;
124         #if CV_SIMD128
125         {
126             v_uint8x16 v_zero = v_setzero_u8();
127
128             for( ; x <= size.width - 16; x += 16 )
129             {
130                 v_uint16x8 v_src1 = v_load(src + x), v_src2 = v_load(src + x + 8),
131                            v_dst1 = v_load(dst + x), v_dst2 = v_load(dst + x + 8);
132
133                 v_uint8x16 v_nmask1, v_nmask2;
134                 v_uint8x16 v_nmask = v_load(mask + x) == v_zero;
135                 v_zip(v_nmask, v_nmask, v_nmask1, v_nmask2);
136
137                 v_dst1 = v_select(v_reinterpret_as_u16(v_nmask1), v_dst1, v_src1);
138                 v_dst2 = v_select(v_reinterpret_as_u16(v_nmask2), v_dst2, v_src2);
139                 v_store(dst + x, v_dst1);
140                 v_store(dst + x + 8, v_dst2);
141             }
142         }
143         #endif
144         for( ; x < size.width; x++ )
145             if( mask[x] )
146                 dst[x] = src[x];
147     }
148 }
149
150 static void
151 copyMaskGeneric(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size, void* _esz)
152 {
153     size_t k, esz = *(size_t*)_esz;
154     for( ; size.height--; mask += mstep, _src += sstep, _dst += dstep )
155     {
156         const uchar* src = _src;
157         uchar* dst = _dst;
158         int x = 0;
159         for( ; x < size.width; x++, src += esz, dst += esz )
160         {
161             if( !mask[x] )
162                 continue;
163             for( k = 0; k < esz; k++ )
164                 dst[k] = src[k];
165         }
166     }
167 }
168
169
170 #define DEF_COPY_MASK(suffix, type) \
171 static void copyMask##suffix(const uchar* src, size_t sstep, const uchar* mask, size_t mstep, \
172                              uchar* dst, size_t dstep, Size size, void*) \
173 { \
174     copyMask_<type>(src, sstep, mask, mstep, dst, dstep, size); \
175 }
176
177 #if defined HAVE_IPP
178 #define DEF_COPY_MASK_F(suffix, type, ippfavor, ipptype) \
179 static void copyMask##suffix(const uchar* src, size_t sstep, const uchar* mask, size_t mstep, \
180                              uchar* dst, size_t dstep, Size size, void*) \
181 { \
182     CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippiCopy_##ippfavor, (const ipptype *)src, (int)sstep, (ipptype *)dst, (int)dstep, ippiSize(size), (const Ipp8u *)mask, (int)mstep) >= 0)\
183     copyMask_<type>(src, sstep, mask, mstep, dst, dstep, size); \
184 }
185 #else
186 #define DEF_COPY_MASK_F(suffix, type, ippfavor, ipptype) \
187 static void copyMask##suffix(const uchar* src, size_t sstep, const uchar* mask, size_t mstep, \
188                              uchar* dst, size_t dstep, Size size, void*) \
189 { \
190     copyMask_<type>(src, sstep, mask, mstep, dst, dstep, size); \
191 }
192 #endif
193
194 #if IPP_VERSION_X100 == 901 // bug in IPP 9.0.1
195 DEF_COPY_MASK(32sC3, Vec3i)
196 DEF_COPY_MASK(8uC3, Vec3b)
197 #else
198 DEF_COPY_MASK_F(8uC3, Vec3b, 8u_C3MR, Ipp8u)
199 DEF_COPY_MASK_F(32sC3, Vec3i, 32s_C3MR, Ipp32s)
200 #endif
201 DEF_COPY_MASK(8u, uchar)
202 DEF_COPY_MASK(16u, ushort)
203 DEF_COPY_MASK_F(32s, int, 32s_C1MR, Ipp32s)
204 DEF_COPY_MASK_F(16uC3, Vec3s, 16u_C3MR, Ipp16u)
205 DEF_COPY_MASK(32sC2, Vec2i)
206 DEF_COPY_MASK_F(32sC4, Vec4i, 32s_C4MR, Ipp32s)
207 DEF_COPY_MASK(32sC6, Vec6i)
208 DEF_COPY_MASK(32sC8, Vec8i)
209
210 BinaryFunc copyMaskTab[] =
211 {
212     0,
213     copyMask8u,
214     copyMask16u,
215     copyMask8uC3,
216     copyMask32s,
217     0,
218     copyMask16uC3,
219     0,
220     copyMask32sC2,
221     0, 0, 0,
222     copyMask32sC3,
223     0, 0, 0,
224     copyMask32sC4,
225     0, 0, 0, 0, 0, 0, 0,
226     copyMask32sC6,
227     0, 0, 0, 0, 0, 0, 0,
228     copyMask32sC8
229 };
230
231 BinaryFunc getCopyMaskFunc(size_t esz)
232 {
233     return esz <= 32 && copyMaskTab[esz] ? copyMaskTab[esz] : copyMaskGeneric;
234 }
235
236 /* dst = src */
237 void Mat::copyTo( OutputArray _dst ) const
238 {
239     CV_INSTRUMENT_REGION()
240
241     int dtype = _dst.type();
242     if( _dst.fixedType() && dtype != type() )
243     {
244         CV_Assert( channels() == CV_MAT_CN(dtype) );
245         convertTo( _dst, dtype );
246         return;
247     }
248
249     if( empty() )
250     {
251         _dst.release();
252         return;
253     }
254
255     if( _dst.isUMat() )
256     {
257         _dst.create( dims, size.p, type() );
258         UMat dst = _dst.getUMat();
259         CV_Assert(dst.u != NULL);
260         size_t i, sz[CV_MAX_DIM] = {0}, dstofs[CV_MAX_DIM], esz = elemSize();
261         CV_Assert(dims >= 0 && dims < CV_MAX_DIM);
262         for( i = 0; i < (size_t)dims; i++ )
263             sz[i] = size.p[i];
264         sz[dims-1] *= esz;
265         dst.ndoffset(dstofs);
266         dstofs[dims-1] *= esz;
267         dst.u->currAllocator->upload(dst.u, data, dims, sz, dstofs, dst.step.p, step.p);
268         return;
269     }
270
271     if( dims <= 2 )
272     {
273         _dst.create( rows, cols, type() );
274         Mat dst = _dst.getMat();
275         if( data == dst.data )
276             return;
277
278         if( rows > 0 && cols > 0 )
279         {
280             // For some cases (with vector) dst.size != src.size, so force to column-based form
281             // It prevents memory corruption in case of column-based src
282             if (_dst.isVector())
283                 dst = dst.reshape(0, (int)dst.total());
284
285             const uchar* sptr = data;
286             uchar* dptr = dst.data;
287
288 #if IPP_VERSION_X100 >= 201700
289             CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippiCopy_8u_C1R_L, sptr, (int)step, dptr, (int)dst.step, ippiSizeL((int)(cols*elemSize()), rows)) >= 0)
290 #endif
291
292             Size sz = getContinuousSize(*this, dst);
293             size_t len = sz.width*elemSize();
294
295             for( ; sz.height--; sptr += step, dptr += dst.step )
296                 memcpy( dptr, sptr, len );
297         }
298         return;
299     }
300
301     _dst.create( dims, size, type() );
302     Mat dst = _dst.getMat();
303     if( data == dst.data )
304         return;
305
306     if( total() != 0 )
307     {
308         const Mat* arrays[] = { this, &dst };
309         uchar* ptrs[2];
310         NAryMatIterator it(arrays, ptrs, 2);
311         size_t sz = it.size*elemSize();
312
313         for( size_t i = 0; i < it.nplanes; i++, ++it )
314             memcpy(ptrs[1], ptrs[0], sz);
315     }
316 }
317
318 #ifdef HAVE_IPP
319 static bool ipp_copyTo(const Mat &src, Mat &dst, const Mat &mask)
320 {
321 #ifdef HAVE_IPP_IW
322     CV_INSTRUMENT_REGION_IPP()
323
324     if(mask.channels() > 1 || mask.depth() != CV_8U)
325         return false;
326
327     if (src.dims <= 2)
328     {
329         IppiSize size = ippiSize(src.size());
330         return CV_INSTRUMENT_FUN_IPP(llwiCopyMask, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, size, (int)src.elemSize1(), src.channels(), mask.ptr(), (int)mask.step) >= 0;
331     }
332     else
333     {
334         const Mat      *arrays[] = {&src, &dst, &mask, NULL};
335         uchar          *ptrs[3]  = {NULL};
336         NAryMatIterator it(arrays, ptrs);
337
338         IppiSize size = ippiSize(it.size, 1);
339
340         for (size_t i = 0; i < it.nplanes; i++, ++it)
341         {
342             if(CV_INSTRUMENT_FUN_IPP(llwiCopyMask, ptrs[0], 0, ptrs[1], 0, size, (int)src.elemSize1(), src.channels(), ptrs[2], 0) < 0)
343                 return false;
344         }
345         return true;
346     }
347 #else
348     CV_UNUSED(src); CV_UNUSED(dst); CV_UNUSED(mask);
349     return false;
350 #endif
351 }
352 #endif
353
354 void Mat::copyTo( OutputArray _dst, InputArray _mask ) const
355 {
356     CV_INSTRUMENT_REGION()
357
358     Mat mask = _mask.getMat();
359     if( !mask.data )
360     {
361         copyTo(_dst);
362         return;
363     }
364
365     int cn = channels(), mcn = mask.channels();
366     CV_Assert( mask.depth() == CV_8U && (mcn == 1 || mcn == cn) );
367     bool colorMask = mcn > 1;
368     if( dims <= 2 )
369     {
370         CV_Assert( size() == mask.size() );
371     }
372
373     Mat dst;
374     {
375         Mat dst0 = _dst.getMat();
376         _dst.create(dims, size, type()); // TODO Prohibit 'dst' re-creation, user should pass it explicitly with correct size/type or empty
377         dst = _dst.getMat();
378
379         if (dst.data != dst0.data) // re-allocation happened
380         {
381 #ifdef OPENCV_FUTURE
382             CV_Assert(dst0.empty() &&
383                 "copyTo(): dst size/type mismatch (looks like a bug) - use dst.release() before copyTo() call to suppress this message");
384 #endif
385             dst = Scalar(0); // do not leave dst uninitialized
386         }
387     }
388
389     CV_IPP_RUN_FAST(ipp_copyTo(*this, dst, mask))
390
391     size_t esz = colorMask ? elemSize1() : elemSize();
392     BinaryFunc copymask = getCopyMaskFunc(esz);
393
394     if( dims <= 2 )
395     {
396         Size sz = getContinuousSize(*this, dst, mask, mcn);
397         copymask(data, step, mask.data, mask.step, dst.data, dst.step, sz, &esz);
398         return;
399     }
400
401     const Mat* arrays[] = { this, &dst, &mask, 0 };
402     uchar* ptrs[3];
403     NAryMatIterator it(arrays, ptrs);
404     Size sz((int)(it.size*mcn), 1);
405
406     for( size_t i = 0; i < it.nplanes; i++, ++it )
407         copymask(ptrs[0], 0, ptrs[2], 0, ptrs[1], 0, sz, &esz);
408 }
409
410 Mat& Mat::operator = (const Scalar& s)
411 {
412     CV_INSTRUMENT_REGION()
413
414     if (this->empty())
415         return *this;
416
417     const Mat* arrays[] = { this };
418     uchar* dptr;
419     NAryMatIterator it(arrays, &dptr, 1);
420     size_t elsize = it.size*elemSize();
421     const int64* is = (const int64*)&s.val[0];
422
423     if( is[0] == 0 && is[1] == 0 && is[2] == 0 && is[3] == 0 )
424     {
425         for( size_t i = 0; i < it.nplanes; i++, ++it )
426             memset( dptr, 0, elsize );
427     }
428     else
429     {
430         if( it.nplanes > 0 )
431         {
432             double scalar[12];
433             scalarToRawData(s, scalar, type(), 12);
434             size_t blockSize = 12*elemSize1();
435
436             for( size_t j = 0; j < elsize; j += blockSize )
437             {
438                 size_t sz = MIN(blockSize, elsize - j);
439                 CV_Assert(sz <= sizeof(scalar));
440                 memcpy( dptr + j, scalar, sz );
441             }
442         }
443
444         for( size_t i = 1; i < it.nplanes; i++ )
445         {
446             ++it;
447             memcpy( dptr, data, elsize );
448         }
449     }
450     return *this;
451 }
452
453 #ifdef HAVE_IPP
454 static bool ipp_Mat_setTo_Mat(Mat &dst, Mat &_val, Mat &mask)
455 {
456 #ifdef HAVE_IPP_IW
457     CV_INSTRUMENT_REGION_IPP()
458
459     if(mask.empty())
460         return false;
461
462     if(mask.depth() != CV_8U || mask.channels() > 1)
463         return false;
464
465     if(dst.channels() > 4)
466         return false;
467
468     if (dst.depth() == CV_32F)
469     {
470         for (int i = 0; i < (int)(_val.total()); i++)
471         {
472             float v = (float)(_val.at<double>(i));  // cast to float
473             if (cvIsNaN(v) || cvIsInf(v))  // accept finite numbers only
474                 return false;
475         }
476     }
477
478     if(dst.dims <= 2)
479     {
480         IppiSize            size     = ippiSize(dst.size());
481         IppDataType         dataType = ippiGetDataType(dst.depth());
482         ::ipp::IwValueFloat s;
483         convertAndUnrollScalar(_val, CV_MAKETYPE(CV_64F, dst.channels()), (uchar*)((Ipp64f*)s), 1);
484
485         return CV_INSTRUMENT_FUN_IPP(llwiSetMask, s, dst.ptr(), (int)dst.step, size, dataType, dst.channels(), mask.ptr(), (int)mask.step) >= 0;
486     }
487     else
488     {
489         const Mat      *arrays[] = {&dst, mask.empty()?NULL:&mask, NULL};
490         uchar          *ptrs[2]  = {NULL};
491         NAryMatIterator it(arrays, ptrs);
492
493         IppiSize            size     = {(int)it.size, 1};
494         IppDataType         dataType = ippiGetDataType(dst.depth());
495         ::ipp::IwValueFloat s;
496         convertAndUnrollScalar(_val, CV_MAKETYPE(CV_64F, dst.channels()), (uchar*)((Ipp64f*)s), 1);
497
498         for( size_t i = 0; i < it.nplanes; i++, ++it)
499         {
500             if(CV_INSTRUMENT_FUN_IPP(llwiSetMask, s, ptrs[0], 0, size, dataType, dst.channels(), ptrs[1], 0) < 0)
501                 return false;
502         }
503         return true;
504     }
505 #else
506     CV_UNUSED(dst); CV_UNUSED(_val); CV_UNUSED(mask);
507     return false;
508 #endif
509 }
510 #endif
511
512 Mat& Mat::setTo(InputArray _value, InputArray _mask)
513 {
514     CV_INSTRUMENT_REGION()
515
516     if( empty() )
517         return *this;
518
519     Mat value = _value.getMat(), mask = _mask.getMat();
520
521     CV_Assert( checkScalar(value, type(), _value.kind(), _InputArray::MAT ));
522     int cn = channels(), mcn = mask.channels();
523     CV_Assert( mask.empty() || (mask.depth() == CV_8U && (mcn == 1 || mcn == cn) && size == mask.size) );
524
525     CV_IPP_RUN_FAST(ipp_Mat_setTo_Mat(*this, value, mask), *this)
526
527     size_t esz = mcn > 1 ? elemSize1() : elemSize();
528     BinaryFunc copymask = getCopyMaskFunc(esz);
529
530     const Mat* arrays[] = { this, !mask.empty() ? &mask : 0, 0 };
531     uchar* ptrs[2]={0,0};
532     NAryMatIterator it(arrays, ptrs);
533     int totalsz = (int)it.size*mcn;
534     int blockSize0 = std::min(totalsz, (int)((BLOCK_SIZE + esz-1)/esz));
535     blockSize0 -= blockSize0 % mcn;    // must be divisible without remainder for unrolling and advancing
536     AutoBuffer<uchar> _scbuf(blockSize0*esz + 32);
537     uchar* scbuf = alignPtr((uchar*)_scbuf.data(), (int)sizeof(double));
538     convertAndUnrollScalar( value, type(), scbuf, blockSize0/mcn );
539
540     for( size_t i = 0; i < it.nplanes; i++, ++it )
541     {
542         for( int j = 0; j < totalsz; j += blockSize0 )
543         {
544             Size sz(std::min(blockSize0, totalsz - j), 1);
545             size_t blockSize = sz.width*esz;
546             if( ptrs[1] )
547             {
548                 copymask(scbuf, 0, ptrs[1], 0, ptrs[0], 0, sz, &esz);
549                 ptrs[1] += sz.width;
550             }
551             else
552                 memcpy(ptrs[0], scbuf, blockSize);
553             ptrs[0] += blockSize;
554         }
555     }
556     return *this;
557 }
558
559
560 static void
561 flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, size_t esz )
562 {
563     int i, j, limit = (int)(((size.width + 1)/2)*esz);
564     AutoBuffer<int> _tab(size.width*esz);
565     int* tab = _tab.data();
566
567     for( i = 0; i < size.width; i++ )
568         for( size_t k = 0; k < esz; k++ )
569             tab[i*esz + k] = (int)((size.width - i - 1)*esz + k);
570
571     for( ; size.height--; src += sstep, dst += dstep )
572     {
573         for( i = 0; i < limit; i++ )
574         {
575             j = tab[i];
576             uchar t0 = src[i], t1 = src[j];
577             dst[i] = t1; dst[j] = t0;
578         }
579     }
580 }
581
582 static void
583 flipVert( const uchar* src0, size_t sstep, uchar* dst0, size_t dstep, Size size, size_t esz )
584 {
585     const uchar* src1 = src0 + (size.height - 1)*sstep;
586     uchar* dst1 = dst0 + (size.height - 1)*dstep;
587     size.width *= (int)esz;
588
589     for( int y = 0; y < (size.height + 1)/2; y++, src0 += sstep, src1 -= sstep,
590                                                   dst0 += dstep, dst1 -= dstep )
591     {
592         int i = 0;
593         if( ((size_t)src0|(size_t)dst0|(size_t)src1|(size_t)dst1) % sizeof(int) == 0 )
594         {
595             for( ; i <= size.width - 16; i += 16 )
596             {
597                 int t0 = ((int*)(src0 + i))[0];
598                 int t1 = ((int*)(src1 + i))[0];
599
600                 ((int*)(dst0 + i))[0] = t1;
601                 ((int*)(dst1 + i))[0] = t0;
602
603                 t0 = ((int*)(src0 + i))[1];
604                 t1 = ((int*)(src1 + i))[1];
605
606                 ((int*)(dst0 + i))[1] = t1;
607                 ((int*)(dst1 + i))[1] = t0;
608
609                 t0 = ((int*)(src0 + i))[2];
610                 t1 = ((int*)(src1 + i))[2];
611
612                 ((int*)(dst0 + i))[2] = t1;
613                 ((int*)(dst1 + i))[2] = t0;
614
615                 t0 = ((int*)(src0 + i))[3];
616                 t1 = ((int*)(src1 + i))[3];
617
618                 ((int*)(dst0 + i))[3] = t1;
619                 ((int*)(dst1 + i))[3] = t0;
620             }
621
622             for( ; i <= size.width - 4; i += 4 )
623             {
624                 int t0 = ((int*)(src0 + i))[0];
625                 int t1 = ((int*)(src1 + i))[0];
626
627                 ((int*)(dst0 + i))[0] = t1;
628                 ((int*)(dst1 + i))[0] = t0;
629             }
630         }
631
632         for( ; i < size.width; i++ )
633         {
634             uchar t0 = src0[i];
635             uchar t1 = src1[i];
636
637             dst0[i] = t1;
638             dst1[i] = t0;
639         }
640     }
641 }
642
643 #ifdef HAVE_OPENCL
644
645 enum { FLIP_COLS = 1 << 0, FLIP_ROWS = 1 << 1, FLIP_BOTH = FLIP_ROWS | FLIP_COLS };
646
647 static bool ocl_flip(InputArray _src, OutputArray _dst, int flipCode )
648 {
649     CV_Assert(flipCode >= -1 && flipCode <= 1);
650
651     const ocl::Device & dev = ocl::Device::getDefault();
652     int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type),
653             flipType, kercn = std::min(ocl::predictOptimalVectorWidth(_src, _dst), 4);
654
655     bool doubleSupport = dev.doubleFPConfig() > 0;
656     if (!doubleSupport && depth == CV_64F)
657         kercn = cn;
658
659     if (cn > 4)
660         return false;
661
662     const char * kernelName;
663     if (flipCode == 0)
664         kernelName = "arithm_flip_rows", flipType = FLIP_ROWS;
665     else if (flipCode > 0)
666         kernelName = "arithm_flip_cols", flipType = FLIP_COLS;
667     else
668         kernelName = "arithm_flip_rows_cols", flipType = FLIP_BOTH;
669
670     int pxPerWIy = (dev.isIntel() && (dev.type() & ocl::Device::TYPE_GPU)) ? 4 : 1;
671     kercn = (cn!=3 || flipType == FLIP_ROWS) ? std::max(kercn, cn) : cn;
672
673     ocl::Kernel k(kernelName, ocl::core::flip_oclsrc,
674         format( "-D T=%s -D T1=%s -D cn=%d -D PIX_PER_WI_Y=%d -D kercn=%d",
675                 kercn != cn ? ocl::typeToStr(CV_MAKE_TYPE(depth, kercn)) : ocl::vecopTypeToStr(CV_MAKE_TYPE(depth, kercn)),
676                 kercn != cn ? ocl::typeToStr(depth) : ocl::vecopTypeToStr(depth), cn, pxPerWIy, kercn));
677     if (k.empty())
678         return false;
679
680     Size size = _src.size();
681     _dst.create(size, type);
682     UMat src = _src.getUMat(), dst = _dst.getUMat();
683
684     int cols = size.width * cn / kercn, rows = size.height;
685     cols = flipType == FLIP_COLS ? (cols + 1) >> 1 : cols;
686     rows = flipType & FLIP_ROWS ? (rows + 1) >> 1 : rows;
687
688     k.args(ocl::KernelArg::ReadOnlyNoSize(src),
689            ocl::KernelArg::WriteOnly(dst, cn, kercn), rows, cols);
690
691     size_t maxWorkGroupSize = dev.maxWorkGroupSize();
692     CV_Assert(maxWorkGroupSize % 4 == 0);
693
694     size_t globalsize[2] = { (size_t)cols, ((size_t)rows + pxPerWIy - 1) / pxPerWIy },
695             localsize[2] = { maxWorkGroupSize / 4, 4 };
696     return k.run(2, globalsize, (flipType == FLIP_COLS) && !dev.isIntel() ? localsize : NULL, false);
697 }
698
699 #endif
700
701 #if defined HAVE_IPP
702 static bool ipp_flip(Mat &src, Mat &dst, int flip_mode)
703 {
704 #ifdef HAVE_IPP_IW
705     CV_INSTRUMENT_REGION_IPP()
706
707     IppiAxis ippMode;
708     if(flip_mode < 0)
709         ippMode = ippAxsBoth;
710     else if(flip_mode == 0)
711         ippMode = ippAxsHorizontal;
712     else
713         ippMode = ippAxsVertical;
714
715     try
716     {
717         ::ipp::IwiImage iwSrc = ippiGetImage(src);
718         ::ipp::IwiImage iwDst = ippiGetImage(dst);
719
720         CV_INSTRUMENT_FUN_IPP(::ipp::iwiMirror, iwSrc, iwDst, ippMode);
721     }
722     catch(::ipp::IwException)
723     {
724         return false;
725     }
726
727     return true;
728 #else
729     CV_UNUSED(src); CV_UNUSED(dst); CV_UNUSED(flip_mode);
730     return false;
731 #endif
732 }
733 #endif
734
735
736 void flip( InputArray _src, OutputArray _dst, int flip_mode )
737 {
738     CV_INSTRUMENT_REGION()
739
740     CV_Assert( _src.dims() <= 2 );
741     Size size = _src.size();
742
743     if (flip_mode < 0)
744     {
745         if (size.width == 1)
746             flip_mode = 0;
747         if (size.height == 1)
748             flip_mode = 1;
749     }
750
751     if ((size.width == 1 && flip_mode > 0) ||
752         (size.height == 1 && flip_mode == 0) ||
753         (size.height == 1 && size.width == 1 && flip_mode < 0))
754     {
755         return _src.copyTo(_dst);
756     }
757
758     CV_OCL_RUN( _dst.isUMat(), ocl_flip(_src, _dst, flip_mode))
759
760     Mat src = _src.getMat();
761     int type = src.type();
762     _dst.create( size, type );
763     Mat dst = _dst.getMat();
764
765     CV_IPP_RUN_FAST(ipp_flip(src, dst, flip_mode));
766
767     size_t esz = CV_ELEM_SIZE(type);
768
769     if( flip_mode <= 0 )
770         flipVert( src.ptr(), src.step, dst.ptr(), dst.step, src.size(), esz );
771     else
772         flipHoriz( src.ptr(), src.step, dst.ptr(), dst.step, src.size(), esz );
773
774     if( flip_mode < 0 )
775         flipHoriz( dst.ptr(), dst.step, dst.ptr(), dst.step, dst.size(), esz );
776 }
777
778 #ifdef HAVE_OPENCL
779
780 static bool ocl_rotate(InputArray _src, OutputArray _dst, int rotateMode)
781 {
782     switch (rotateMode)
783     {
784     case ROTATE_90_CLOCKWISE:
785         transpose(_src, _dst);
786         flip(_dst, _dst, 1);
787         break;
788     case ROTATE_180:
789         flip(_src, _dst, -1);
790         break;
791     case ROTATE_90_COUNTERCLOCKWISE:
792         transpose(_src, _dst);
793         flip(_dst, _dst, 0);
794         break;
795     default:
796         break;
797     }
798     return true;
799 }
800 #endif
801
802 void rotate(InputArray _src, OutputArray _dst, int rotateMode)
803 {
804     CV_Assert(_src.dims() <= 2);
805
806     CV_OCL_RUN(_dst.isUMat(), ocl_rotate(_src, _dst, rotateMode))
807
808     switch (rotateMode)
809     {
810     case ROTATE_90_CLOCKWISE:
811         transpose(_src, _dst);
812         flip(_dst, _dst, 1);
813         break;
814     case ROTATE_180:
815         flip(_src, _dst, -1);
816         break;
817     case ROTATE_90_COUNTERCLOCKWISE:
818         transpose(_src, _dst);
819         flip(_dst, _dst, 0);
820         break;
821     default:
822         break;
823     }
824 }
825
826 #if defined HAVE_OPENCL && !defined __APPLE__
827
828 static bool ocl_repeat(InputArray _src, int ny, int nx, OutputArray _dst)
829 {
830     if (ny == 1 && nx == 1)
831     {
832         _src.copyTo(_dst);
833         return true;
834     }
835
836     int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type),
837             rowsPerWI = ocl::Device::getDefault().isIntel() ? 4 : 1,
838             kercn = ocl::predictOptimalVectorWidth(_src, _dst);
839
840     ocl::Kernel k("repeat", ocl::core::repeat_oclsrc,
841                   format("-D T=%s -D nx=%d -D ny=%d -D rowsPerWI=%d -D cn=%d",
842                          ocl::memopTypeToStr(CV_MAKE_TYPE(depth, kercn)),
843                          nx, ny, rowsPerWI, kercn));
844     if (k.empty())
845         return false;
846
847     UMat src = _src.getUMat(), dst = _dst.getUMat();
848     k.args(ocl::KernelArg::ReadOnly(src, cn, kercn), ocl::KernelArg::WriteOnlyNoSize(dst));
849
850     size_t globalsize[] = { (size_t)src.cols * cn / kercn, ((size_t)src.rows + rowsPerWI - 1) / rowsPerWI };
851     return k.run(2, globalsize, NULL, false);
852 }
853
854 #endif
855
856 void repeat(InputArray _src, int ny, int nx, OutputArray _dst)
857 {
858     CV_INSTRUMENT_REGION()
859
860     CV_Assert(_src.getObj() != _dst.getObj());
861     CV_Assert( _src.dims() <= 2 );
862     CV_Assert( ny > 0 && nx > 0 );
863
864     Size ssize = _src.size();
865     _dst.create(ssize.height*ny, ssize.width*nx, _src.type());
866
867 #if !defined __APPLE__
868     CV_OCL_RUN(_dst.isUMat(),
869                ocl_repeat(_src, ny, nx, _dst))
870 #endif
871
872     Mat src = _src.getMat(), dst = _dst.getMat();
873     Size dsize = dst.size();
874     int esz = (int)src.elemSize();
875     int x, y;
876     ssize.width *= esz; dsize.width *= esz;
877
878     for( y = 0; y < ssize.height; y++ )
879     {
880         for( x = 0; x < dsize.width; x += ssize.width )
881             memcpy( dst.ptr(y) + x, src.ptr(y), ssize.width );
882     }
883
884     for( ; y < dsize.height; y++ )
885         memcpy( dst.ptr(y), dst.ptr(y - ssize.height), dsize.width );
886 }
887
888 Mat repeat(const Mat& src, int ny, int nx)
889 {
890     if( nx == 1 && ny == 1 )
891         return src;
892     Mat dst;
893     repeat(src, ny, nx, dst);
894     return dst;
895 }
896
897
898 } // cv
899
900
901 /*
902  Various border types, image boundaries are denoted with '|'
903
904  * BORDER_REPLICATE:     aaaaaa|abcdefgh|hhhhhhh
905  * BORDER_REFLECT:       fedcba|abcdefgh|hgfedcb
906  * BORDER_REFLECT_101:   gfedcb|abcdefgh|gfedcba
907  * BORDER_WRAP:          cdefgh|abcdefgh|abcdefg
908  * BORDER_CONSTANT:      iiiiii|abcdefgh|iiiiiii  with some specified 'i'
909  */
910 int cv::borderInterpolate( int p, int len, int borderType )
911 {
912     CV_TRACE_FUNCTION_VERBOSE();
913
914     if( (unsigned)p < (unsigned)len )
915         ;
916     else if( borderType == BORDER_REPLICATE )
917         p = p < 0 ? 0 : len - 1;
918     else if( borderType == BORDER_REFLECT || borderType == BORDER_REFLECT_101 )
919     {
920         int delta = borderType == BORDER_REFLECT_101;
921         if( len == 1 )
922             return 0;
923         do
924         {
925             if( p < 0 )
926                 p = -p - 1 + delta;
927             else
928                 p = len - 1 - (p - len) - delta;
929         }
930         while( (unsigned)p >= (unsigned)len );
931     }
932     else if( borderType == BORDER_WRAP )
933     {
934         CV_Assert(len > 0);
935         if( p < 0 )
936             p -= ((p-len+1)/len)*len;
937         if( p >= len )
938             p %= len;
939     }
940     else if( borderType == BORDER_CONSTANT )
941         p = -1;
942     else
943         CV_Error( CV_StsBadArg, "Unknown/unsupported border type" );
944     return p;
945 }
946
947 namespace
948 {
949
950 void copyMakeBorder_8u( const uchar* src, size_t srcstep, cv::Size srcroi,
951                         uchar* dst, size_t dststep, cv::Size dstroi,
952                         int top, int left, int cn, int borderType )
953 {
954     const int isz = (int)sizeof(int);
955     int i, j, k, elemSize = 1;
956     bool intMode = false;
957
958     if( (cn | srcstep | dststep | (size_t)src | (size_t)dst) % isz == 0 )
959     {
960         cn /= isz;
961         elemSize = isz;
962         intMode = true;
963     }
964
965     cv::AutoBuffer<int> _tab((dstroi.width - srcroi.width)*cn);
966     int* tab = _tab.data();
967     int right = dstroi.width - srcroi.width - left;
968     int bottom = dstroi.height - srcroi.height - top;
969
970     for( i = 0; i < left; i++ )
971     {
972         j = cv::borderInterpolate(i - left, srcroi.width, borderType)*cn;
973         for( k = 0; k < cn; k++ )
974             tab[i*cn + k] = j + k;
975     }
976
977     for( i = 0; i < right; i++ )
978     {
979         j = cv::borderInterpolate(srcroi.width + i, srcroi.width, borderType)*cn;
980         for( k = 0; k < cn; k++ )
981             tab[(i+left)*cn + k] = j + k;
982     }
983
984     srcroi.width *= cn;
985     dstroi.width *= cn;
986     left *= cn;
987     right *= cn;
988
989     uchar* dstInner = dst + dststep*top + left*elemSize;
990
991     for( i = 0; i < srcroi.height; i++, dstInner += dststep, src += srcstep )
992     {
993         if( dstInner != src )
994             memcpy(dstInner, src, srcroi.width*elemSize);
995
996         if( intMode )
997         {
998             const int* isrc = (int*)src;
999             int* idstInner = (int*)dstInner;
1000             for( j = 0; j < left; j++ )
1001                 idstInner[j - left] = isrc[tab[j]];
1002             for( j = 0; j < right; j++ )
1003                 idstInner[j + srcroi.width] = isrc[tab[j + left]];
1004         }
1005         else
1006         {
1007             for( j = 0; j < left; j++ )
1008                 dstInner[j - left] = src[tab[j]];
1009             for( j = 0; j < right; j++ )
1010                 dstInner[j + srcroi.width] = src[tab[j + left]];
1011         }
1012     }
1013
1014     dstroi.width *= elemSize;
1015     dst += dststep*top;
1016
1017     for( i = 0; i < top; i++ )
1018     {
1019         j = cv::borderInterpolate(i - top, srcroi.height, borderType);
1020         memcpy(dst + (i - top)*dststep, dst + j*dststep, dstroi.width);
1021     }
1022
1023     for( i = 0; i < bottom; i++ )
1024     {
1025         j = cv::borderInterpolate(i + srcroi.height, srcroi.height, borderType);
1026         memcpy(dst + (i + srcroi.height)*dststep, dst + j*dststep, dstroi.width);
1027     }
1028 }
1029
1030
1031 void copyMakeConstBorder_8u( const uchar* src, size_t srcstep, cv::Size srcroi,
1032                              uchar* dst, size_t dststep, cv::Size dstroi,
1033                              int top, int left, int cn, const uchar* value )
1034 {
1035     int i, j;
1036     cv::AutoBuffer<uchar> _constBuf(dstroi.width*cn);
1037     uchar* constBuf = _constBuf.data();
1038     int right = dstroi.width - srcroi.width - left;
1039     int bottom = dstroi.height - srcroi.height - top;
1040
1041     for( i = 0; i < dstroi.width; i++ )
1042     {
1043         for( j = 0; j < cn; j++ )
1044             constBuf[i*cn + j] = value[j];
1045     }
1046
1047     srcroi.width *= cn;
1048     dstroi.width *= cn;
1049     left *= cn;
1050     right *= cn;
1051
1052     uchar* dstInner = dst + dststep*top + left;
1053
1054     for( i = 0; i < srcroi.height; i++, dstInner += dststep, src += srcstep )
1055     {
1056         if( dstInner != src )
1057             memcpy( dstInner, src, srcroi.width );
1058         memcpy( dstInner - left, constBuf, left );
1059         memcpy( dstInner + srcroi.width, constBuf, right );
1060     }
1061
1062     dst += dststep*top;
1063
1064     for( i = 0; i < top; i++ )
1065         memcpy(dst + (i - top)*dststep, constBuf, dstroi.width);
1066
1067     for( i = 0; i < bottom; i++ )
1068         memcpy(dst + (i + srcroi.height)*dststep, constBuf, dstroi.width);
1069 }
1070
1071 }
1072
1073 #ifdef HAVE_OPENCL
1074
1075 namespace cv {
1076
1077 static bool ocl_copyMakeBorder( InputArray _src, OutputArray _dst, int top, int bottom,
1078                                 int left, int right, int borderType, const Scalar& value )
1079 {
1080     int type = _src.type(), cn = CV_MAT_CN(type), depth = CV_MAT_DEPTH(type),
1081             rowsPerWI = ocl::Device::getDefault().isIntel() ? 4 : 1;
1082     bool isolated = (borderType & BORDER_ISOLATED) != 0;
1083     borderType &= ~cv::BORDER_ISOLATED;
1084
1085     if ( !(borderType == BORDER_CONSTANT || borderType == BORDER_REPLICATE || borderType == BORDER_REFLECT ||
1086            borderType == BORDER_WRAP || borderType == BORDER_REFLECT_101) ||
1087          cn > 4)
1088         return false;
1089
1090     const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", "BORDER_WRAP", "BORDER_REFLECT_101" };
1091     int scalarcn = cn == 3 ? 4 : cn;
1092     int sctype = CV_MAKETYPE(depth, scalarcn);
1093     String buildOptions = format("-D T=%s -D %s -D T1=%s -D cn=%d -D ST=%s -D rowsPerWI=%d",
1094                                  ocl::memopTypeToStr(type), borderMap[borderType],
1095                                  ocl::memopTypeToStr(depth), cn,
1096                                  ocl::memopTypeToStr(sctype), rowsPerWI);
1097
1098     ocl::Kernel k("copyMakeBorder", ocl::core::copymakeborder_oclsrc, buildOptions);
1099     if (k.empty())
1100         return false;
1101
1102     UMat src = _src.getUMat();
1103     if( src.isSubmatrix() && !isolated )
1104     {
1105         Size wholeSize;
1106         Point ofs;
1107         src.locateROI(wholeSize, ofs);
1108         int dtop = std::min(ofs.y, top);
1109         int dbottom = std::min(wholeSize.height - src.rows - ofs.y, bottom);
1110         int dleft = std::min(ofs.x, left);
1111         int dright = std::min(wholeSize.width - src.cols - ofs.x, right);
1112         src.adjustROI(dtop, dbottom, dleft, dright);
1113         top -= dtop;
1114         left -= dleft;
1115         bottom -= dbottom;
1116         right -= dright;
1117     }
1118
1119     _dst.create(src.rows + top + bottom, src.cols + left + right, type);
1120     UMat dst = _dst.getUMat();
1121
1122     if (top == 0 && left == 0 && bottom == 0 && right == 0)
1123     {
1124         if(src.u != dst.u || src.step != dst.step)
1125             src.copyTo(dst);
1126         return true;
1127     }
1128
1129     k.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::WriteOnly(dst),
1130            top, left, ocl::KernelArg::Constant(Mat(1, 1, sctype, value)));
1131
1132     size_t globalsize[2] = { (size_t)dst.cols, ((size_t)dst.rows + rowsPerWI - 1) / rowsPerWI };
1133     return k.run(2, globalsize, NULL, false);
1134 }
1135
1136 }
1137 #endif
1138
1139 #ifdef HAVE_IPP
1140 namespace cv {
1141
1142 static bool ipp_copyMakeBorder( Mat &_src, Mat &_dst, int top, int bottom,
1143                                 int left, int right, int _borderType, const Scalar& value )
1144 {
1145 #if defined HAVE_IPP_IW && !IPP_DISABLE_PERF_COPYMAKE
1146     CV_INSTRUMENT_REGION_IPP()
1147
1148     ::ipp::IwiBorderSize borderSize(left, top, right, bottom);
1149     ::ipp::IwiSize       size(_src.cols, _src.rows);
1150     IppDataType          dataType   = ippiGetDataType(_src.depth());
1151     IppiBorderType       borderType = ippiGetBorderType(_borderType);
1152     if((int)borderType == -1)
1153         return false;
1154
1155     if(_src.dims > 2)
1156         return false;
1157
1158     Rect dstRect(borderSize.left, borderSize.top,
1159         _dst.cols - borderSize.right - borderSize.left,
1160         _dst.rows - borderSize.bottom - borderSize.top);
1161     Mat  subDst = Mat(_dst, dstRect);
1162     Mat *pSrc   = &_src;
1163
1164     return CV_INSTRUMENT_FUN_IPP(llwiCopyMakeBorder, pSrc->ptr(), pSrc->step, subDst.ptr(), subDst.step, size, dataType, _src.channels(), borderSize, borderType, &value[0]) >= 0;
1165 #else
1166     CV_UNUSED(_src); CV_UNUSED(_dst); CV_UNUSED(top); CV_UNUSED(bottom); CV_UNUSED(left); CV_UNUSED(right);
1167     CV_UNUSED(_borderType); CV_UNUSED(value);
1168     return false;
1169 #endif
1170 }
1171 }
1172 #endif
1173
1174 void cv::copyMakeBorder( InputArray _src, OutputArray _dst, int top, int bottom,
1175                          int left, int right, int borderType, const Scalar& value )
1176 {
1177     CV_INSTRUMENT_REGION()
1178
1179     CV_Assert( top >= 0 && bottom >= 0 && left >= 0 && right >= 0 );
1180
1181     CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2,
1182                ocl_copyMakeBorder(_src, _dst, top, bottom, left, right, borderType, value))
1183
1184     Mat src = _src.getMat();
1185     int type = src.type();
1186
1187     if( src.isSubmatrix() && (borderType & BORDER_ISOLATED) == 0 )
1188     {
1189         Size wholeSize;
1190         Point ofs;
1191         src.locateROI(wholeSize, ofs);
1192         int dtop = std::min(ofs.y, top);
1193         int dbottom = std::min(wholeSize.height - src.rows - ofs.y, bottom);
1194         int dleft = std::min(ofs.x, left);
1195         int dright = std::min(wholeSize.width - src.cols - ofs.x, right);
1196         src.adjustROI(dtop, dbottom, dleft, dright);
1197         top -= dtop;
1198         left -= dleft;
1199         bottom -= dbottom;
1200         right -= dright;
1201     }
1202
1203     _dst.create( src.rows + top + bottom, src.cols + left + right, type );
1204     Mat dst = _dst.getMat();
1205
1206     if(top == 0 && left == 0 && bottom == 0 && right == 0)
1207     {
1208         if(src.data != dst.data || src.step != dst.step)
1209             src.copyTo(dst);
1210         return;
1211     }
1212
1213     borderType &= ~BORDER_ISOLATED;
1214
1215     CV_IPP_RUN_FAST(ipp_copyMakeBorder(src, dst, top, bottom, left, right, borderType, value))
1216
1217     if( borderType != BORDER_CONSTANT )
1218         copyMakeBorder_8u( src.ptr(), src.step, src.size(),
1219                            dst.ptr(), dst.step, dst.size(),
1220                            top, left, (int)src.elemSize(), borderType );
1221     else
1222     {
1223         int cn = src.channels(), cn1 = cn;
1224         AutoBuffer<double> buf(cn);
1225         if( cn > 4 )
1226         {
1227             CV_Assert( value[0] == value[1] && value[0] == value[2] && value[0] == value[3] );
1228             cn1 = 1;
1229         }
1230         scalarToRawData(value, buf.data(), CV_MAKETYPE(src.depth(), cn1), cn);
1231         copyMakeConstBorder_8u( src.ptr(), src.step, src.size(),
1232                                 dst.ptr(), dst.step, dst.size(),
1233                                 top, left, (int)src.elemSize(), (uchar*)buf.data() );
1234     }
1235 }
1236
1237 /* dst = src */
1238 CV_IMPL void
1239 cvCopy( const void* srcarr, void* dstarr, const void* maskarr )
1240 {
1241     if( CV_IS_SPARSE_MAT(srcarr) && CV_IS_SPARSE_MAT(dstarr))
1242     {
1243         CV_Assert( maskarr == 0 );
1244         CvSparseMat* src1 = (CvSparseMat*)srcarr;
1245         CvSparseMat* dst1 = (CvSparseMat*)dstarr;
1246         CvSparseMatIterator iterator;
1247         CvSparseNode* node;
1248
1249         dst1->dims = src1->dims;
1250         memcpy( dst1->size, src1->size, src1->dims*sizeof(src1->size[0]));
1251         dst1->valoffset = src1->valoffset;
1252         dst1->idxoffset = src1->idxoffset;
1253         cvClearSet( dst1->heap );
1254
1255         if( src1->heap->active_count >= dst1->hashsize*CV_SPARSE_HASH_RATIO )
1256         {
1257             cvFree( &dst1->hashtable );
1258             dst1->hashsize = src1->hashsize;
1259             dst1->hashtable =
1260                 (void**)cvAlloc( dst1->hashsize*sizeof(dst1->hashtable[0]));
1261         }
1262
1263         memset( dst1->hashtable, 0, dst1->hashsize*sizeof(dst1->hashtable[0]));
1264
1265         for( node = cvInitSparseMatIterator( src1, &iterator );
1266              node != 0; node = cvGetNextSparseNode( &iterator ))
1267         {
1268             CvSparseNode* node_copy = (CvSparseNode*)cvSetNew( dst1->heap );
1269             int tabidx = node->hashval & (dst1->hashsize - 1);
1270             memcpy( node_copy, node, dst1->heap->elem_size );
1271             node_copy->next = (CvSparseNode*)dst1->hashtable[tabidx];
1272             dst1->hashtable[tabidx] = node_copy;
1273         }
1274         return;
1275     }
1276     cv::Mat src = cv::cvarrToMat(srcarr, false, true, 1), dst = cv::cvarrToMat(dstarr, false, true, 1);
1277     CV_Assert( src.depth() == dst.depth() && src.size == dst.size );
1278
1279     int coi1 = 0, coi2 = 0;
1280     if( CV_IS_IMAGE(srcarr) )
1281         coi1 = cvGetImageCOI((const IplImage*)srcarr);
1282     if( CV_IS_IMAGE(dstarr) )
1283         coi2 = cvGetImageCOI((const IplImage*)dstarr);
1284
1285     if( coi1 || coi2 )
1286     {
1287         CV_Assert( (coi1 != 0 || src.channels() == 1) &&
1288             (coi2 != 0 || dst.channels() == 1) );
1289
1290         int pair[] = { std::max(coi1-1, 0), std::max(coi2-1, 0) };
1291         cv::mixChannels( &src, 1, &dst, 1, pair, 1 );
1292         return;
1293     }
1294     else
1295         CV_Assert( src.channels() == dst.channels() );
1296
1297     if( !maskarr )
1298         src.copyTo(dst);
1299     else
1300         src.copyTo(dst, cv::cvarrToMat(maskarr));
1301 }
1302
1303 CV_IMPL void
1304 cvSet( void* arr, CvScalar value, const void* maskarr )
1305 {
1306     cv::Mat m = cv::cvarrToMat(arr);
1307     if( !maskarr )
1308         m = value;
1309     else
1310         m.setTo(cv::Scalar(value), cv::cvarrToMat(maskarr));
1311 }
1312
1313 CV_IMPL void
1314 cvSetZero( CvArr* arr )
1315 {
1316     if( CV_IS_SPARSE_MAT(arr) )
1317     {
1318         CvSparseMat* mat1 = (CvSparseMat*)arr;
1319         cvClearSet( mat1->heap );
1320         if( mat1->hashtable )
1321             memset( mat1->hashtable, 0, mat1->hashsize*sizeof(mat1->hashtable[0]));
1322         return;
1323     }
1324     cv::Mat m = cv::cvarrToMat(arr);
1325     m = cv::Scalar(0);
1326 }
1327
1328 CV_IMPL void
1329 cvFlip( const CvArr* srcarr, CvArr* dstarr, int flip_mode )
1330 {
1331     cv::Mat src = cv::cvarrToMat(srcarr);
1332     cv::Mat dst;
1333
1334     if (!dstarr)
1335       dst = src;
1336     else
1337       dst = cv::cvarrToMat(dstarr);
1338
1339     CV_Assert( src.type() == dst.type() && src.size() == dst.size() );
1340     cv::flip( src, dst, flip_mode );
1341 }
1342
1343 CV_IMPL void
1344 cvRepeat( const CvArr* srcarr, CvArr* dstarr )
1345 {
1346     cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
1347     CV_Assert( src.type() == dst.type() &&
1348         dst.rows % src.rows == 0 && dst.cols % src.cols == 0 );
1349     cv::repeat(src, dst.rows/src.rows, dst.cols/src.cols, dst);
1350 }
1351
1352 /* End of file. */