8775bff4aa945583d4c3acedf0804d59915f31c4
[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 (empty()) return *this;
415
416     const Mat* arrays[] = { this };
417     uchar* dptr;
418     NAryMatIterator it(arrays, &dptr, 1);
419     size_t elsize = it.size*elemSize();
420     const int64* is = (const int64*)&s.val[0];
421
422     if( is[0] == 0 && is[1] == 0 && is[2] == 0 && is[3] == 0 )
423     {
424         for( size_t i = 0; i < it.nplanes; i++, ++it )
425             memset( dptr, 0, elsize );
426     }
427     else
428     {
429         if( it.nplanes > 0 )
430         {
431             double scalar[12];
432             scalarToRawData(s, scalar, type(), 12);
433             size_t blockSize = 12*elemSize1();
434
435             for( size_t j = 0; j < elsize; j += blockSize )
436             {
437                 size_t sz = MIN(blockSize, elsize - j);
438                 CV_Assert(sz <= sizeof(scalar));
439                 memcpy( dptr + j, scalar, sz );
440             }
441         }
442
443         for( size_t i = 1; i < it.nplanes; i++ )
444         {
445             ++it;
446             memcpy( dptr, data, elsize );
447         }
448     }
449     return *this;
450 }
451
452 #ifdef HAVE_IPP
453 static bool ipp_Mat_setTo_Mat(Mat &dst, Mat &_val, Mat &mask)
454 {
455 #ifdef HAVE_IPP_IW
456     CV_INSTRUMENT_REGION_IPP()
457
458     if(mask.empty())
459         return false;
460
461     if(mask.depth() != CV_8U || mask.channels() > 1)
462         return false;
463
464     if(dst.channels() > 4)
465         return false;
466
467     if (dst.depth() == CV_32F)
468     {
469         for (int i = 0; i < (int)(_val.total()); i++)
470         {
471             float v = (float)(_val.at<double>(i));  // cast to float
472             if (cvIsNaN(v) || cvIsInf(v))  // accept finite numbers only
473                 return false;
474         }
475     }
476
477     if(dst.dims <= 2)
478     {
479         IppiSize            size     = ippiSize(dst.size());
480         IppDataType         dataType = ippiGetDataType(dst.depth());
481         ::ipp::IwValueFloat s;
482         convertAndUnrollScalar(_val, CV_MAKETYPE(CV_64F, dst.channels()), (uchar*)((Ipp64f*)s), 1);
483
484         return CV_INSTRUMENT_FUN_IPP(llwiSetMask, s, dst.ptr(), (int)dst.step, size, dataType, dst.channels(), mask.ptr(), (int)mask.step) >= 0;
485     }
486     else
487     {
488         const Mat      *arrays[] = {&dst, mask.empty()?NULL:&mask, NULL};
489         uchar          *ptrs[2]  = {NULL};
490         NAryMatIterator it(arrays, ptrs);
491
492         IppiSize            size     = {(int)it.size, 1};
493         IppDataType         dataType = ippiGetDataType(dst.depth());
494         ::ipp::IwValueFloat s;
495         convertAndUnrollScalar(_val, CV_MAKETYPE(CV_64F, dst.channels()), (uchar*)((Ipp64f*)s), 1);
496
497         for( size_t i = 0; i < it.nplanes; i++, ++it)
498         {
499             if(CV_INSTRUMENT_FUN_IPP(llwiSetMask, s, ptrs[0], 0, size, dataType, dst.channels(), ptrs[1], 0) < 0)
500                 return false;
501         }
502         return true;
503     }
504 #else
505     CV_UNUSED(dst); CV_UNUSED(_val); CV_UNUSED(mask);
506     return false;
507 #endif
508 }
509 #endif
510
511 Mat& Mat::setTo(InputArray _value, InputArray _mask)
512 {
513     CV_INSTRUMENT_REGION()
514
515     if( empty() )
516         return *this;
517
518     Mat value = _value.getMat(), mask = _mask.getMat();
519
520     CV_Assert( checkScalar(value, type(), _value.kind(), _InputArray::MAT ));
521     int cn = channels(), mcn = mask.channels();
522     CV_Assert( mask.empty() || (mask.depth() == CV_8U && (mcn == 1 || mcn == cn) && size == mask.size) );
523
524     CV_IPP_RUN_FAST(ipp_Mat_setTo_Mat(*this, value, mask), *this)
525
526     size_t esz = mcn > 1 ? elemSize1() : elemSize();
527     BinaryFunc copymask = getCopyMaskFunc(esz);
528
529     const Mat* arrays[] = { this, !mask.empty() ? &mask : 0, 0 };
530     uchar* ptrs[2]={0,0};
531     NAryMatIterator it(arrays, ptrs);
532     int totalsz = (int)it.size*mcn;
533     int blockSize0 = std::min(totalsz, (int)((BLOCK_SIZE + esz-1)/esz));
534     blockSize0 -= blockSize0 % mcn;    // must be divisible without remainder for unrolling and advancing
535     AutoBuffer<uchar> _scbuf(blockSize0*esz + 32);
536     uchar* scbuf = alignPtr((uchar*)_scbuf.data(), (int)sizeof(double));
537     convertAndUnrollScalar( value, type(), scbuf, blockSize0/mcn );
538
539     for( size_t i = 0; i < it.nplanes; i++, ++it )
540     {
541         for( int j = 0; j < totalsz; j += blockSize0 )
542         {
543             Size sz(std::min(blockSize0, totalsz - j), 1);
544             size_t blockSize = sz.width*esz;
545             if( ptrs[1] )
546             {
547                 copymask(scbuf, 0, ptrs[1], 0, ptrs[0], 0, sz, &esz);
548                 ptrs[1] += sz.width;
549             }
550             else
551                 memcpy(ptrs[0], scbuf, blockSize);
552             ptrs[0] += blockSize;
553         }
554     }
555     return *this;
556 }
557
558
559 static void
560 flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, size_t esz )
561 {
562     int i, j, limit = (int)(((size.width + 1)/2)*esz);
563     AutoBuffer<int> _tab(size.width*esz);
564     int* tab = _tab.data();
565
566     for( i = 0; i < size.width; i++ )
567         for( size_t k = 0; k < esz; k++ )
568             tab[i*esz + k] = (int)((size.width - i - 1)*esz + k);
569
570     for( ; size.height--; src += sstep, dst += dstep )
571     {
572         for( i = 0; i < limit; i++ )
573         {
574             j = tab[i];
575             uchar t0 = src[i], t1 = src[j];
576             dst[i] = t1; dst[j] = t0;
577         }
578     }
579 }
580
581 static void
582 flipVert( const uchar* src0, size_t sstep, uchar* dst0, size_t dstep, Size size, size_t esz )
583 {
584     const uchar* src1 = src0 + (size.height - 1)*sstep;
585     uchar* dst1 = dst0 + (size.height - 1)*dstep;
586     size.width *= (int)esz;
587
588     for( int y = 0; y < (size.height + 1)/2; y++, src0 += sstep, src1 -= sstep,
589                                                   dst0 += dstep, dst1 -= dstep )
590     {
591         int i = 0;
592         if( ((size_t)src0|(size_t)dst0|(size_t)src1|(size_t)dst1) % sizeof(int) == 0 )
593         {
594             for( ; i <= size.width - 16; i += 16 )
595             {
596                 int t0 = ((int*)(src0 + i))[0];
597                 int t1 = ((int*)(src1 + i))[0];
598
599                 ((int*)(dst0 + i))[0] = t1;
600                 ((int*)(dst1 + i))[0] = t0;
601
602                 t0 = ((int*)(src0 + i))[1];
603                 t1 = ((int*)(src1 + i))[1];
604
605                 ((int*)(dst0 + i))[1] = t1;
606                 ((int*)(dst1 + i))[1] = t0;
607
608                 t0 = ((int*)(src0 + i))[2];
609                 t1 = ((int*)(src1 + i))[2];
610
611                 ((int*)(dst0 + i))[2] = t1;
612                 ((int*)(dst1 + i))[2] = t0;
613
614                 t0 = ((int*)(src0 + i))[3];
615                 t1 = ((int*)(src1 + i))[3];
616
617                 ((int*)(dst0 + i))[3] = t1;
618                 ((int*)(dst1 + i))[3] = t0;
619             }
620
621             for( ; i <= size.width - 4; i += 4 )
622             {
623                 int t0 = ((int*)(src0 + i))[0];
624                 int t1 = ((int*)(src1 + i))[0];
625
626                 ((int*)(dst0 + i))[0] = t1;
627                 ((int*)(dst1 + i))[0] = t0;
628             }
629         }
630
631         for( ; i < size.width; i++ )
632         {
633             uchar t0 = src0[i];
634             uchar t1 = src1[i];
635
636             dst0[i] = t1;
637             dst1[i] = t0;
638         }
639     }
640 }
641
642 #ifdef HAVE_OPENCL
643
644 enum { FLIP_COLS = 1 << 0, FLIP_ROWS = 1 << 1, FLIP_BOTH = FLIP_ROWS | FLIP_COLS };
645
646 static bool ocl_flip(InputArray _src, OutputArray _dst, int flipCode )
647 {
648     CV_Assert(flipCode >= -1 && flipCode <= 1);
649
650     const ocl::Device & dev = ocl::Device::getDefault();
651     int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type),
652             flipType, kercn = std::min(ocl::predictOptimalVectorWidth(_src, _dst), 4);
653
654     bool doubleSupport = dev.doubleFPConfig() > 0;
655     if (!doubleSupport && depth == CV_64F)
656         kercn = cn;
657
658     if (cn > 4)
659         return false;
660
661     const char * kernelName;
662     if (flipCode == 0)
663         kernelName = "arithm_flip_rows", flipType = FLIP_ROWS;
664     else if (flipCode > 0)
665         kernelName = "arithm_flip_cols", flipType = FLIP_COLS;
666     else
667         kernelName = "arithm_flip_rows_cols", flipType = FLIP_BOTH;
668
669     int pxPerWIy = (dev.isIntel() && (dev.type() & ocl::Device::TYPE_GPU)) ? 4 : 1;
670     kercn = (cn!=3 || flipType == FLIP_ROWS) ? std::max(kercn, cn) : cn;
671
672     ocl::Kernel k(kernelName, ocl::core::flip_oclsrc,
673         format( "-D T=%s -D T1=%s -D cn=%d -D PIX_PER_WI_Y=%d -D kercn=%d",
674                 kercn != cn ? ocl::typeToStr(CV_MAKE_TYPE(depth, kercn)) : ocl::vecopTypeToStr(CV_MAKE_TYPE(depth, kercn)),
675                 kercn != cn ? ocl::typeToStr(depth) : ocl::vecopTypeToStr(depth), cn, pxPerWIy, kercn));
676     if (k.empty())
677         return false;
678
679     Size size = _src.size();
680     _dst.create(size, type);
681     UMat src = _src.getUMat(), dst = _dst.getUMat();
682
683     int cols = size.width * cn / kercn, rows = size.height;
684     cols = flipType == FLIP_COLS ? (cols + 1) >> 1 : cols;
685     rows = flipType & FLIP_ROWS ? (rows + 1) >> 1 : rows;
686
687     k.args(ocl::KernelArg::ReadOnlyNoSize(src),
688            ocl::KernelArg::WriteOnly(dst, cn, kercn), rows, cols);
689
690     size_t maxWorkGroupSize = dev.maxWorkGroupSize();
691     CV_Assert(maxWorkGroupSize % 4 == 0);
692
693     size_t globalsize[2] = { (size_t)cols, ((size_t)rows + pxPerWIy - 1) / pxPerWIy },
694             localsize[2] = { maxWorkGroupSize / 4, 4 };
695     return k.run(2, globalsize, (flipType == FLIP_COLS) && !dev.isIntel() ? localsize : NULL, false);
696 }
697
698 #endif
699
700 #if defined HAVE_IPP
701 static bool ipp_flip(Mat &src, Mat &dst, int flip_mode)
702 {
703 #ifdef HAVE_IPP_IW
704     CV_INSTRUMENT_REGION_IPP()
705
706     IppiAxis ippMode;
707     if(flip_mode < 0)
708         ippMode = ippAxsBoth;
709     else if(flip_mode == 0)
710         ippMode = ippAxsHorizontal;
711     else
712         ippMode = ippAxsVertical;
713
714     try
715     {
716         ::ipp::IwiImage iwSrc = ippiGetImage(src);
717         ::ipp::IwiImage iwDst = ippiGetImage(dst);
718
719         CV_INSTRUMENT_FUN_IPP(::ipp::iwiMirror, iwSrc, iwDst, ippMode);
720     }
721     catch(::ipp::IwException)
722     {
723         return false;
724     }
725
726     return true;
727 #else
728     CV_UNUSED(src); CV_UNUSED(dst); CV_UNUSED(flip_mode);
729     return false;
730 #endif
731 }
732 #endif
733
734
735 void flip( InputArray _src, OutputArray _dst, int flip_mode )
736 {
737     CV_INSTRUMENT_REGION()
738
739     CV_Assert( _src.dims() <= 2 );
740     Size size = _src.size();
741
742     if (flip_mode < 0)
743     {
744         if (size.width == 1)
745             flip_mode = 0;
746         if (size.height == 1)
747             flip_mode = 1;
748     }
749
750     if ((size.width == 1 && flip_mode > 0) ||
751         (size.height == 1 && flip_mode == 0) ||
752         (size.height == 1 && size.width == 1 && flip_mode < 0))
753     {
754         return _src.copyTo(_dst);
755     }
756
757     CV_OCL_RUN( _dst.isUMat(), ocl_flip(_src, _dst, flip_mode))
758
759     Mat src = _src.getMat();
760     int type = src.type();
761     _dst.create( size, type );
762     Mat dst = _dst.getMat();
763
764     CV_IPP_RUN_FAST(ipp_flip(src, dst, flip_mode));
765
766     size_t esz = CV_ELEM_SIZE(type);
767
768     if( flip_mode <= 0 )
769         flipVert( src.ptr(), src.step, dst.ptr(), dst.step, src.size(), esz );
770     else
771         flipHoriz( src.ptr(), src.step, dst.ptr(), dst.step, src.size(), esz );
772
773     if( flip_mode < 0 )
774         flipHoriz( dst.ptr(), dst.step, dst.ptr(), dst.step, dst.size(), esz );
775 }
776
777 #ifdef HAVE_OPENCL
778
779 static bool ocl_rotate(InputArray _src, OutputArray _dst, int rotateMode)
780 {
781     switch (rotateMode)
782     {
783     case ROTATE_90_CLOCKWISE:
784         transpose(_src, _dst);
785         flip(_dst, _dst, 1);
786         break;
787     case ROTATE_180:
788         flip(_src, _dst, -1);
789         break;
790     case ROTATE_90_COUNTERCLOCKWISE:
791         transpose(_src, _dst);
792         flip(_dst, _dst, 0);
793         break;
794     default:
795         break;
796     }
797     return true;
798 }
799 #endif
800
801 void rotate(InputArray _src, OutputArray _dst, int rotateMode)
802 {
803     CV_Assert(_src.dims() <= 2);
804
805     CV_OCL_RUN(_dst.isUMat(), ocl_rotate(_src, _dst, rotateMode))
806
807     switch (rotateMode)
808     {
809     case ROTATE_90_CLOCKWISE:
810         transpose(_src, _dst);
811         flip(_dst, _dst, 1);
812         break;
813     case ROTATE_180:
814         flip(_src, _dst, -1);
815         break;
816     case ROTATE_90_COUNTERCLOCKWISE:
817         transpose(_src, _dst);
818         flip(_dst, _dst, 0);
819         break;
820     default:
821         break;
822     }
823 }
824
825 #if defined HAVE_OPENCL && !defined __APPLE__
826
827 static bool ocl_repeat(InputArray _src, int ny, int nx, OutputArray _dst)
828 {
829     if (ny == 1 && nx == 1)
830     {
831         _src.copyTo(_dst);
832         return true;
833     }
834
835     int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type),
836             rowsPerWI = ocl::Device::getDefault().isIntel() ? 4 : 1,
837             kercn = ocl::predictOptimalVectorWidth(_src, _dst);
838
839     ocl::Kernel k("repeat", ocl::core::repeat_oclsrc,
840                   format("-D T=%s -D nx=%d -D ny=%d -D rowsPerWI=%d -D cn=%d",
841                          ocl::memopTypeToStr(CV_MAKE_TYPE(depth, kercn)),
842                          nx, ny, rowsPerWI, kercn));
843     if (k.empty())
844         return false;
845
846     UMat src = _src.getUMat(), dst = _dst.getUMat();
847     k.args(ocl::KernelArg::ReadOnly(src, cn, kercn), ocl::KernelArg::WriteOnlyNoSize(dst));
848
849     size_t globalsize[] = { (size_t)src.cols * cn / kercn, ((size_t)src.rows + rowsPerWI - 1) / rowsPerWI };
850     return k.run(2, globalsize, NULL, false);
851 }
852
853 #endif
854
855 void repeat(InputArray _src, int ny, int nx, OutputArray _dst)
856 {
857     CV_INSTRUMENT_REGION()
858
859     CV_Assert(_src.getObj() != _dst.getObj());
860     CV_Assert( _src.dims() <= 2 );
861     CV_Assert( ny > 0 && nx > 0 );
862
863     Size ssize = _src.size();
864     _dst.create(ssize.height*ny, ssize.width*nx, _src.type());
865
866 #if !defined __APPLE__
867     CV_OCL_RUN(_dst.isUMat(),
868                ocl_repeat(_src, ny, nx, _dst))
869 #endif
870
871     Mat src = _src.getMat(), dst = _dst.getMat();
872     Size dsize = dst.size();
873     int esz = (int)src.elemSize();
874     int x, y;
875     ssize.width *= esz; dsize.width *= esz;
876
877     for( y = 0; y < ssize.height; y++ )
878     {
879         for( x = 0; x < dsize.width; x += ssize.width )
880             memcpy( dst.ptr(y) + x, src.ptr(y), ssize.width );
881     }
882
883     for( ; y < dsize.height; y++ )
884         memcpy( dst.ptr(y), dst.ptr(y - ssize.height), dsize.width );
885 }
886
887 Mat repeat(const Mat& src, int ny, int nx)
888 {
889     if( nx == 1 && ny == 1 )
890         return src;
891     Mat dst;
892     repeat(src, ny, nx, dst);
893     return dst;
894 }
895
896
897 } // cv
898
899
900 /*
901  Various border types, image boundaries are denoted with '|'
902
903  * BORDER_REPLICATE:     aaaaaa|abcdefgh|hhhhhhh
904  * BORDER_REFLECT:       fedcba|abcdefgh|hgfedcb
905  * BORDER_REFLECT_101:   gfedcb|abcdefgh|gfedcba
906  * BORDER_WRAP:          cdefgh|abcdefgh|abcdefg
907  * BORDER_CONSTANT:      iiiiii|abcdefgh|iiiiiii  with some specified 'i'
908  */
909 int cv::borderInterpolate( int p, int len, int borderType )
910 {
911     CV_TRACE_FUNCTION_VERBOSE();
912
913     if( (unsigned)p < (unsigned)len )
914         ;
915     else if( borderType == BORDER_REPLICATE )
916         p = p < 0 ? 0 : len - 1;
917     else if( borderType == BORDER_REFLECT || borderType == BORDER_REFLECT_101 )
918     {
919         int delta = borderType == BORDER_REFLECT_101;
920         if( len == 1 )
921             return 0;
922         do
923         {
924             if( p < 0 )
925                 p = -p - 1 + delta;
926             else
927                 p = len - 1 - (p - len) - delta;
928         }
929         while( (unsigned)p >= (unsigned)len );
930     }
931     else if( borderType == BORDER_WRAP )
932     {
933         CV_Assert(len > 0);
934         if( p < 0 )
935             p -= ((p-len+1)/len)*len;
936         if( p >= len )
937             p %= len;
938     }
939     else if( borderType == BORDER_CONSTANT )
940         p = -1;
941     else
942         CV_Error( CV_StsBadArg, "Unknown/unsupported border type" );
943     return p;
944 }
945
946 namespace
947 {
948
949 void copyMakeBorder_8u( const uchar* src, size_t srcstep, cv::Size srcroi,
950                         uchar* dst, size_t dststep, cv::Size dstroi,
951                         int top, int left, int cn, int borderType )
952 {
953     const int isz = (int)sizeof(int);
954     int i, j, k, elemSize = 1;
955     bool intMode = false;
956
957     if( (cn | srcstep | dststep | (size_t)src | (size_t)dst) % isz == 0 )
958     {
959         cn /= isz;
960         elemSize = isz;
961         intMode = true;
962     }
963
964     cv::AutoBuffer<int> _tab((dstroi.width - srcroi.width)*cn);
965     int* tab = _tab.data();
966     int right = dstroi.width - srcroi.width - left;
967     int bottom = dstroi.height - srcroi.height - top;
968
969     for( i = 0; i < left; i++ )
970     {
971         j = cv::borderInterpolate(i - left, srcroi.width, borderType)*cn;
972         for( k = 0; k < cn; k++ )
973             tab[i*cn + k] = j + k;
974     }
975
976     for( i = 0; i < right; i++ )
977     {
978         j = cv::borderInterpolate(srcroi.width + i, srcroi.width, borderType)*cn;
979         for( k = 0; k < cn; k++ )
980             tab[(i+left)*cn + k] = j + k;
981     }
982
983     srcroi.width *= cn;
984     dstroi.width *= cn;
985     left *= cn;
986     right *= cn;
987
988     uchar* dstInner = dst + dststep*top + left*elemSize;
989
990     for( i = 0; i < srcroi.height; i++, dstInner += dststep, src += srcstep )
991     {
992         if( dstInner != src )
993             memcpy(dstInner, src, srcroi.width*elemSize);
994
995         if( intMode )
996         {
997             const int* isrc = (int*)src;
998             int* idstInner = (int*)dstInner;
999             for( j = 0; j < left; j++ )
1000                 idstInner[j - left] = isrc[tab[j]];
1001             for( j = 0; j < right; j++ )
1002                 idstInner[j + srcroi.width] = isrc[tab[j + left]];
1003         }
1004         else
1005         {
1006             for( j = 0; j < left; j++ )
1007                 dstInner[j - left] = src[tab[j]];
1008             for( j = 0; j < right; j++ )
1009                 dstInner[j + srcroi.width] = src[tab[j + left]];
1010         }
1011     }
1012
1013     dstroi.width *= elemSize;
1014     dst += dststep*top;
1015
1016     for( i = 0; i < top; i++ )
1017     {
1018         j = cv::borderInterpolate(i - top, srcroi.height, borderType);
1019         memcpy(dst + (i - top)*dststep, dst + j*dststep, dstroi.width);
1020     }
1021
1022     for( i = 0; i < bottom; i++ )
1023     {
1024         j = cv::borderInterpolate(i + srcroi.height, srcroi.height, borderType);
1025         memcpy(dst + (i + srcroi.height)*dststep, dst + j*dststep, dstroi.width);
1026     }
1027 }
1028
1029
1030 void copyMakeConstBorder_8u( const uchar* src, size_t srcstep, cv::Size srcroi,
1031                              uchar* dst, size_t dststep, cv::Size dstroi,
1032                              int top, int left, int cn, const uchar* value )
1033 {
1034     int i, j;
1035     cv::AutoBuffer<uchar> _constBuf(dstroi.width*cn);
1036     uchar* constBuf = _constBuf.data();
1037     int right = dstroi.width - srcroi.width - left;
1038     int bottom = dstroi.height - srcroi.height - top;
1039
1040     for( i = 0; i < dstroi.width; i++ )
1041     {
1042         for( j = 0; j < cn; j++ )
1043             constBuf[i*cn + j] = value[j];
1044     }
1045
1046     srcroi.width *= cn;
1047     dstroi.width *= cn;
1048     left *= cn;
1049     right *= cn;
1050
1051     uchar* dstInner = dst + dststep*top + left;
1052
1053     for( i = 0; i < srcroi.height; i++, dstInner += dststep, src += srcstep )
1054     {
1055         if( dstInner != src )
1056             memcpy( dstInner, src, srcroi.width );
1057         memcpy( dstInner - left, constBuf, left );
1058         memcpy( dstInner + srcroi.width, constBuf, right );
1059     }
1060
1061     dst += dststep*top;
1062
1063     for( i = 0; i < top; i++ )
1064         memcpy(dst + (i - top)*dststep, constBuf, dstroi.width);
1065
1066     for( i = 0; i < bottom; i++ )
1067         memcpy(dst + (i + srcroi.height)*dststep, constBuf, dstroi.width);
1068 }
1069
1070 }
1071
1072 #ifdef HAVE_OPENCL
1073
1074 namespace cv {
1075
1076 static bool ocl_copyMakeBorder( InputArray _src, OutputArray _dst, int top, int bottom,
1077                                 int left, int right, int borderType, const Scalar& value )
1078 {
1079     int type = _src.type(), cn = CV_MAT_CN(type), depth = CV_MAT_DEPTH(type),
1080             rowsPerWI = ocl::Device::getDefault().isIntel() ? 4 : 1;
1081     bool isolated = (borderType & BORDER_ISOLATED) != 0;
1082     borderType &= ~cv::BORDER_ISOLATED;
1083
1084     if ( !(borderType == BORDER_CONSTANT || borderType == BORDER_REPLICATE || borderType == BORDER_REFLECT ||
1085            borderType == BORDER_WRAP || borderType == BORDER_REFLECT_101) ||
1086          cn > 4)
1087         return false;
1088
1089     const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", "BORDER_WRAP", "BORDER_REFLECT_101" };
1090     int scalarcn = cn == 3 ? 4 : cn;
1091     int sctype = CV_MAKETYPE(depth, scalarcn);
1092     String buildOptions = format("-D T=%s -D %s -D T1=%s -D cn=%d -D ST=%s -D rowsPerWI=%d",
1093                                  ocl::memopTypeToStr(type), borderMap[borderType],
1094                                  ocl::memopTypeToStr(depth), cn,
1095                                  ocl::memopTypeToStr(sctype), rowsPerWI);
1096
1097     ocl::Kernel k("copyMakeBorder", ocl::core::copymakeborder_oclsrc, buildOptions);
1098     if (k.empty())
1099         return false;
1100
1101     UMat src = _src.getUMat();
1102     if( src.isSubmatrix() && !isolated )
1103     {
1104         Size wholeSize;
1105         Point ofs;
1106         src.locateROI(wholeSize, ofs);
1107         int dtop = std::min(ofs.y, top);
1108         int dbottom = std::min(wholeSize.height - src.rows - ofs.y, bottom);
1109         int dleft = std::min(ofs.x, left);
1110         int dright = std::min(wholeSize.width - src.cols - ofs.x, right);
1111         src.adjustROI(dtop, dbottom, dleft, dright);
1112         top -= dtop;
1113         left -= dleft;
1114         bottom -= dbottom;
1115         right -= dright;
1116     }
1117
1118     _dst.create(src.rows + top + bottom, src.cols + left + right, type);
1119     UMat dst = _dst.getUMat();
1120
1121     if (top == 0 && left == 0 && bottom == 0 && right == 0)
1122     {
1123         if(src.u != dst.u || src.step != dst.step)
1124             src.copyTo(dst);
1125         return true;
1126     }
1127
1128     k.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::WriteOnly(dst),
1129            top, left, ocl::KernelArg::Constant(Mat(1, 1, sctype, value)));
1130
1131     size_t globalsize[2] = { (size_t)dst.cols, ((size_t)dst.rows + rowsPerWI - 1) / rowsPerWI };
1132     return k.run(2, globalsize, NULL, false);
1133 }
1134
1135 }
1136 #endif
1137
1138 #ifdef HAVE_IPP
1139 namespace cv {
1140
1141 static bool ipp_copyMakeBorder( Mat &_src, Mat &_dst, int top, int bottom,
1142                                 int left, int right, int _borderType, const Scalar& value )
1143 {
1144 #if defined HAVE_IPP_IW && !IPP_DISABLE_PERF_COPYMAKE
1145     CV_INSTRUMENT_REGION_IPP()
1146
1147     ::ipp::IwiBorderSize borderSize(left, top, right, bottom);
1148     ::ipp::IwiSize       size(_src.cols, _src.rows);
1149     IppDataType          dataType   = ippiGetDataType(_src.depth());
1150     IppiBorderType       borderType = ippiGetBorderType(_borderType);
1151     if((int)borderType == -1)
1152         return false;
1153
1154     if(_src.dims > 2)
1155         return false;
1156
1157     Rect dstRect(borderSize.left, borderSize.top,
1158         _dst.cols - borderSize.right - borderSize.left,
1159         _dst.rows - borderSize.bottom - borderSize.top);
1160     Mat  subDst = Mat(_dst, dstRect);
1161     Mat *pSrc   = &_src;
1162
1163     return CV_INSTRUMENT_FUN_IPP(llwiCopyMakeBorder, pSrc->ptr(), pSrc->step, subDst.ptr(), subDst.step, size, dataType, _src.channels(), borderSize, borderType, &value[0]) >= 0;
1164 #else
1165     CV_UNUSED(_src); CV_UNUSED(_dst); CV_UNUSED(top); CV_UNUSED(bottom); CV_UNUSED(left); CV_UNUSED(right);
1166     CV_UNUSED(_borderType); CV_UNUSED(value);
1167     return false;
1168 #endif
1169 }
1170 }
1171 #endif
1172
1173 void cv::copyMakeBorder( InputArray _src, OutputArray _dst, int top, int bottom,
1174                          int left, int right, int borderType, const Scalar& value )
1175 {
1176     CV_INSTRUMENT_REGION()
1177
1178     CV_Assert( top >= 0 && bottom >= 0 && left >= 0 && right >= 0 );
1179
1180     CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2,
1181                ocl_copyMakeBorder(_src, _dst, top, bottom, left, right, borderType, value))
1182
1183     Mat src = _src.getMat();
1184     int type = src.type();
1185
1186     if( src.isSubmatrix() && (borderType & BORDER_ISOLATED) == 0 )
1187     {
1188         Size wholeSize;
1189         Point ofs;
1190         src.locateROI(wholeSize, ofs);
1191         int dtop = std::min(ofs.y, top);
1192         int dbottom = std::min(wholeSize.height - src.rows - ofs.y, bottom);
1193         int dleft = std::min(ofs.x, left);
1194         int dright = std::min(wholeSize.width - src.cols - ofs.x, right);
1195         src.adjustROI(dtop, dbottom, dleft, dright);
1196         top -= dtop;
1197         left -= dleft;
1198         bottom -= dbottom;
1199         right -= dright;
1200     }
1201
1202     _dst.create( src.rows + top + bottom, src.cols + left + right, type );
1203     Mat dst = _dst.getMat();
1204
1205     if(top == 0 && left == 0 && bottom == 0 && right == 0)
1206     {
1207         if(src.data != dst.data || src.step != dst.step)
1208             src.copyTo(dst);
1209         return;
1210     }
1211
1212     borderType &= ~BORDER_ISOLATED;
1213
1214     CV_IPP_RUN_FAST(ipp_copyMakeBorder(src, dst, top, bottom, left, right, borderType, value))
1215
1216     if( borderType != BORDER_CONSTANT )
1217         copyMakeBorder_8u( src.ptr(), src.step, src.size(),
1218                            dst.ptr(), dst.step, dst.size(),
1219                            top, left, (int)src.elemSize(), borderType );
1220     else
1221     {
1222         int cn = src.channels(), cn1 = cn;
1223         AutoBuffer<double> buf(cn);
1224         if( cn > 4 )
1225         {
1226             CV_Assert( value[0] == value[1] && value[0] == value[2] && value[0] == value[3] );
1227             cn1 = 1;
1228         }
1229         scalarToRawData(value, buf.data(), CV_MAKETYPE(src.depth(), cn1), cn);
1230         copyMakeConstBorder_8u( src.ptr(), src.step, src.size(),
1231                                 dst.ptr(), dst.step, dst.size(),
1232                                 top, left, (int)src.elemSize(), (uchar*)buf.data() );
1233     }
1234 }
1235
1236 /* dst = src */
1237 CV_IMPL void
1238 cvCopy( const void* srcarr, void* dstarr, const void* maskarr )
1239 {
1240     if( CV_IS_SPARSE_MAT(srcarr) && CV_IS_SPARSE_MAT(dstarr))
1241     {
1242         CV_Assert( maskarr == 0 );
1243         CvSparseMat* src1 = (CvSparseMat*)srcarr;
1244         CvSparseMat* dst1 = (CvSparseMat*)dstarr;
1245         CvSparseMatIterator iterator;
1246         CvSparseNode* node;
1247
1248         dst1->dims = src1->dims;
1249         memcpy( dst1->size, src1->size, src1->dims*sizeof(src1->size[0]));
1250         dst1->valoffset = src1->valoffset;
1251         dst1->idxoffset = src1->idxoffset;
1252         cvClearSet( dst1->heap );
1253
1254         if( src1->heap->active_count >= dst1->hashsize*CV_SPARSE_HASH_RATIO )
1255         {
1256             cvFree( &dst1->hashtable );
1257             dst1->hashsize = src1->hashsize;
1258             dst1->hashtable =
1259                 (void**)cvAlloc( dst1->hashsize*sizeof(dst1->hashtable[0]));
1260         }
1261
1262         memset( dst1->hashtable, 0, dst1->hashsize*sizeof(dst1->hashtable[0]));
1263
1264         for( node = cvInitSparseMatIterator( src1, &iterator );
1265              node != 0; node = cvGetNextSparseNode( &iterator ))
1266         {
1267             CvSparseNode* node_copy = (CvSparseNode*)cvSetNew( dst1->heap );
1268             int tabidx = node->hashval & (dst1->hashsize - 1);
1269             memcpy( node_copy, node, dst1->heap->elem_size );
1270             node_copy->next = (CvSparseNode*)dst1->hashtable[tabidx];
1271             dst1->hashtable[tabidx] = node_copy;
1272         }
1273         return;
1274     }
1275     cv::Mat src = cv::cvarrToMat(srcarr, false, true, 1), dst = cv::cvarrToMat(dstarr, false, true, 1);
1276     CV_Assert( src.depth() == dst.depth() && src.size == dst.size );
1277
1278     int coi1 = 0, coi2 = 0;
1279     if( CV_IS_IMAGE(srcarr) )
1280         coi1 = cvGetImageCOI((const IplImage*)srcarr);
1281     if( CV_IS_IMAGE(dstarr) )
1282         coi2 = cvGetImageCOI((const IplImage*)dstarr);
1283
1284     if( coi1 || coi2 )
1285     {
1286         CV_Assert( (coi1 != 0 || src.channels() == 1) &&
1287             (coi2 != 0 || dst.channels() == 1) );
1288
1289         int pair[] = { std::max(coi1-1, 0), std::max(coi2-1, 0) };
1290         cv::mixChannels( &src, 1, &dst, 1, pair, 1 );
1291         return;
1292     }
1293     else
1294         CV_Assert( src.channels() == dst.channels() );
1295
1296     if( !maskarr )
1297         src.copyTo(dst);
1298     else
1299         src.copyTo(dst, cv::cvarrToMat(maskarr));
1300 }
1301
1302 CV_IMPL void
1303 cvSet( void* arr, CvScalar value, const void* maskarr )
1304 {
1305     cv::Mat m = cv::cvarrToMat(arr);
1306     if( !maskarr )
1307         m = value;
1308     else
1309         m.setTo(cv::Scalar(value), cv::cvarrToMat(maskarr));
1310 }
1311
1312 CV_IMPL void
1313 cvSetZero( CvArr* arr )
1314 {
1315     if( CV_IS_SPARSE_MAT(arr) )
1316     {
1317         CvSparseMat* mat1 = (CvSparseMat*)arr;
1318         cvClearSet( mat1->heap );
1319         if( mat1->hashtable )
1320             memset( mat1->hashtable, 0, mat1->hashsize*sizeof(mat1->hashtable[0]));
1321         return;
1322     }
1323     cv::Mat m = cv::cvarrToMat(arr);
1324     m = cv::Scalar(0);
1325 }
1326
1327 CV_IMPL void
1328 cvFlip( const CvArr* srcarr, CvArr* dstarr, int flip_mode )
1329 {
1330     cv::Mat src = cv::cvarrToMat(srcarr);
1331     cv::Mat dst;
1332
1333     if (!dstarr)
1334       dst = src;
1335     else
1336       dst = cv::cvarrToMat(dstarr);
1337
1338     CV_Assert( src.type() == dst.type() && src.size() == dst.size() );
1339     cv::flip( src, dst, flip_mode );
1340 }
1341
1342 CV_IMPL void
1343 cvRepeat( const CvArr* srcarr, CvArr* dstarr )
1344 {
1345     cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
1346     CV_Assert( src.type() == dst.type() &&
1347         dst.rows % src.rows == 0 && dst.cols % src.cols == 0 );
1348     cv::repeat(src, dst.rows/src.rows, dst.cols/src.cols, dst);
1349 }
1350
1351 /* End of file. */