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