Merge pull request #3158 from arielelkin:master
[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
619     const ocl::Device & dev = ocl::Device::getDefault();
620     int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type),
621             flipType, kercn = std::min(ocl::predictOptimalVectorWidth(_src, _dst), 4);
622
623     bool doubleSupport = dev.doubleFPConfig() > 0;
624     if (!doubleSupport && depth == CV_64F)
625         kercn = cn;
626
627     if (cn > 4)
628         return false;
629
630     const char * kernelName;
631     if (flipCode == 0)
632         kernelName = "arithm_flip_rows", flipType = FLIP_ROWS;
633     else if (flipCode > 0)
634         kernelName = "arithm_flip_cols", flipType = FLIP_COLS;
635     else
636         kernelName = "arithm_flip_rows_cols", flipType = FLIP_BOTH;
637
638     int pxPerWIy = (dev.isIntel() && (dev.type() & ocl::Device::TYPE_GPU)) ? 4 : 1;
639     kercn = (cn!=3 || flipType == FLIP_ROWS) ? std::max(kercn, cn) : cn;
640
641     ocl::Kernel k(kernelName, ocl::core::flip_oclsrc,
642         format( "-D T=%s -D T1=%s -D cn=%d -D PIX_PER_WI_Y=%d -D kercn=%d",
643                 kercn != cn ? ocl::typeToStr(CV_MAKE_TYPE(depth, kercn)) : ocl::memopTypeToStr(CV_MAKE_TYPE(depth, kercn)),
644                 kercn != cn ? ocl::typeToStr(depth) : ocl::memopTypeToStr(depth), cn, pxPerWIy, kercn));
645     if (k.empty())
646         return false;
647
648     Size size = _src.size();
649     _dst.create(size, type);
650     UMat src = _src.getUMat(), dst = _dst.getUMat();
651
652     int cols = size.width * cn / kercn, rows = size.height;
653     cols = flipType == FLIP_COLS ? (cols + 1) >> 1 : cols;
654     rows = flipType & FLIP_ROWS ? (rows + 1) >> 1 : rows;
655
656     k.args(ocl::KernelArg::ReadOnlyNoSize(src),
657            ocl::KernelArg::WriteOnly(dst, cn, kercn), rows, cols);
658
659     size_t maxWorkGroupSize = dev.maxWorkGroupSize();
660     CV_Assert(maxWorkGroupSize % 4 == 0);
661
662     size_t globalsize[2] = { cols, (rows + pxPerWIy - 1) / pxPerWIy },
663             localsize[2] = { maxWorkGroupSize / 4, 4 };
664     return k.run(2, globalsize, (flipType == FLIP_COLS) && !dev.isIntel() ? localsize : NULL, false);
665 }
666
667 #endif
668
669 void flip( InputArray _src, OutputArray _dst, int flip_mode )
670 {
671     CV_Assert( _src.dims() <= 2 );
672     Size size = _src.size();
673
674     if (flip_mode < 0)
675     {
676         if (size.width == 1)
677             flip_mode = 0;
678         if (size.height == 1)
679             flip_mode = 1;
680     }
681
682     if ((size.width == 1 && flip_mode > 0) ||
683         (size.height == 1 && flip_mode == 0) ||
684         (size.height == 1 && size.width == 1 && flip_mode < 0))
685     {
686         return _src.copyTo(_dst);
687     }
688
689     CV_OCL_RUN( _dst.isUMat(), ocl_flip(_src, _dst, flip_mode))
690
691     Mat src = _src.getMat();
692     int type = src.type();
693     _dst.create( size, type );
694     Mat dst = _dst.getMat();
695     size_t esz = CV_ELEM_SIZE(type);
696
697 #if defined HAVE_IPP
698     typedef IppStatus (CV_STDCALL * ippiMirror)(const void * pSrc, int srcStep, void * pDst, int dstStep, IppiSize roiSize, IppiAxis flip);
699     typedef IppStatus (CV_STDCALL * ippiMirrorI)(const void * pSrcDst, int srcDstStep, IppiSize roiSize, IppiAxis flip);
700     ippiMirror ippFunc = 0;
701     ippiMirrorI ippFuncI = 0;
702
703     if (src.data == dst.data)
704     {
705         CV_SUPPRESS_DEPRECATED_START
706         ippFuncI =
707             type == CV_8UC1 ? (ippiMirrorI)ippiMirror_8u_C1IR :
708             type == CV_8UC3 ? (ippiMirrorI)ippiMirror_8u_C3IR :
709             type == CV_8UC4 ? (ippiMirrorI)ippiMirror_8u_C4IR :
710             type == CV_16UC1 ? (ippiMirrorI)ippiMirror_16u_C1IR :
711             type == CV_16UC3 ? (ippiMirrorI)ippiMirror_16u_C3IR :
712             type == CV_16UC4 ? (ippiMirrorI)ippiMirror_16u_C4IR :
713             type == CV_16SC1 ? (ippiMirrorI)ippiMirror_16s_C1IR :
714             type == CV_16SC3 ? (ippiMirrorI)ippiMirror_16s_C3IR :
715             type == CV_16SC4 ? (ippiMirrorI)ippiMirror_16s_C4IR :
716             type == CV_32SC1 ? (ippiMirrorI)ippiMirror_32s_C1IR :
717             type == CV_32SC3 ? (ippiMirrorI)ippiMirror_32s_C3IR :
718             type == CV_32SC4 ? (ippiMirrorI)ippiMirror_32s_C4IR :
719             type == CV_32FC1 ? (ippiMirrorI)ippiMirror_32f_C1IR :
720             type == CV_32FC3 ? (ippiMirrorI)ippiMirror_32f_C3IR :
721             type == CV_32FC4 ? (ippiMirrorI)ippiMirror_32f_C4IR : 0;
722         CV_SUPPRESS_DEPRECATED_END
723     }
724     else
725     {
726         ippFunc =
727             type == CV_8UC1 ? (ippiMirror)ippiMirror_8u_C1R :
728             type == CV_8UC3 ? (ippiMirror)ippiMirror_8u_C3R :
729             type == CV_8UC4 ? (ippiMirror)ippiMirror_8u_C4R :
730             type == CV_16UC1 ? (ippiMirror)ippiMirror_16u_C1R :
731             type == CV_16UC3 ? (ippiMirror)ippiMirror_16u_C3R :
732             type == CV_16UC4 ? (ippiMirror)ippiMirror_16u_C4R :
733             type == CV_16SC1 ? (ippiMirror)ippiMirror_16s_C1R :
734             type == CV_16SC3 ? (ippiMirror)ippiMirror_16s_C3R :
735             type == CV_16SC4 ? (ippiMirror)ippiMirror_16s_C4R :
736             type == CV_32SC1 ? (ippiMirror)ippiMirror_32s_C1R :
737             type == CV_32SC3 ? (ippiMirror)ippiMirror_32s_C3R :
738             type == CV_32SC4 ? (ippiMirror)ippiMirror_32s_C4R :
739             type == CV_32FC1 ? (ippiMirror)ippiMirror_32f_C1R :
740             type == CV_32FC3 ? (ippiMirror)ippiMirror_32f_C3R :
741             type == CV_32FC4 ? (ippiMirror)ippiMirror_32f_C4R : 0;
742     }
743     IppiAxis axis = flip_mode == 0 ? ippAxsHorizontal :
744         flip_mode > 0 ? ippAxsVertical : ippAxsBoth;
745     IppiSize roisize = { dst.cols, dst.rows };
746
747     if (ippFunc != 0)
748     {
749         if (ippFunc(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, ippiSize(src.cols, src.rows), axis) >= 0)
750             return;
751         setIppErrorStatus();
752     }
753     else if (ippFuncI != 0)
754     {
755         if (ippFuncI(dst.ptr(), (int)dst.step, roisize, axis) >= 0)
756             return;
757         setIppErrorStatus();
758     }
759 #endif
760
761     if( flip_mode <= 0 )
762         flipVert( src.ptr(), src.step, dst.ptr(), dst.step, src.size(), esz );
763     else
764         flipHoriz( src.ptr(), src.step, dst.ptr(), dst.step, src.size(), esz );
765
766     if( flip_mode < 0 )
767         flipHoriz( dst.ptr(), dst.step, dst.ptr(), dst.step, dst.size(), esz );
768 }
769
770 #if defined HAVE_OPENCL && !defined __APPLE__
771
772 static bool ocl_repeat(InputArray _src, int ny, int nx, OutputArray _dst)
773 {
774     if (ny == 1 && nx == 1)
775     {
776         _src.copyTo(_dst);
777         return true;
778     }
779
780     int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type),
781             rowsPerWI = ocl::Device::getDefault().isIntel() ? 4 : 1,
782             kercn = std::min(ocl::predictOptimalVectorWidth(_src, _dst), 4);
783
784     ocl::Kernel k("repeat", ocl::core::repeat_oclsrc,
785                   format("-D T=%s -D nx=%d -D ny=%d -D rowsPerWI=%d -D cn=%d",
786                          ocl::memopTypeToStr(CV_MAKE_TYPE(depth, kercn)),
787                          nx, ny, rowsPerWI, kercn));
788     if (k.empty())
789         return false;
790
791     UMat src = _src.getUMat(), dst = _dst.getUMat();
792     k.args(ocl::KernelArg::ReadOnly(src, cn, kercn), ocl::KernelArg::WriteOnlyNoSize(dst));
793
794     size_t globalsize[] = { src.cols * cn / kercn, (src.rows + rowsPerWI - 1) / rowsPerWI };
795     return k.run(2, globalsize, NULL, false);
796 }
797
798 #endif
799
800 void repeat(InputArray _src, int ny, int nx, OutputArray _dst)
801 {
802     CV_Assert( _src.dims() <= 2 );
803     CV_Assert( ny > 0 && nx > 0 );
804
805     Size ssize = _src.size();
806     _dst.create(ssize.height*ny, ssize.width*nx, _src.type());
807
808 #if !defined __APPLE__
809     CV_OCL_RUN(_dst.isUMat(),
810                ocl_repeat(_src, ny, nx, _dst))
811 #endif
812
813     Mat src = _src.getMat(), dst = _dst.getMat();
814     Size dsize = dst.size();
815     int esz = (int)src.elemSize();
816     int x, y;
817     ssize.width *= esz; dsize.width *= esz;
818
819     for( y = 0; y < ssize.height; y++ )
820     {
821         for( x = 0; x < dsize.width; x += ssize.width )
822             memcpy( dst.ptr(y) + x, src.ptr(y), ssize.width );
823     }
824
825     for( ; y < dsize.height; y++ )
826         memcpy( dst.ptr(y), dst.ptr(y - ssize.height), dsize.width );
827 }
828
829 Mat repeat(const Mat& src, int ny, int nx)
830 {
831     if( nx == 1 && ny == 1 )
832         return src;
833     Mat dst;
834     repeat(src, ny, nx, dst);
835     return dst;
836 }
837
838
839 } // cv
840
841
842 /*
843  Various border types, image boundaries are denoted with '|'
844
845  * BORDER_REPLICATE:     aaaaaa|abcdefgh|hhhhhhh
846  * BORDER_REFLECT:       fedcba|abcdefgh|hgfedcb
847  * BORDER_REFLECT_101:   gfedcb|abcdefgh|gfedcba
848  * BORDER_WRAP:          cdefgh|abcdefgh|abcdefg
849  * BORDER_CONSTANT:      iiiiii|abcdefgh|iiiiiii  with some specified 'i'
850  */
851 int cv::borderInterpolate( int p, int len, int borderType )
852 {
853     if( (unsigned)p < (unsigned)len )
854         ;
855     else if( borderType == BORDER_REPLICATE )
856         p = p < 0 ? 0 : len - 1;
857     else if( borderType == BORDER_REFLECT || borderType == BORDER_REFLECT_101 )
858     {
859         int delta = borderType == BORDER_REFLECT_101;
860         if( len == 1 )
861             return 0;
862         do
863         {
864             if( p < 0 )
865                 p = -p - 1 + delta;
866             else
867                 p = len - 1 - (p - len) - delta;
868         }
869         while( (unsigned)p >= (unsigned)len );
870     }
871     else if( borderType == BORDER_WRAP )
872     {
873         CV_Assert(len > 0);
874         if( p < 0 )
875             p -= ((p-len+1)/len)*len;
876         if( p >= len )
877             p %= len;
878     }
879     else if( borderType == BORDER_CONSTANT )
880         p = -1;
881     else
882         CV_Error( CV_StsBadArg, "Unknown/unsupported border type" );
883     return p;
884 }
885
886 namespace
887 {
888
889 void copyMakeBorder_8u( const uchar* src, size_t srcstep, cv::Size srcroi,
890                         uchar* dst, size_t dststep, cv::Size dstroi,
891                         int top, int left, int cn, int borderType )
892 {
893     const int isz = (int)sizeof(int);
894     int i, j, k, elemSize = 1;
895     bool intMode = false;
896
897     if( (cn | srcstep | dststep | (size_t)src | (size_t)dst) % isz == 0 )
898     {
899         cn /= isz;
900         elemSize = isz;
901         intMode = true;
902     }
903
904     cv::AutoBuffer<int> _tab((dstroi.width - srcroi.width)*cn);
905     int* tab = _tab;
906     int right = dstroi.width - srcroi.width - left;
907     int bottom = dstroi.height - srcroi.height - top;
908
909     for( i = 0; i < left; i++ )
910     {
911         j = cv::borderInterpolate(i - left, srcroi.width, borderType)*cn;
912         for( k = 0; k < cn; k++ )
913             tab[i*cn + k] = j + k;
914     }
915
916     for( i = 0; i < right; i++ )
917     {
918         j = cv::borderInterpolate(srcroi.width + i, srcroi.width, borderType)*cn;
919         for( k = 0; k < cn; k++ )
920             tab[(i+left)*cn + k] = j + k;
921     }
922
923     srcroi.width *= cn;
924     dstroi.width *= cn;
925     left *= cn;
926     right *= cn;
927
928     uchar* dstInner = dst + dststep*top + left*elemSize;
929
930     for( i = 0; i < srcroi.height; i++, dstInner += dststep, src += srcstep )
931     {
932         if( dstInner != src )
933             memcpy(dstInner, src, srcroi.width*elemSize);
934
935         if( intMode )
936         {
937             const int* isrc = (int*)src;
938             int* idstInner = (int*)dstInner;
939             for( j = 0; j < left; j++ )
940                 idstInner[j - left] = isrc[tab[j]];
941             for( j = 0; j < right; j++ )
942                 idstInner[j + srcroi.width] = isrc[tab[j + left]];
943         }
944         else
945         {
946             for( j = 0; j < left; j++ )
947                 dstInner[j - left] = src[tab[j]];
948             for( j = 0; j < right; j++ )
949                 dstInner[j + srcroi.width] = src[tab[j + left]];
950         }
951     }
952
953     dstroi.width *= elemSize;
954     dst += dststep*top;
955
956     for( i = 0; i < top; i++ )
957     {
958         j = cv::borderInterpolate(i - top, srcroi.height, borderType);
959         memcpy(dst + (i - top)*dststep, dst + j*dststep, dstroi.width);
960     }
961
962     for( i = 0; i < bottom; i++ )
963     {
964         j = cv::borderInterpolate(i + srcroi.height, srcroi.height, borderType);
965         memcpy(dst + (i + srcroi.height)*dststep, dst + j*dststep, dstroi.width);
966     }
967 }
968
969
970 void copyMakeConstBorder_8u( const uchar* src, size_t srcstep, cv::Size srcroi,
971                              uchar* dst, size_t dststep, cv::Size dstroi,
972                              int top, int left, int cn, const uchar* value )
973 {
974     int i, j;
975     cv::AutoBuffer<uchar> _constBuf(dstroi.width*cn);
976     uchar* constBuf = _constBuf;
977     int right = dstroi.width - srcroi.width - left;
978     int bottom = dstroi.height - srcroi.height - top;
979
980     for( i = 0; i < dstroi.width; i++ )
981     {
982         for( j = 0; j < cn; j++ )
983             constBuf[i*cn + j] = value[j];
984     }
985
986     srcroi.width *= cn;
987     dstroi.width *= cn;
988     left *= cn;
989     right *= cn;
990
991     uchar* dstInner = dst + dststep*top + left;
992
993     for( i = 0; i < srcroi.height; i++, dstInner += dststep, src += srcstep )
994     {
995         if( dstInner != src )
996             memcpy( dstInner, src, srcroi.width );
997         memcpy( dstInner - left, constBuf, left );
998         memcpy( dstInner + srcroi.width, constBuf, right );
999     }
1000
1001     dst += dststep*top;
1002
1003     for( i = 0; i < top; i++ )
1004         memcpy(dst + (i - top)*dststep, constBuf, dstroi.width);
1005
1006     for( i = 0; i < bottom; i++ )
1007         memcpy(dst + (i + srcroi.height)*dststep, constBuf, dstroi.width);
1008 }
1009
1010 }
1011
1012 #ifdef HAVE_OPENCL
1013
1014 namespace cv {
1015
1016 static bool ocl_copyMakeBorder( InputArray _src, OutputArray _dst, int top, int bottom,
1017                                 int left, int right, int borderType, const Scalar& value )
1018 {
1019     int type = _src.type(), cn = CV_MAT_CN(type), depth = CV_MAT_DEPTH(type),
1020             rowsPerWI = ocl::Device::getDefault().isIntel() ? 4 : 1;
1021     bool isolated = (borderType & BORDER_ISOLATED) != 0;
1022     borderType &= ~cv::BORDER_ISOLATED;
1023
1024     if ( !(borderType == BORDER_CONSTANT || borderType == BORDER_REPLICATE || borderType == BORDER_REFLECT ||
1025            borderType == BORDER_WRAP || borderType == BORDER_REFLECT_101) ||
1026          cn > 4)
1027         return false;
1028
1029     const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", "BORDER_WRAP", "BORDER_REFLECT_101" };
1030     int scalarcn = cn == 3 ? 4 : cn;
1031     int sctype = CV_MAKETYPE(depth, scalarcn);
1032     String buildOptions = format("-D T=%s -D %s -D T1=%s -D cn=%d -D ST=%s -D rowsPerWI=%d",
1033                                  ocl::memopTypeToStr(type), borderMap[borderType],
1034                                  ocl::memopTypeToStr(depth), cn,
1035                                  ocl::memopTypeToStr(sctype), rowsPerWI);
1036
1037     ocl::Kernel k("copyMakeBorder", ocl::core::copymakeborder_oclsrc, buildOptions);
1038     if (k.empty())
1039         return false;
1040
1041     UMat src = _src.getUMat();
1042     if( src.isSubmatrix() && !isolated )
1043     {
1044         Size wholeSize;
1045         Point ofs;
1046         src.locateROI(wholeSize, ofs);
1047         int dtop = std::min(ofs.y, top);
1048         int dbottom = std::min(wholeSize.height - src.rows - ofs.y, bottom);
1049         int dleft = std::min(ofs.x, left);
1050         int dright = std::min(wholeSize.width - src.cols - ofs.x, right);
1051         src.adjustROI(dtop, dbottom, dleft, dright);
1052         top -= dtop;
1053         left -= dleft;
1054         bottom -= dbottom;
1055         right -= dright;
1056     }
1057
1058     _dst.create(src.rows + top + bottom, src.cols + left + right, type);
1059     UMat dst = _dst.getUMat();
1060
1061     if (top == 0 && left == 0 && bottom == 0 && right == 0)
1062     {
1063         if(src.u != dst.u || src.step != dst.step)
1064             src.copyTo(dst);
1065         return true;
1066     }
1067
1068     k.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::WriteOnly(dst),
1069            top, left, ocl::KernelArg::Constant(Mat(1, 1, sctype, value)));
1070
1071     size_t globalsize[2] = { dst.cols, (dst.rows + rowsPerWI - 1) / rowsPerWI };
1072     return k.run(2, globalsize, NULL, false);
1073 }
1074
1075 }
1076
1077 #endif
1078
1079 void cv::copyMakeBorder( InputArray _src, OutputArray _dst, int top, int bottom,
1080                          int left, int right, int borderType, const Scalar& value )
1081 {
1082     CV_Assert( top >= 0 && bottom >= 0 && left >= 0 && right >= 0 );
1083
1084     CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2,
1085                ocl_copyMakeBorder(_src, _dst, top, bottom, left, right, borderType, value))
1086
1087     Mat src = _src.getMat();
1088     int type = src.type();
1089
1090     if( src.isSubmatrix() && (borderType & BORDER_ISOLATED) == 0 )
1091     {
1092         Size wholeSize;
1093         Point ofs;
1094         src.locateROI(wholeSize, ofs);
1095         int dtop = std::min(ofs.y, top);
1096         int dbottom = std::min(wholeSize.height - src.rows - ofs.y, bottom);
1097         int dleft = std::min(ofs.x, left);
1098         int dright = std::min(wholeSize.width - src.cols - ofs.x, right);
1099         src.adjustROI(dtop, dbottom, dleft, dright);
1100         top -= dtop;
1101         left -= dleft;
1102         bottom -= dbottom;
1103         right -= dright;
1104     }
1105
1106     _dst.create( src.rows + top + bottom, src.cols + left + right, type );
1107     Mat dst = _dst.getMat();
1108
1109     if(top == 0 && left == 0 && bottom == 0 && right == 0)
1110     {
1111         if(src.data != dst.data || src.step != dst.step)
1112             src.copyTo(dst);
1113         return;
1114     }
1115
1116     borderType &= ~BORDER_ISOLATED;
1117
1118 #if defined HAVE_IPP && 0
1119     typedef IppStatus (CV_STDCALL * ippiCopyMakeBorder)(const void * pSrc, int srcStep, IppiSize srcRoiSize, void * pDst,
1120                                                         int dstStep, IppiSize dstRoiSize, int topBorderHeight, int leftBorderWidth);
1121     typedef IppStatus (CV_STDCALL * ippiCopyMakeBorderI)(const void * pSrc, int srcDstStep, IppiSize srcRoiSize, IppiSize dstRoiSize,
1122                                                          int topBorderHeight, int leftborderwidth);
1123     typedef IppStatus (CV_STDCALL * ippiCopyConstBorder)(const void * pSrc, int srcStep, IppiSize srcRoiSize, void * pDst, int dstStep,
1124                                                          IppiSize dstRoiSize, int topBorderHeight, int leftBorderWidth, void * value);
1125
1126     IppiSize srcRoiSize = { src.cols, src.rows }, dstRoiSize = { dst.cols, dst.rows };
1127     ippiCopyMakeBorder ippFunc = 0;
1128     ippiCopyMakeBorderI ippFuncI = 0;
1129     ippiCopyConstBorder ippFuncConst = 0;
1130     bool inplace = dst.datastart == src.datastart;
1131
1132     if (borderType == BORDER_CONSTANT)
1133     {
1134          ippFuncConst =
1135 //             type == CV_8UC1 ? (ippiCopyConstBorder)ippiCopyConstBorder_8u_C1R : bug in IPP 8.1
1136              type == CV_16UC1 ? (ippiCopyConstBorder)ippiCopyConstBorder_16u_C1R :
1137 //             type == CV_16SC1 ? (ippiCopyConstBorder)ippiCopyConstBorder_16s_C1R : bug in IPP 8.1
1138 //             type == CV_32SC1 ? (ippiCopyConstBorder)ippiCopyConstBorder_32s_C1R : bug in IPP 8.1
1139 //             type == CV_32FC1 ? (ippiCopyConstBorder)ippiCopyConstBorder_32f_C1R : bug in IPP 8.1
1140              type == CV_8UC3 ? (ippiCopyConstBorder)ippiCopyConstBorder_8u_C3R :
1141              type == CV_16UC3 ? (ippiCopyConstBorder)ippiCopyConstBorder_16u_C3R :
1142              type == CV_16SC3 ? (ippiCopyConstBorder)ippiCopyConstBorder_16s_C3R :
1143              type == CV_32SC3 ? (ippiCopyConstBorder)ippiCopyConstBorder_32s_C3R :
1144              type == CV_32FC3 ? (ippiCopyConstBorder)ippiCopyConstBorder_32f_C3R :
1145              type == CV_8UC4 ? (ippiCopyConstBorder)ippiCopyConstBorder_8u_C4R :
1146              type == CV_16UC4 ? (ippiCopyConstBorder)ippiCopyConstBorder_16u_C4R :
1147              type == CV_16SC4 ? (ippiCopyConstBorder)ippiCopyConstBorder_16s_C4R :
1148              type == CV_32SC4 ? (ippiCopyConstBorder)ippiCopyConstBorder_32s_C4R :
1149              type == CV_32FC4 ? (ippiCopyConstBorder)ippiCopyConstBorder_32f_C4R : 0;
1150     }
1151     else if (borderType == BORDER_WRAP)
1152     {
1153         if (inplace)
1154         {
1155             CV_SUPPRESS_DEPRECATED_START
1156             ippFuncI =
1157                 type == CV_32SC1 ? (ippiCopyMakeBorderI)ippiCopyWrapBorder_32s_C1IR :
1158                 type == CV_32FC1 ? (ippiCopyMakeBorderI)ippiCopyWrapBorder_32s_C1IR : 0;
1159             CV_SUPPRESS_DEPRECATED_END
1160         }
1161         else
1162         {
1163             ippFunc =
1164                 type == CV_32SC1 ? (ippiCopyMakeBorder)ippiCopyWrapBorder_32s_C1R :
1165                 type == CV_32FC1 ? (ippiCopyMakeBorder)ippiCopyWrapBorder_32s_C1R : 0;
1166         }
1167     }
1168     else if (borderType == BORDER_REPLICATE)
1169     {
1170         if (inplace)
1171         {
1172             CV_SUPPRESS_DEPRECATED_START
1173             ippFuncI =
1174                 type == CV_8UC1 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_8u_C1IR :
1175                 type == CV_16UC1 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_16u_C1IR :
1176                 type == CV_16SC1 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_16s_C1IR :
1177                 type == CV_32SC1 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_32s_C1IR :
1178                 type == CV_32FC1 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_32f_C1IR :
1179                 type == CV_8UC3 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_8u_C3IR :
1180                 type == CV_16UC3 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_16u_C3IR :
1181                 type == CV_16SC3 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_16s_C3IR :
1182                 type == CV_32SC3 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_32s_C3IR :
1183                 type == CV_32FC3 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_32f_C3IR :
1184                 type == CV_8UC4 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_8u_C4IR :
1185                 type == CV_16UC4 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_16u_C4IR :
1186                 type == CV_16SC4 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_16s_C4IR :
1187                 type == CV_32SC4 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_32s_C4IR :
1188                 type == CV_32FC4 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_32f_C4IR : 0;
1189             CV_SUPPRESS_DEPRECATED_END
1190         }
1191         else
1192         {
1193              ippFunc =
1194                  type == CV_8UC1 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_8u_C1R :
1195                  type == CV_16UC1 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_16u_C1R :
1196                  type == CV_16SC1 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_16s_C1R :
1197                  type == CV_32SC1 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_32s_C1R :
1198                  type == CV_32FC1 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_32f_C1R :
1199                  type == CV_8UC3 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_8u_C3R :
1200                  type == CV_16UC3 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_16u_C3R :
1201                  type == CV_16SC3 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_16s_C3R :
1202                  type == CV_32SC3 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_32s_C3R :
1203                  type == CV_32FC3 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_32f_C3R :
1204                  type == CV_8UC4 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_8u_C4R :
1205                  type == CV_16UC4 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_16u_C4R :
1206                  type == CV_16SC4 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_16s_C4R :
1207                  type == CV_32SC4 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_32s_C4R :
1208                  type == CV_32FC4 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_32f_C4R : 0;
1209         }
1210     }
1211
1212     if (ippFunc || ippFuncI || ippFuncConst)
1213     {
1214         uchar scbuf[32];
1215         scalarToRawData(value, scbuf, type);
1216
1217         if ( (ippFunc && ippFunc(src.data, (int)src.step, srcRoiSize, dst.data, (int)dst.step, dstRoiSize, top, left) >= 0) ||
1218              (ippFuncI && ippFuncI(src.data, (int)src.step, srcRoiSize, dstRoiSize, top, left) >= 0) ||
1219              (ippFuncConst && ippFuncConst(src.data, (int)src.step, srcRoiSize, dst.data, (int)dst.step,
1220                                            dstRoiSize, top, left, scbuf) >= 0))
1221             return;
1222
1223         setIppErrorStatus();
1224     }
1225 #endif
1226
1227     if( borderType != BORDER_CONSTANT )
1228         copyMakeBorder_8u( src.ptr(), src.step, src.size(),
1229                            dst.ptr(), dst.step, dst.size(),
1230                            top, left, (int)src.elemSize(), borderType );
1231     else
1232     {
1233         int cn = src.channels(), cn1 = cn;
1234         AutoBuffer<double> buf(cn);
1235         if( cn > 4 )
1236         {
1237             CV_Assert( value[0] == value[1] && value[0] == value[2] && value[0] == value[3] );
1238             cn1 = 1;
1239         }
1240         scalarToRawData(value, buf, CV_MAKETYPE(src.depth(), cn1), cn);
1241         copyMakeConstBorder_8u( src.ptr(), src.step, src.size(),
1242                                 dst.ptr(), dst.step, dst.size(),
1243                                 top, left, (int)src.elemSize(), (uchar*)(double*)buf );
1244     }
1245 }
1246
1247 /* dst = src */
1248 CV_IMPL void
1249 cvCopy( const void* srcarr, void* dstarr, const void* maskarr )
1250 {
1251     if( CV_IS_SPARSE_MAT(srcarr) && CV_IS_SPARSE_MAT(dstarr))
1252     {
1253         CV_Assert( maskarr == 0 );
1254         CvSparseMat* src1 = (CvSparseMat*)srcarr;
1255         CvSparseMat* dst1 = (CvSparseMat*)dstarr;
1256         CvSparseMatIterator iterator;
1257         CvSparseNode* node;
1258
1259         dst1->dims = src1->dims;
1260         memcpy( dst1->size, src1->size, src1->dims*sizeof(src1->size[0]));
1261         dst1->valoffset = src1->valoffset;
1262         dst1->idxoffset = src1->idxoffset;
1263         cvClearSet( dst1->heap );
1264
1265         if( src1->heap->active_count >= dst1->hashsize*CV_SPARSE_HASH_RATIO )
1266         {
1267             cvFree( &dst1->hashtable );
1268             dst1->hashsize = src1->hashsize;
1269             dst1->hashtable =
1270                 (void**)cvAlloc( dst1->hashsize*sizeof(dst1->hashtable[0]));
1271         }
1272
1273         memset( dst1->hashtable, 0, dst1->hashsize*sizeof(dst1->hashtable[0]));
1274
1275         for( node = cvInitSparseMatIterator( src1, &iterator );
1276              node != 0; node = cvGetNextSparseNode( &iterator ))
1277         {
1278             CvSparseNode* node_copy = (CvSparseNode*)cvSetNew( dst1->heap );
1279             int tabidx = node->hashval & (dst1->hashsize - 1);
1280             memcpy( node_copy, node, dst1->heap->elem_size );
1281             node_copy->next = (CvSparseNode*)dst1->hashtable[tabidx];
1282             dst1->hashtable[tabidx] = node_copy;
1283         }
1284         return;
1285     }
1286     cv::Mat src = cv::cvarrToMat(srcarr, false, true, 1), dst = cv::cvarrToMat(dstarr, false, true, 1);
1287     CV_Assert( src.depth() == dst.depth() && src.size == dst.size );
1288
1289     int coi1 = 0, coi2 = 0;
1290     if( CV_IS_IMAGE(srcarr) )
1291         coi1 = cvGetImageCOI((const IplImage*)srcarr);
1292     if( CV_IS_IMAGE(dstarr) )
1293         coi2 = cvGetImageCOI((const IplImage*)dstarr);
1294
1295     if( coi1 || coi2 )
1296     {
1297         CV_Assert( (coi1 != 0 || src.channels() == 1) &&
1298             (coi2 != 0 || dst.channels() == 1) );
1299
1300         int pair[] = { std::max(coi1-1, 0), std::max(coi2-1, 0) };
1301         cv::mixChannels( &src, 1, &dst, 1, pair, 1 );
1302         return;
1303     }
1304     else
1305         CV_Assert( src.channels() == dst.channels() );
1306
1307     if( !maskarr )
1308         src.copyTo(dst);
1309     else
1310         src.copyTo(dst, cv::cvarrToMat(maskarr));
1311 }
1312
1313 CV_IMPL void
1314 cvSet( void* arr, CvScalar value, const void* maskarr )
1315 {
1316     cv::Mat m = cv::cvarrToMat(arr);
1317     if( !maskarr )
1318         m = value;
1319     else
1320         m.setTo(cv::Scalar(value), cv::cvarrToMat(maskarr));
1321 }
1322
1323 CV_IMPL void
1324 cvSetZero( CvArr* arr )
1325 {
1326     if( CV_IS_SPARSE_MAT(arr) )
1327     {
1328         CvSparseMat* mat1 = (CvSparseMat*)arr;
1329         cvClearSet( mat1->heap );
1330         if( mat1->hashtable )
1331             memset( mat1->hashtable, 0, mat1->hashsize*sizeof(mat1->hashtable[0]));
1332         return;
1333     }
1334     cv::Mat m = cv::cvarrToMat(arr);
1335     m = cv::Scalar(0);
1336 }
1337
1338 CV_IMPL void
1339 cvFlip( const CvArr* srcarr, CvArr* dstarr, int flip_mode )
1340 {
1341     cv::Mat src = cv::cvarrToMat(srcarr);
1342     cv::Mat dst;
1343
1344     if (!dstarr)
1345       dst = src;
1346     else
1347       dst = cv::cvarrToMat(dstarr);
1348
1349     CV_Assert( src.type() == dst.type() && src.size() == dst.size() );
1350     cv::flip( src, dst, flip_mode );
1351 }
1352
1353 CV_IMPL void
1354 cvRepeat( const CvArr* srcarr, CvArr* dstarr )
1355 {
1356     cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
1357     CV_Assert( src.type() == dst.type() &&
1358         dst.rows % src.rows == 0 && dst.cols % src.cols == 0 );
1359     cv::repeat(src, dst.rows/src.rows, dst.cols/src.cols, dst);
1360 }
1361
1362 /* End of file. */