1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
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.
10 // For Open Source Computer Vision Library
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.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
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.
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.
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.
42 /* ////////////////////////////////////////////////////////////////////
44 // Mat basic operations: Copy, Set
48 #include "precomp.hpp"
49 #include "opencl_kernels.hpp"
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)
57 for( ; size.height--; mask += mstep, _src += sstep, _dst += dstep )
59 const T* src = (const T*)_src;
62 #if CV_ENABLE_UNROLLED
63 for( ; x <= size.width - 4; x += 4 )
75 for( ; x < size.width; x++ )
82 copyMask_<uchar>(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size)
84 #if defined HAVE_IPP && !defined HAVE_IPP_ICV_ONLY
85 if (ippiCopy_8u_C1MR(_src, (int)sstep, _dst, (int)dstep, ippiSize(size), mask, (int)mstep) >= 0)
89 for( ; size.height--; mask += mstep, _src += sstep, _dst += dstep )
91 const uchar* src = (const uchar*)_src;
92 uchar* dst = (uchar*)_dst;
97 __m128i zero = _mm_setzero_si128 ();
99 for( ; x <= size.width - 16; x += 16 )
101 const __m128i rSrc = _mm_lddqu_si128((const __m128i*)(src+x));
102 __m128i _mask = _mm_lddqu_si128((const __m128i*)(mask+x));
103 __m128i rDst = _mm_lddqu_si128((__m128i*)(dst+x));
104 __m128i _negMask = _mm_cmpeq_epi8(_mask, zero);
105 rDst = _mm_blendv_epi8(rSrc, rDst, _negMask);
106 _mm_storeu_si128((__m128i*)(dst + x), rDst);
110 for( ; x < size.width; x++ )
117 copyMask_<ushort>(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size)
119 #if defined HAVE_IPP && !defined HAVE_IPP_ICV_ONLY
120 if (ippiCopy_16u_C1MR((const Ipp16u *)_src, (int)sstep, (Ipp16u *)_dst, (int)dstep, ippiSize(size), mask, (int)mstep) >= 0)
124 for( ; size.height--; mask += mstep, _src += sstep, _dst += dstep )
126 const ushort* src = (const ushort*)_src;
127 ushort* dst = (ushort*)_dst;
132 __m128i zero = _mm_setzero_si128 ();
133 for( ; x <= size.width - 8; x += 8 )
135 const __m128i rSrc =_mm_lddqu_si128((const __m128i*)(src+x));
136 __m128i _mask = _mm_loadl_epi64((const __m128i*)(mask+x));
137 _mask = _mm_unpacklo_epi8(_mask, _mask);
138 __m128i rDst = _mm_lddqu_si128((const __m128i*)(dst+x));
139 __m128i _negMask = _mm_cmpeq_epi8(_mask, zero);
140 rDst = _mm_blendv_epi8(rSrc, rDst, _negMask);
141 _mm_storeu_si128((__m128i*)(dst + x), rDst);
145 for( ; x < size.width; x++ )
152 copyMaskGeneric(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size, void* _esz)
154 size_t k, esz = *(size_t*)_esz;
155 for( ; size.height--; mask += mstep, _src += sstep, _dst += dstep )
157 const uchar* src = _src;
160 for( ; x < size.width; x++, src += esz, dst += esz )
164 for( k = 0; k < esz; k++ )
171 #define DEF_COPY_MASK(suffix, type) \
172 static void copyMask##suffix(const uchar* src, size_t sstep, const uchar* mask, size_t mstep, \
173 uchar* dst, size_t dstep, Size size, void*) \
175 copyMask_<type>(src, sstep, mask, mstep, dst, dstep, size); \
178 #if defined HAVE_IPP && !defined HAVE_IPP_ICV_ONLY
179 #define DEF_COPY_MASK_F(suffix, type, ippfavor, ipptype) \
180 static void copyMask##suffix(const uchar* src, size_t sstep, const uchar* mask, size_t mstep, \
181 uchar* dst, size_t dstep, Size size, void*) \
183 if (ippiCopy_##ippfavor((const ipptype *)src, (int)sstep, (ipptype *)dst, (int)dstep, ippiSize(size), (const Ipp8u *)mask, (int)mstep) >= 0) \
185 copyMask_<type>(src, sstep, mask, mstep, dst, dstep, size); \
188 #define DEF_COPY_MASK_F(suffix, type, ippfavor, ipptype) \
189 static void copyMask##suffix(const uchar* src, size_t sstep, const uchar* mask, size_t mstep, \
190 uchar* dst, size_t dstep, Size size, void*) \
192 copyMask_<type>(src, sstep, mask, mstep, dst, dstep, size); \
197 DEF_COPY_MASK(8u, uchar)
198 DEF_COPY_MASK(16u, ushort)
199 DEF_COPY_MASK_F(8uC3, Vec3b, 8u_C3MR, Ipp8u)
200 DEF_COPY_MASK_F(32s, int, 32s_C1MR, Ipp32s)
201 DEF_COPY_MASK_F(16uC3, Vec3s, 16u_C3MR, Ipp16u)
202 DEF_COPY_MASK(32sC2, Vec2i)
203 DEF_COPY_MASK_F(32sC3, Vec3i, 32s_C3MR, Ipp32s)
204 DEF_COPY_MASK_F(32sC4, Vec4i, 32s_C4MR, Ipp32s)
205 DEF_COPY_MASK(32sC6, Vec6i)
206 DEF_COPY_MASK(32sC8, Vec8i)
208 BinaryFunc copyMaskTab[] =
229 BinaryFunc getCopyMaskFunc(size_t esz)
231 return esz <= 32 && copyMaskTab[esz] ? copyMaskTab[esz] : copyMaskGeneric;
235 void Mat::copyTo( OutputArray _dst ) const
237 int dtype = _dst.type();
238 if( _dst.fixedType() && dtype != type() )
240 CV_Assert( channels() == CV_MAT_CN(dtype) );
241 convertTo( _dst, dtype );
253 _dst.create( dims, size.p, type() );
254 UMat dst = _dst.getUMat();
256 size_t i, sz[CV_MAX_DIM], dstofs[CV_MAX_DIM], esz = elemSize();
257 for( i = 0; i < (size_t)dims; i++ )
260 dst.ndoffset(dstofs);
261 dstofs[dims-1] *= esz;
262 dst.u->currAllocator->upload(dst.u, data, dims, sz, dstofs, dst.step.p, step.p);
268 _dst.create( rows, cols, type() );
269 Mat dst = _dst.getMat();
270 if( data == dst.data )
273 if( rows > 0 && cols > 0 )
275 const uchar* sptr = data;
276 uchar* dptr = dst.data;
278 Size sz = getContinuousSize(*this, dst);
279 size_t len = sz.width*elemSize();
281 #if defined HAVE_IPP && !defined HAVE_IPP_ICV_ONLY
282 if (ippiCopy_8u_C1R(sptr, (int)step, dptr, (int)dst.step, ippiSize((int)len, sz.height)) >= 0)
286 for( ; sz.height--; sptr += step, dptr += dst.step )
287 memcpy( dptr, sptr, len );
292 _dst.create( dims, size, type() );
293 Mat dst = _dst.getMat();
294 if( data == dst.data )
299 const Mat* arrays[] = { this, &dst };
301 NAryMatIterator it(arrays, ptrs, 2);
302 size_t sz = it.size*elemSize();
304 for( size_t i = 0; i < it.nplanes; i++, ++it )
305 memcpy(ptrs[1], ptrs[0], sz);
309 void Mat::copyTo( OutputArray _dst, InputArray _mask ) const
311 Mat mask = _mask.getMat();
318 int cn = channels(), mcn = mask.channels();
319 CV_Assert( mask.depth() == CV_8U && (mcn == 1 || mcn == cn) );
320 bool colorMask = mcn > 1;
322 size_t esz = colorMask ? elemSize1() : elemSize();
323 BinaryFunc copymask = getCopyMaskFunc(esz);
325 uchar* data0 = _dst.getMat().data;
326 _dst.create( dims, size, type() );
327 Mat dst = _dst.getMat();
329 if( dst.data != data0 ) // do not leave dst uninitialized
334 CV_Assert( size() == mask.size() );
335 Size sz = getContinuousSize(*this, dst, mask, mcn);
336 copymask(data, step, mask.data, mask.step, dst.data, dst.step, sz, &esz);
340 const Mat* arrays[] = { this, &dst, &mask, 0 };
342 NAryMatIterator it(arrays, ptrs);
343 Size sz((int)(it.size*mcn), 1);
345 for( size_t i = 0; i < it.nplanes; i++, ++it )
346 copymask(ptrs[0], 0, ptrs[2], 0, ptrs[1], 0, sz, &esz);
349 Mat& Mat::operator = (const Scalar& s)
351 const Mat* arrays[] = { this };
353 NAryMatIterator it(arrays, &dptr, 1);
354 size_t elsize = it.size*elemSize();
355 const int64* is = (const int64*)&s.val[0];
357 if( is[0] == 0 && is[1] == 0 && is[2] == 0 && is[3] == 0 )
359 #if defined HAVE_IPP && !defined HAVE_IPP_ICV_ONLY
360 if (dims <= 2 || isContinuous())
362 IppiSize roisize = { cols, rows };
365 roisize.width = (int)total();
368 if (ippsZero_8u(data, roisize.width * elemSize()) >= 0)
371 roisize.width *= elemSize();
373 if (ippiSet_8u_C1R(0, data, (int)step, roisize) >= 0)
378 for( size_t i = 0; i < it.nplanes; i++, ++it )
379 memset( dptr, 0, elsize );
386 scalarToRawData(s, scalar, type(), 12);
387 size_t blockSize = 12*elemSize1();
389 for( size_t j = 0; j < elsize; j += blockSize )
391 size_t sz = MIN(blockSize, elsize - j);
392 memcpy( dptr + j, scalar, sz );
396 for( size_t i = 1; i < it.nplanes; i++ )
399 memcpy( dptr, data, elsize );
406 Mat& Mat::setTo(InputArray _value, InputArray _mask)
411 Mat value = _value.getMat(), mask = _mask.getMat();
413 CV_Assert( checkScalar(value, type(), _value.kind(), _InputArray::MAT ));
414 CV_Assert( mask.empty() || (mask.type() == CV_8U && size == mask.size) );
416 #if defined HAVE_IPP && !defined HAVE_IPP_ICV_ONLY
417 if (!mask.empty() && (dims <= 2 || (isContinuous() && mask.isContinuous())))
420 convertAndUnrollScalar( value, type(), buf, 1 );
422 int cn = channels(), depth0 = depth();
423 IppStatus status = (IppStatus)-1;
424 IppiSize roisize = { cols, rows };
425 int mstep = (int)mask.step, dstep = (int)step;
427 if (isContinuous() && mask.isContinuous())
429 roisize.width = (int)total();
436 status = ippiSet_8u_C1MR(*(Ipp8u *)buf, (Ipp8u *)data, dstep, roisize, mask.data, mstep);
437 else if (depth0 == CV_16U)
438 status = ippiSet_16u_C1MR(*(Ipp16u *)buf, (Ipp16u *)data, dstep, roisize, mask.data, mstep);
439 else if (depth0 == CV_16S)
440 status = ippiSet_16s_C1MR(*(Ipp16s *)buf, (Ipp16s *)data, dstep, roisize, mask.data, mstep);
441 else if (depth0 == CV_32S)
442 status = ippiSet_32s_C1MR(*(Ipp32s *)buf, (Ipp32s *)data, dstep, roisize, mask.data, mstep);
443 else if (depth0 == CV_32F)
444 status = ippiSet_32f_C1MR(*(Ipp32f *)buf, (Ipp32f *)data, dstep, roisize, mask.data, mstep);
446 else if (cn == 3 || cn == 3)
448 #define IPP_SET(ippfavor, ippcn) \
451 typedef Ipp##ippfavor ipptype; \
452 ipptype ippvalue[4] = { ((ipptype *)buf)[0], ((ipptype *)buf)[1], ((ipptype *)buf)[2], ((ipptype *)buf)[4] }; \
453 status = ippiSet_##ippfavor##_C##ippcn##MR(ippvalue, (ipptype *)data, dstep, roisize, mask.data, mstep); \
456 #define IPP_SET_CN(ippcn) \
461 if (depth0 == CV_8U) \
462 IPP_SET(8u, ippcn); \
463 else if (depth0 == CV_16U) \
464 IPP_SET(16u, ippcn); \
465 else if (depth0 == CV_16S) \
466 IPP_SET(16s, ippcn); \
467 else if (depth0 == CV_32S) \
468 IPP_SET(32s, ippcn); \
469 else if (depth0 == CV_32F) \
470 IPP_SET(32f, ippcn); \
486 size_t esz = elemSize();
487 BinaryFunc copymask = getCopyMaskFunc(esz);
489 const Mat* arrays[] = { this, !mask.empty() ? &mask : 0, 0 };
490 uchar* ptrs[2]={0,0};
491 NAryMatIterator it(arrays, ptrs);
492 int totalsz = (int)it.size, blockSize0 = std::min(totalsz, (int)((BLOCK_SIZE + esz-1)/esz));
493 AutoBuffer<uchar> _scbuf(blockSize0*esz + 32);
494 uchar* scbuf = alignPtr((uchar*)_scbuf, (int)sizeof(double));
495 convertAndUnrollScalar( value, type(), scbuf, blockSize0 );
497 for( size_t i = 0; i < it.nplanes; i++, ++it )
499 for( int j = 0; j < totalsz; j += blockSize0 )
501 Size sz(std::min(blockSize0, totalsz - j), 1);
502 size_t blockSize = sz.width*esz;
505 copymask(scbuf, 0, ptrs[1], 0, ptrs[0], 0, sz, &esz);
509 memcpy(ptrs[0], scbuf, blockSize);
510 ptrs[0] += blockSize;
518 flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, size_t esz )
520 int i, j, limit = (int)(((size.width + 1)/2)*esz);
521 AutoBuffer<int> _tab(size.width*esz);
524 for( i = 0; i < size.width; i++ )
525 for( size_t k = 0; k < esz; k++ )
526 tab[i*esz + k] = (int)((size.width - i - 1)*esz + k);
528 for( ; size.height--; src += sstep, dst += dstep )
530 for( i = 0; i < limit; i++ )
533 uchar t0 = src[i], t1 = src[j];
534 dst[i] = t1; dst[j] = t0;
540 flipVert( const uchar* src0, size_t sstep, uchar* dst0, size_t dstep, Size size, size_t esz )
542 const uchar* src1 = src0 + (size.height - 1)*sstep;
543 uchar* dst1 = dst0 + (size.height - 1)*dstep;
544 size.width *= (int)esz;
546 for( int y = 0; y < (size.height + 1)/2; y++, src0 += sstep, src1 -= sstep,
547 dst0 += dstep, dst1 -= dstep )
550 if( ((size_t)src0|(size_t)dst0|(size_t)src1|(size_t)dst1) % sizeof(int) == 0 )
552 for( ; i <= size.width - 16; i += 16 )
554 int t0 = ((int*)(src0 + i))[0];
555 int t1 = ((int*)(src1 + i))[0];
557 ((int*)(dst0 + i))[0] = t1;
558 ((int*)(dst1 + i))[0] = t0;
560 t0 = ((int*)(src0 + i))[1];
561 t1 = ((int*)(src1 + i))[1];
563 ((int*)(dst0 + i))[1] = t1;
564 ((int*)(dst1 + i))[1] = t0;
566 t0 = ((int*)(src0 + i))[2];
567 t1 = ((int*)(src1 + i))[2];
569 ((int*)(dst0 + i))[2] = t1;
570 ((int*)(dst1 + i))[2] = t0;
572 t0 = ((int*)(src0 + i))[3];
573 t1 = ((int*)(src1 + i))[3];
575 ((int*)(dst0 + i))[3] = t1;
576 ((int*)(dst1 + i))[3] = t0;
579 for( ; i <= size.width - 4; i += 4 )
581 int t0 = ((int*)(src0 + i))[0];
582 int t1 = ((int*)(src1 + i))[0];
584 ((int*)(dst0 + i))[0] = t1;
585 ((int*)(dst1 + i))[0] = t0;
589 for( ; i < size.width; i++ )
602 enum { FLIP_COLS = 1 << 0, FLIP_ROWS = 1 << 1, FLIP_BOTH = FLIP_ROWS | FLIP_COLS };
604 static bool ocl_flip(InputArray _src, OutputArray _dst, int flipCode )
606 CV_Assert(flipCode >= - 1 && flipCode <= 1);
607 int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type), flipType;
612 const char * kernelName;
614 kernelName = "arithm_flip_rows", flipType = FLIP_ROWS;
615 else if (flipCode > 0)
616 kernelName = "arithm_flip_cols", flipType = FLIP_COLS;
618 kernelName = "arithm_flip_rows_cols", flipType = FLIP_BOTH;
620 ocl::Kernel k(kernelName, ocl::core::flip_oclsrc,
621 format( "-D T=%s -D T1=%s -D cn=%d", ocl::memopTypeToStr(type),
622 ocl::memopTypeToStr(depth), cn));
626 Size size = _src.size();
627 _dst.create(size, type);
628 UMat src = _src.getUMat(), dst = _dst.getUMat();
630 int cols = size.width, rows = size.height;
631 cols = flipType == FLIP_COLS ? (cols + 1) >> 1 : cols;
632 rows = flipType & FLIP_ROWS ? (rows + 1) >> 1 : rows;
634 k.args(ocl::KernelArg::ReadOnlyNoSize(src),
635 ocl::KernelArg::WriteOnly(dst), rows, cols);
637 size_t maxWorkGroupSize = ocl::Device::getDefault().maxWorkGroupSize();
638 CV_Assert(maxWorkGroupSize % 4 == 0);
639 size_t globalsize[2] = { cols, rows }, localsize[2] = { maxWorkGroupSize / 4, 4 };
640 return k.run(2, globalsize, flipType == FLIP_COLS ? localsize : NULL, false);
645 void flip( InputArray _src, OutputArray _dst, int flip_mode )
647 CV_Assert( _src.dims() <= 2 );
648 Size size = _src.size();
654 if (size.height == 1)
658 if ((size.width == 1 && flip_mode > 0) ||
659 (size.height == 1 && flip_mode == 0) ||
660 (size.height == 1 && size.width == 1 && flip_mode < 0))
662 return _src.copyTo(_dst);
665 CV_OCL_RUN( _dst.isUMat(), ocl_flip(_src, _dst, flip_mode))
667 Mat src = _src.getMat();
668 int type = src.type();
669 _dst.create( size, type );
670 Mat dst = _dst.getMat();
671 size_t esz = CV_ELEM_SIZE(type);
673 #if defined HAVE_IPP && !defined HAVE_IPP_ICV_ONLY
674 typedef IppStatus (CV_STDCALL * ippiMirror)(const void * pSrc, int srcStep, void * pDst, int dstStep, IppiSize roiSize, IppiAxis flip);
675 typedef IppStatus (CV_STDCALL * ippiMirrorI)(const void * pSrcDst, int srcDstStep, IppiSize roiSize, IppiAxis flip);
676 ippiMirror ippFunc = 0;
677 ippiMirrorI ippFuncI = 0;
679 if (src.data == dst.data)
682 type == CV_8UC1 ? (ippiMirrorI)ippiMirror_8u_C1IR :
683 type == CV_8UC3 ? (ippiMirrorI)ippiMirror_8u_C3IR :
684 type == CV_8UC4 ? (ippiMirrorI)ippiMirror_8u_C4IR :
685 type == CV_16UC1 ? (ippiMirrorI)ippiMirror_16u_C1IR :
686 type == CV_16UC3 ? (ippiMirrorI)ippiMirror_16u_C3IR :
687 type == CV_16UC4 ? (ippiMirrorI)ippiMirror_16u_C4IR :
688 type == CV_16SC1 ? (ippiMirrorI)ippiMirror_16s_C1IR :
689 type == CV_16SC3 ? (ippiMirrorI)ippiMirror_16s_C3IR :
690 type == CV_16SC4 ? (ippiMirrorI)ippiMirror_16s_C4IR :
691 type == CV_32SC1 ? (ippiMirrorI)ippiMirror_32s_C1IR :
692 type == CV_32SC3 ? (ippiMirrorI)ippiMirror_32s_C3IR :
693 type == CV_32SC4 ? (ippiMirrorI)ippiMirror_32s_C4IR :
694 type == CV_32FC1 ? (ippiMirrorI)ippiMirror_32f_C1IR :
695 type == CV_32FC3 ? (ippiMirrorI)ippiMirror_32f_C3IR :
696 type == CV_32FC4 ? (ippiMirrorI)ippiMirror_32f_C4IR : 0;
701 type == CV_8UC1 ? (ippiMirror)ippiMirror_8u_C1R :
702 type == CV_8UC3 ? (ippiMirror)ippiMirror_8u_C3R :
703 type == CV_8UC4 ? (ippiMirror)ippiMirror_8u_C4R :
704 type == CV_16UC1 ? (ippiMirror)ippiMirror_16u_C1R :
705 type == CV_16UC3 ? (ippiMirror)ippiMirror_16u_C3R :
706 type == CV_16UC4 ? (ippiMirror)ippiMirror_16u_C4R :
707 type == CV_16SC1 ? (ippiMirror)ippiMirror_16s_C1R :
708 type == CV_16SC3 ? (ippiMirror)ippiMirror_16s_C3R :
709 type == CV_16SC4 ? (ippiMirror)ippiMirror_16s_C4R :
710 type == CV_32SC1 ? (ippiMirror)ippiMirror_32s_C1R :
711 type == CV_32SC3 ? (ippiMirror)ippiMirror_32s_C3R :
712 type == CV_32SC4 ? (ippiMirror)ippiMirror_32s_C4R :
713 type == CV_32FC1 ? (ippiMirror)ippiMirror_32f_C1R :
714 type == CV_32FC3 ? (ippiMirror)ippiMirror_32f_C3R :
715 type == CV_32FC4 ? (ippiMirror)ippiMirror_32f_C4R : 0;
717 IppiAxis axis = flip_mode == 0 ? ippAxsHorizontal :
718 flip_mode > 0 ? ippAxsVertical : ippAxsBoth;
719 IppiSize roisize = { dst.cols, dst.rows };
723 if (ippFunc(src.data, (int)src.step, dst.data, (int)dst.step, ippiSize(src.cols, src.rows), axis) >= 0)
727 else if (ippFuncI != 0)
729 if (ippFuncI(dst.data, (int)dst.step, roisize, axis) >= 0)
735 flipVert( src.data, src.step, dst.data, dst.step, src.size(), esz );
737 flipHoriz( src.data, src.step, dst.data, dst.step, src.size(), esz );
740 flipHoriz( dst.data, dst.step, dst.data, dst.step, dst.size(), esz );
745 static bool ocl_repeat(InputArray _src, int ny, int nx, OutputArray _dst)
747 UMat src = _src.getUMat(), dst = _dst.getUMat();
749 for (int y = 0; y < ny; ++y)
750 for (int x = 0; x < nx; ++x)
752 Rect roi(x * src.cols, y * src.rows, src.cols, src.rows);
761 void repeat(InputArray _src, int ny, int nx, OutputArray _dst)
763 CV_Assert( _src.dims() <= 2 );
764 CV_Assert( ny > 0 && nx > 0 );
766 Size ssize = _src.size();
767 _dst.create(ssize.height*ny, ssize.width*nx, _src.type());
769 CV_OCL_RUN(_dst.isUMat(),
770 ocl_repeat(_src, ny, nx, _dst))
772 Mat src = _src.getMat(), dst = _dst.getMat();
773 Size dsize = dst.size();
774 int esz = (int)src.elemSize();
776 ssize.width *= esz; dsize.width *= esz;
778 for( y = 0; y < ssize.height; y++ )
780 for( x = 0; x < dsize.width; x += ssize.width )
781 memcpy( dst.data + y*dst.step + x, src.data + y*src.step, ssize.width );
784 for( ; y < dsize.height; y++ )
785 memcpy( dst.data + y*dst.step, dst.data + (y - ssize.height)*dst.step, dsize.width );
788 Mat repeat(const Mat& src, int ny, int nx)
790 if( nx == 1 && ny == 1 )
793 repeat(src, ny, nx, dst);
802 Various border types, image boundaries are denoted with '|'
804 * BORDER_REPLICATE: aaaaaa|abcdefgh|hhhhhhh
805 * BORDER_REFLECT: fedcba|abcdefgh|hgfedcb
806 * BORDER_REFLECT_101: gfedcb|abcdefgh|gfedcba
807 * BORDER_WRAP: cdefgh|abcdefgh|abcdefg
808 * BORDER_CONSTANT: iiiiii|abcdefgh|iiiiiii with some specified 'i'
810 int cv::borderInterpolate( int p, int len, int borderType )
812 if( (unsigned)p < (unsigned)len )
814 else if( borderType == BORDER_REPLICATE )
815 p = p < 0 ? 0 : len - 1;
816 else if( borderType == BORDER_REFLECT || borderType == BORDER_REFLECT_101 )
818 int delta = borderType == BORDER_REFLECT_101;
826 p = len - 1 - (p - len) - delta;
828 while( (unsigned)p >= (unsigned)len );
830 else if( borderType == BORDER_WRAP )
834 p -= ((p-len+1)/len)*len;
838 else if( borderType == BORDER_CONSTANT )
841 CV_Error( CV_StsBadArg, "Unknown/unsupported border type" );
848 void copyMakeBorder_8u( const uchar* src, size_t srcstep, cv::Size srcroi,
849 uchar* dst, size_t dststep, cv::Size dstroi,
850 int top, int left, int cn, int borderType )
852 const int isz = (int)sizeof(int);
853 int i, j, k, elemSize = 1;
854 bool intMode = false;
856 if( (cn | srcstep | dststep | (size_t)src | (size_t)dst) % isz == 0 )
863 cv::AutoBuffer<int> _tab((dstroi.width - srcroi.width)*cn);
865 int right = dstroi.width - srcroi.width - left;
866 int bottom = dstroi.height - srcroi.height - top;
868 for( i = 0; i < left; i++ )
870 j = cv::borderInterpolate(i - left, srcroi.width, borderType)*cn;
871 for( k = 0; k < cn; k++ )
872 tab[i*cn + k] = j + k;
875 for( i = 0; i < right; i++ )
877 j = cv::borderInterpolate(srcroi.width + i, srcroi.width, borderType)*cn;
878 for( k = 0; k < cn; k++ )
879 tab[(i+left)*cn + k] = j + k;
887 uchar* dstInner = dst + dststep*top + left*elemSize;
889 for( i = 0; i < srcroi.height; i++, dstInner += dststep, src += srcstep )
891 if( dstInner != src )
892 memcpy(dstInner, src, srcroi.width*elemSize);
896 const int* isrc = (int*)src;
897 int* idstInner = (int*)dstInner;
898 for( j = 0; j < left; j++ )
899 idstInner[j - left] = isrc[tab[j]];
900 for( j = 0; j < right; j++ )
901 idstInner[j + srcroi.width] = isrc[tab[j + left]];
905 for( j = 0; j < left; j++ )
906 dstInner[j - left] = src[tab[j]];
907 for( j = 0; j < right; j++ )
908 dstInner[j + srcroi.width] = src[tab[j + left]];
912 dstroi.width *= elemSize;
915 for( i = 0; i < top; i++ )
917 j = cv::borderInterpolate(i - top, srcroi.height, borderType);
918 memcpy(dst + (i - top)*dststep, dst + j*dststep, dstroi.width);
921 for( i = 0; i < bottom; i++ )
923 j = cv::borderInterpolate(i + srcroi.height, srcroi.height, borderType);
924 memcpy(dst + (i + srcroi.height)*dststep, dst + j*dststep, dstroi.width);
929 void copyMakeConstBorder_8u( const uchar* src, size_t srcstep, cv::Size srcroi,
930 uchar* dst, size_t dststep, cv::Size dstroi,
931 int top, int left, int cn, const uchar* value )
934 cv::AutoBuffer<uchar> _constBuf(dstroi.width*cn);
935 uchar* constBuf = _constBuf;
936 int right = dstroi.width - srcroi.width - left;
937 int bottom = dstroi.height - srcroi.height - top;
939 for( i = 0; i < dstroi.width; i++ )
941 for( j = 0; j < cn; j++ )
942 constBuf[i*cn + j] = value[j];
950 uchar* dstInner = dst + dststep*top + left;
952 for( i = 0; i < srcroi.height; i++, dstInner += dststep, src += srcstep )
954 if( dstInner != src )
955 memcpy( dstInner, src, srcroi.width );
956 memcpy( dstInner - left, constBuf, left );
957 memcpy( dstInner + srcroi.width, constBuf, right );
962 for( i = 0; i < top; i++ )
963 memcpy(dst + (i - top)*dststep, constBuf, dstroi.width);
965 for( i = 0; i < bottom; i++ )
966 memcpy(dst + (i + srcroi.height)*dststep, constBuf, dstroi.width);
975 static bool ocl_copyMakeBorder( InputArray _src, OutputArray _dst, int top, int bottom,
976 int left, int right, int borderType, const Scalar& value )
978 int type = _src.type(), cn = CV_MAT_CN(type), depth = CV_MAT_DEPTH(type);
979 bool isolated = (borderType & BORDER_ISOLATED) != 0;
980 borderType &= ~cv::BORDER_ISOLATED;
982 if ( !(borderType == BORDER_CONSTANT || borderType == BORDER_REPLICATE || borderType == BORDER_REFLECT ||
983 borderType == BORDER_WRAP || borderType == BORDER_REFLECT_101) ||
987 const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", "BORDER_WRAP", "BORDER_REFLECT_101" };
988 int scalarcn = cn == 3 ? 4 : cn;
989 int sctype = CV_MAKETYPE(depth, scalarcn);
990 String buildOptions = format(
992 "-D T1=%s -D cn=%d -D ST=%s",
993 ocl::memopTypeToStr(type), borderMap[borderType],
994 ocl::memopTypeToStr(depth), cn, ocl::memopTypeToStr(sctype)
997 ocl::Kernel k("copyMakeBorder", ocl::core::copymakeborder_oclsrc, buildOptions);
1001 UMat src = _src.getUMat();
1002 if( src.isSubmatrix() && !isolated )
1006 src.locateROI(wholeSize, ofs);
1007 int dtop = std::min(ofs.y, top);
1008 int dbottom = std::min(wholeSize.height - src.rows - ofs.y, bottom);
1009 int dleft = std::min(ofs.x, left);
1010 int dright = std::min(wholeSize.width - src.cols - ofs.x, right);
1011 src.adjustROI(dtop, dbottom, dleft, dright);
1018 _dst.create(src.rows + top + bottom, src.cols + left + right, type);
1019 UMat dst = _dst.getUMat();
1021 if (top == 0 && left == 0 && bottom == 0 && right == 0)
1023 if(src.u != dst.u || src.step != dst.step)
1028 k.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::WriteOnly(dst),
1029 top, left, ocl::KernelArg::Constant(Mat(1, 1, sctype, value)));
1031 size_t globalsize[2] = { dst.cols, dst.rows };
1032 return k.run(2, globalsize, NULL, false);
1039 void cv::copyMakeBorder( InputArray _src, OutputArray _dst, int top, int bottom,
1040 int left, int right, int borderType, const Scalar& value )
1042 CV_Assert( top >= 0 && bottom >= 0 && left >= 0 && right >= 0 );
1044 CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2,
1045 ocl_copyMakeBorder(_src, _dst, top, bottom, left, right, borderType, value))
1047 Mat src = _src.getMat();
1049 if( src.isSubmatrix() && (borderType & BORDER_ISOLATED) == 0 )
1053 src.locateROI(wholeSize, ofs);
1054 int dtop = std::min(ofs.y, top);
1055 int dbottom = std::min(wholeSize.height - src.rows - ofs.y, bottom);
1056 int dleft = std::min(ofs.x, left);
1057 int dright = std::min(wholeSize.width - src.cols - ofs.x, right);
1058 src.adjustROI(dtop, dbottom, dleft, dright);
1065 _dst.create( src.rows + top + bottom, src.cols + left + right, src.type() );
1066 Mat dst = _dst.getMat();
1068 if(top == 0 && left == 0 && bottom == 0 && right == 0)
1070 if(src.data != dst.data || src.step != dst.step)
1075 borderType &= ~BORDER_ISOLATED;
1077 if( borderType != BORDER_CONSTANT )
1078 copyMakeBorder_8u( src.data, src.step, src.size(),
1079 dst.data, dst.step, dst.size(),
1080 top, left, (int)src.elemSize(), borderType );
1083 int cn = src.channels(), cn1 = cn;
1084 AutoBuffer<double> buf(cn);
1087 CV_Assert( value[0] == value[1] && value[0] == value[2] && value[0] == value[3] );
1090 scalarToRawData(value, buf, CV_MAKETYPE(src.depth(), cn1), cn);
1091 copyMakeConstBorder_8u( src.data, src.step, src.size(),
1092 dst.data, dst.step, dst.size(),
1093 top, left, (int)src.elemSize(), (uchar*)(double*)buf );
1099 cvCopy( const void* srcarr, void* dstarr, const void* maskarr )
1101 if( CV_IS_SPARSE_MAT(srcarr) && CV_IS_SPARSE_MAT(dstarr))
1103 CV_Assert( maskarr == 0 );
1104 CvSparseMat* src1 = (CvSparseMat*)srcarr;
1105 CvSparseMat* dst1 = (CvSparseMat*)dstarr;
1106 CvSparseMatIterator iterator;
1109 dst1->dims = src1->dims;
1110 memcpy( dst1->size, src1->size, src1->dims*sizeof(src1->size[0]));
1111 dst1->valoffset = src1->valoffset;
1112 dst1->idxoffset = src1->idxoffset;
1113 cvClearSet( dst1->heap );
1115 if( src1->heap->active_count >= dst1->hashsize*CV_SPARSE_HASH_RATIO )
1117 cvFree( &dst1->hashtable );
1118 dst1->hashsize = src1->hashsize;
1120 (void**)cvAlloc( dst1->hashsize*sizeof(dst1->hashtable[0]));
1123 memset( dst1->hashtable, 0, dst1->hashsize*sizeof(dst1->hashtable[0]));
1125 for( node = cvInitSparseMatIterator( src1, &iterator );
1126 node != 0; node = cvGetNextSparseNode( &iterator ))
1128 CvSparseNode* node_copy = (CvSparseNode*)cvSetNew( dst1->heap );
1129 int tabidx = node->hashval & (dst1->hashsize - 1);
1130 memcpy( node_copy, node, dst1->heap->elem_size );
1131 node_copy->next = (CvSparseNode*)dst1->hashtable[tabidx];
1132 dst1->hashtable[tabidx] = node_copy;
1136 cv::Mat src = cv::cvarrToMat(srcarr, false, true, 1), dst = cv::cvarrToMat(dstarr, false, true, 1);
1137 CV_Assert( src.depth() == dst.depth() && src.size == dst.size );
1139 int coi1 = 0, coi2 = 0;
1140 if( CV_IS_IMAGE(srcarr) )
1141 coi1 = cvGetImageCOI((const IplImage*)srcarr);
1142 if( CV_IS_IMAGE(dstarr) )
1143 coi2 = cvGetImageCOI((const IplImage*)dstarr);
1147 CV_Assert( (coi1 != 0 || src.channels() == 1) &&
1148 (coi2 != 0 || dst.channels() == 1) );
1150 int pair[] = { std::max(coi1-1, 0), std::max(coi2-1, 0) };
1151 cv::mixChannels( &src, 1, &dst, 1, pair, 1 );
1155 CV_Assert( src.channels() == dst.channels() );
1160 src.copyTo(dst, cv::cvarrToMat(maskarr));
1164 cvSet( void* arr, CvScalar value, const void* maskarr )
1166 cv::Mat m = cv::cvarrToMat(arr);
1170 m.setTo(cv::Scalar(value), cv::cvarrToMat(maskarr));
1174 cvSetZero( CvArr* arr )
1176 if( CV_IS_SPARSE_MAT(arr) )
1178 CvSparseMat* mat1 = (CvSparseMat*)arr;
1179 cvClearSet( mat1->heap );
1180 if( mat1->hashtable )
1181 memset( mat1->hashtable, 0, mat1->hashsize*sizeof(mat1->hashtable[0]));
1184 cv::Mat m = cv::cvarrToMat(arr);
1189 cvFlip( const CvArr* srcarr, CvArr* dstarr, int flip_mode )
1191 cv::Mat src = cv::cvarrToMat(srcarr);
1197 dst = cv::cvarrToMat(dstarr);
1199 CV_Assert( src.type() == dst.type() && src.size() == dst.size() );
1200 cv::flip( src, dst, flip_mode );
1204 cvRepeat( const CvArr* srcarr, CvArr* dstarr )
1206 cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
1207 CV_Assert( src.type() == dst.type() &&
1208 dst.rows % src.rows == 0 && dst.cols % src.cols == 0 );
1209 cv::repeat(src, dst.rows/src.rows, dst.cols/src.cols, dst);