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