Renesas GR-PEACH OpenCV Development / gr-peach-opencv-project-sd-card_update

Fork of gr-peach-opencv-project-sd-card by the do

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers copy.cpp Source File

copy.cpp

00001 /*M///////////////////////////////////////////////////////////////////////////////////////
00002 //
00003 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
00004 //
00005 //  By downloading, copying, installing or using the software you agree to this license.
00006 //  If you do not agree to this license, do not download, install,
00007 //  copy or use the software.
00008 //
00009 //                           License Agreement
00010 //                For Open Source Computer Vision Library
00011 //
00012 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
00013 // Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
00014 // Copyright (C) 2014, Itseez Inc., all rights reserved.
00015 // Third party copyrights are property of their respective owners.
00016 //
00017 // Redistribution and use in source and binary forms, with or without modification,
00018 // are permitted provided that the following conditions are met:
00019 //
00020 //   * Redistribution's of source code must retain the above copyright notice,
00021 //     this list of conditions and the following disclaimer.
00022 //
00023 //   * Redistribution's in binary form must reproduce the above copyright notice,
00024 //     this list of conditions and the following disclaimer in the documentation
00025 //     and/or other materials provided with the distribution.
00026 //
00027 //   * The name of the copyright holders may not be used to endorse or promote products
00028 //     derived from this software without specific prior written permission.
00029 //
00030 // This software is provided by the copyright holders and contributors "as is" and
00031 // any express or implied warranties, including, but not limited to, the implied
00032 // warranties of merchantability and fitness for a particular purpose are disclaimed.
00033 // In no event shall the Intel Corporation or contributors be liable for any direct,
00034 // indirect, incidental, special, exemplary, or consequential damages
00035 // (including, but not limited to, procurement of substitute goods or services;
00036 // loss of use, data, or profits; or business interruption) however caused
00037 // and on any theory of liability, whether in contract, strict liability,
00038 // or tort (including negligence or otherwise) arising in any way out of
00039 // the use of this software, even if advised of the possibility of such damage.
00040 //
00041 //M*/
00042 
00043 /* ////////////////////////////////////////////////////////////////////
00044 //
00045 //  Mat basic operations: Copy, Set
00046 //
00047 // */
00048 
00049 #include "precomp.hpp"
00050 #include "opencl_kernels_core.hpp"
00051 
00052 namespace cv
00053 {
00054 
00055 template<typename T> static void
00056 copyMask_(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size)
00057 {
00058     for( ; size.height--; mask += mstep, _src += sstep, _dst += dstep )
00059     {
00060         const T* src = (const T*)_src;
00061         T* dst = (T*)_dst;
00062         int x = 0;
00063          #if CV_ENABLE_UNROLLED
00064         for( ; x <= size.width - 4; x += 4 )
00065         {
00066             if( mask[x] )
00067                 dst[x] = src[x];
00068             if( mask[x+1] )
00069                 dst[x+1] = src[x+1];
00070             if( mask[x+2] )
00071                 dst[x+2] = src[x+2];
00072             if( mask[x+3] )
00073                 dst[x+3] = src[x+3];
00074         }
00075         #endif
00076         for( ; x < size.width; x++ )
00077             if( mask[x] )
00078                 dst[x] = src[x];
00079     }
00080 }
00081 
00082 template<> void
00083 copyMask_<uchar>(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size)
00084 {
00085     CV_IPP_RUN(true, ippiCopy_8u_C1MR(_src, (int)sstep, _dst, (int)dstep, ippiSize(size), mask, (int)mstep) >= 0)
00086 
00087     for( ; size.height--; mask += mstep, _src += sstep, _dst += dstep )
00088     {
00089         const uchar* src = (const uchar*)_src;
00090         uchar* dst = (uchar*)_dst;
00091         int x = 0;
00092         #if CV_SSE4_2
00093         if(USE_SSE4_2)//
00094         {
00095             __m128i zero = _mm_setzero_si128 ();
00096 
00097              for( ; x <= size.width - 16; x += 16 )
00098              {
00099                  const __m128i rSrc = _mm_lddqu_si128((const __m128i*)(src+x));
00100                  __m128i _mask = _mm_lddqu_si128((const __m128i*)(mask+x));
00101                  __m128i rDst = _mm_lddqu_si128((__m128i*)(dst+x));
00102                  __m128i _negMask = _mm_cmpeq_epi8(_mask, zero);
00103                  rDst = _mm_blendv_epi8(rSrc, rDst, _negMask);
00104                  _mm_storeu_si128((__m128i*)(dst + x), rDst);
00105              }
00106         }
00107         #elif CV_NEON
00108         uint8x16_t v_one = vdupq_n_u8(1);
00109         for( ; x <= size.width - 16; x += 16 )
00110         {
00111             uint8x16_t v_mask = vcgeq_u8(vld1q_u8(mask + x), v_one);
00112             uint8x16_t v_dst = vld1q_u8(dst + x), v_src = vld1q_u8(src + x);
00113             vst1q_u8(dst + x, vbslq_u8(v_mask, v_src, v_dst));
00114         }
00115         #endif
00116         for( ; x < size.width; x++ )
00117             if( mask[x] )
00118                 dst[x] = src[x];
00119     }
00120 }
00121 
00122 template<> void
00123 copyMask_<ushort>(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size)
00124 {
00125     CV_IPP_RUN(true, ippiCopy_16u_C1MR((const Ipp16u *)_src, (int)sstep, (Ipp16u *)_dst, (int)dstep, ippiSize(size), mask, (int)mstep) >= 0)
00126 
00127     for( ; size.height--; mask += mstep, _src += sstep, _dst += dstep )
00128     {
00129         const ushort* src = (const ushort*)_src;
00130         ushort* dst = (ushort*)_dst;
00131         int x = 0;
00132         #if CV_SSE4_2
00133         if(USE_SSE4_2)//
00134         {
00135             __m128i zero = _mm_setzero_si128 ();
00136             for( ; x <= size.width - 8; x += 8 )
00137             {
00138                  const __m128i rSrc =_mm_lddqu_si128((const __m128i*)(src+x));
00139                  __m128i _mask = _mm_loadl_epi64((const __m128i*)(mask+x));
00140                  _mask = _mm_unpacklo_epi8(_mask, _mask);
00141                  __m128i rDst = _mm_lddqu_si128((const __m128i*)(dst+x));
00142                  __m128i _negMask = _mm_cmpeq_epi8(_mask, zero);
00143                  rDst = _mm_blendv_epi8(rSrc, rDst, _negMask);
00144                  _mm_storeu_si128((__m128i*)(dst + x), rDst);
00145              }
00146         }
00147         #elif CV_NEON
00148         uint8x8_t v_one = vdup_n_u8(1);
00149         for( ; x <= size.width - 8; x += 8 )
00150         {
00151             uint8x8_t v_mask = vcge_u8(vld1_u8(mask + x), v_one);
00152             uint8x8x2_t v_mask2 = vzip_u8(v_mask, v_mask);
00153             uint16x8_t v_mask_res = vreinterpretq_u16_u8(vcombine_u8(v_mask2.val[0], v_mask2.val[1]));
00154 
00155             uint16x8_t v_src = vld1q_u16(src + x), v_dst = vld1q_u16(dst + x);
00156             vst1q_u16(dst + x, vbslq_u16(v_mask_res, v_src, v_dst));
00157         }
00158         #endif
00159         for( ; x < size.width; x++ )
00160             if( mask[x] )
00161                 dst[x] = src[x];
00162     }
00163 }
00164 
00165 static void
00166 copyMaskGeneric(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size, void* _esz)
00167 {
00168     size_t k, esz = *(size_t*)_esz;
00169     for( ; size.height--; mask += mstep, _src += sstep, _dst += dstep )
00170     {
00171         const uchar* src = _src;
00172         uchar* dst = _dst;
00173         int x = 0;
00174         for( ; x < size.width; x++, src += esz, dst += esz )
00175         {
00176             if( !mask[x] )
00177                 continue;
00178             for( k = 0; k < esz; k++ )
00179                 dst[k] = src[k];
00180         }
00181     }
00182 }
00183 
00184 
00185 #define DEF_COPY_MASK(suffix, type) \
00186 static void copyMask##suffix(const uchar* src, size_t sstep, const uchar* mask, size_t mstep, \
00187                              uchar* dst, size_t dstep, Size size, void*) \
00188 { \
00189     copyMask_<type>(src, sstep, mask, mstep, dst, dstep, size); \
00190 }
00191 
00192 #if defined HAVE_IPP
00193 #define DEF_COPY_MASK_F(suffix, type, ippfavor, ipptype) \
00194 static void copyMask##suffix(const uchar* src, size_t sstep, const uchar* mask, size_t mstep, \
00195                              uchar* dst, size_t dstep, Size size, void*) \
00196 { \
00197     CV_IPP_RUN(true, ippiCopy_##ippfavor((const ipptype *)src, (int)sstep, (ipptype *)dst, (int)dstep, ippiSize(size), (const Ipp8u *)mask, (int)mstep) >= 0)\
00198     copyMask_<type>(src, sstep, mask, mstep, dst, dstep, size); \
00199 }
00200 #else
00201 #define DEF_COPY_MASK_F(suffix, type, ippfavor, ipptype) \
00202 static void copyMask##suffix(const uchar* src, size_t sstep, const uchar* mask, size_t mstep, \
00203                              uchar* dst, size_t dstep, Size size, void*) \
00204 { \
00205     copyMask_<type>(src, sstep, mask, mstep, dst, dstep, size); \
00206 }
00207 #endif
00208 
00209 #if IPP_VERSION_X100 == 901 // bug in IPP 9.0.1
00210 DEF_COPY_MASK(32sC3, Vec3i)
00211 DEF_COPY_MASK(8uC3, Vec3b)
00212 #else
00213 DEF_COPY_MASK_F(8uC3, Vec3b, 8u_C3MR, Ipp8u)
00214 DEF_COPY_MASK_F(32sC3, Vec3i, 32s_C3MR, Ipp32s)
00215 #endif
00216 DEF_COPY_MASK(8u, uchar)
00217 DEF_COPY_MASK(16u, ushort)
00218 DEF_COPY_MASK_F(32s, int, 32s_C1MR, Ipp32s)
00219 DEF_COPY_MASK_F(16uC3, Vec3s, 16u_C3MR, Ipp16u)
00220 DEF_COPY_MASK(32sC2, Vec2i)
00221 DEF_COPY_MASK_F(32sC4, Vec4i, 32s_C4MR, Ipp32s)
00222 DEF_COPY_MASK(32sC6, Vec6i)
00223 DEF_COPY_MASK(32sC8, Vec8i)
00224 
00225 BinaryFunc copyMaskTab[] =
00226 {
00227     0,
00228     copyMask8u,
00229     copyMask16u,
00230     copyMask8uC3,
00231     copyMask32s,
00232     0,
00233     copyMask16uC3,
00234     0,
00235     copyMask32sC2,
00236     0, 0, 0,
00237     copyMask32sC3,
00238     0, 0, 0,
00239     copyMask32sC4,
00240     0, 0, 0, 0, 0, 0, 0,
00241     copyMask32sC6,
00242     0, 0, 0, 0, 0, 0, 0,
00243     copyMask32sC8
00244 };
00245 
00246 BinaryFunc getCopyMaskFunc(size_t esz)
00247 {
00248     return esz <= 32 && copyMaskTab[esz] ? copyMaskTab[esz] : copyMaskGeneric;
00249 }
00250 
00251 /* dst = src */
00252 void Mat::copyTo( OutputArray _dst ) const
00253 {
00254     int dtype = _dst.type();
00255     if( _dst.fixedType() && dtype != type() )
00256     {
00257         CV_Assert( channels() == CV_MAT_CN(dtype) );
00258         convertTo( _dst, dtype );
00259         return;
00260     }
00261 
00262     if( empty() )
00263     {
00264         _dst.release();
00265         return;
00266     }
00267 
00268     if( _dst.isUMat() )
00269     {
00270         _dst.create( dims, size.p, type() );
00271         UMat  dst = _dst.getUMat();
00272 
00273         size_t i, sz[CV_MAX_DIM], dstofs[CV_MAX_DIM], esz = elemSize();
00274         for( i = 0; i < (size_t)dims; i++ )
00275             sz[i] = size.p[i];
00276         sz[dims-1] *= esz;
00277         dst.ndoffset(dstofs);
00278         dstofs[dims-1] *= esz;
00279         dst.u->currAllocator->upload(dst.u, data, dims, sz, dstofs, dst.step.p, step.p);
00280         return;
00281     }
00282 
00283     if( dims <= 2 )
00284     {
00285         _dst.create( rows, cols, type() );
00286         Mat dst = _dst.getMat();
00287         if( data == dst.data )
00288             return;
00289 
00290         if( rows > 0 && cols > 0 )
00291         {
00292             // For some cases (with vector) dst.size != src.size, so force to column-based form
00293             // It prevents memory corruption in case of column-based src
00294             if (_dst.isVector())
00295                 dst = dst.reshape(0, (int)dst.total());
00296 
00297             const uchar* sptr = data;
00298             uchar* dptr = dst.data;
00299 
00300             CV_IPP_RUN(
00301                     (size_t)cols*elemSize() <= (size_t)INT_MAX &&
00302                     (size_t)step <= (size_t)INT_MAX &&
00303                     (size_t)dst.step <= (size_t)INT_MAX
00304                     ,
00305                     ippiCopy_8u_C1R(sptr, (int)step, dptr, (int)dst.step, ippiSize((int)(cols*elemSize()), rows)) >= 0
00306             )
00307 
00308             Size sz = getContinuousSize(*this, dst);
00309             size_t len = sz.width*elemSize();
00310 
00311             for( ; sz.height--; sptr += step, dptr += dst.step )
00312                 memcpy( dptr, sptr, len );
00313         }
00314         return;
00315     }
00316 
00317     _dst.create( dims, size, type() );
00318     Mat dst = _dst.getMat();
00319     if( data == dst.data )
00320         return;
00321 
00322     if( total() != 0 )
00323     {
00324         const Mat* arrays[] = { this, &dst };
00325         uchar* ptrs[2];
00326         NAryMatIterator it(arrays, ptrs, 2);
00327         size_t sz = it.size*elemSize();
00328 
00329         for( size_t i = 0; i < it.nplanes; i++, ++it )
00330             memcpy(ptrs[1], ptrs[0], sz);
00331     }
00332 }
00333 
00334 void Mat::copyTo( OutputArray _dst, InputArray _mask ) const
00335 {
00336     Mat mask = _mask.getMat();
00337     if( !mask.data )
00338     {
00339         copyTo(_dst);
00340         return;
00341     }
00342 
00343     int cn = channels(), mcn = mask.channels();
00344     CV_Assert( mask.depth() == CV_8U && (mcn == 1 || mcn == cn) );
00345     bool colorMask = mcn > 1;
00346 
00347     size_t esz = colorMask ? elemSize1() : elemSize();
00348     BinaryFunc copymask = getCopyMaskFunc(esz);
00349 
00350     uchar* data0 = _dst.getMat().data;
00351     _dst.create( dims, size, type() );
00352     Mat dst = _dst.getMat();
00353 
00354     if( dst.data != data0 ) // do not leave dst uninitialized
00355         dst = Scalar (0);
00356 
00357     if( dims <= 2 )
00358     {
00359         CV_Assert( size() == mask.size() );
00360         Size sz = getContinuousSize(*this, dst, mask, mcn);
00361         copymask(data, step, mask.data, mask.step, dst.data, dst.step, sz, &esz);
00362         return;
00363     }
00364 
00365     const Mat* arrays[] = { this, &dst, &mask, 0 };
00366     uchar* ptrs[3];
00367     NAryMatIterator it(arrays, ptrs);
00368     Size sz((int)(it.size*mcn), 1);
00369 
00370     for( size_t i = 0; i < it.nplanes; i++, ++it )
00371         copymask(ptrs[0], 0, ptrs[2], 0, ptrs[1], 0, sz, &esz);
00372 }
00373 
00374 Mat& Mat::operator = (const Scalar & s)
00375 {
00376     const Mat* arrays[] = { this };
00377     uchar* dptr;
00378     NAryMatIterator it(arrays, &dptr, 1);
00379     size_t elsize = it.size*elemSize();
00380     const int64* is = (const int64*)&s.val[0];
00381 
00382     if( is[0] == 0 && is[1] == 0 && is[2] == 0 && is[3] == 0 )
00383     {
00384 #if defined HAVE_IPP && !defined HAVE_IPP_ICV_ONLY && IPP_DISABLE_BLOCK
00385         CV_IPP_CHECK()
00386         {
00387             if (dims <= 2 || isContinuous())
00388             {
00389                 IppiSize roisize = { cols, rows };
00390                 if (isContinuous())
00391                 {
00392                     roisize.width = (int)total();
00393                     roisize.height = 1;
00394 
00395                     if (ippsZero_8u(data, static_cast<int>(roisize.width * elemSize())) >= 0)
00396                     {
00397                         CV_IMPL_ADD(CV_IMPL_IPP)
00398                         return *this;
00399                     }
00400                     setIppErrorStatus();
00401                 }
00402                 roisize.width *= (int)elemSize();
00403 
00404                 if (ippiSet_8u_C1R(0, data, (int)step, roisize) >= 0)
00405                 {
00406                     CV_IMPL_ADD(CV_IMPL_IPP)
00407                     return *this;
00408                 }
00409                 setIppErrorStatus();
00410             }
00411         }
00412 #endif
00413 
00414         for( size_t i = 0; i < it.nplanes; i++, ++it )
00415             memset( dptr, 0, elsize );
00416     }
00417     else
00418     {
00419         if( it.nplanes > 0 )
00420         {
00421             double scalar[12];
00422             scalarToRawData(s, scalar, type(), 12);
00423             size_t blockSize = 12*elemSize1();
00424 
00425             for( size_t j = 0; j < elsize; j += blockSize )
00426             {
00427                 size_t sz = MIN(blockSize, elsize - j);
00428                 memcpy( dptr + j, scalar, sz );
00429             }
00430         }
00431 
00432         for( size_t i = 1; i < it.nplanes; i++ )
00433         {
00434             ++it;
00435             memcpy( dptr, data, elsize );
00436         }
00437     }
00438     return *this;
00439 }
00440 
00441 #if defined HAVE_IPP
00442 static bool ipp_Mat_setTo(Mat *src, Mat &value, Mat &mask)
00443 {
00444     int cn = src->channels(), depth0 = src->depth();
00445 
00446     if (!mask.empty() && (src->dims <= 2 || (src->isContinuous() && mask.isContinuous())) &&
00447             (/*depth0 == CV_8U ||*/ depth0 == CV_16U || depth0 == CV_16S || depth0 == CV_32S || depth0 == CV_32F) &&
00448             (cn == 1 || cn == 3 || cn == 4))
00449     {
00450         uchar _buf[32];
00451         void * buf = _buf;
00452         convertAndUnrollScalar( value, src->type(), _buf, 1 );
00453 
00454         IppStatus status = (IppStatus)-1;
00455         IppiSize roisize = { src->cols, src->rows };
00456         int mstep = (int)mask.step[0], dstep = (int)src->step[0];
00457 
00458         if (src->isContinuous() && mask.isContinuous())
00459         {
00460             roisize.width = (int)src->total();
00461             roisize.height = 1;
00462         }
00463 
00464         if (cn == 1)
00465         {
00466             /*if (depth0 == CV_8U)
00467                 status = ippiSet_8u_C1MR(*(Ipp8u *)buf, (Ipp8u *)data, dstep, roisize, mask.data, mstep);
00468             else*/ if (depth0 == CV_16U)
00469                 status = ippiSet_16u_C1MR(*(Ipp16u *)buf, (Ipp16u *)src->data, dstep, roisize, mask.data, mstep);
00470             else if (depth0 == CV_16S)
00471                 status = ippiSet_16s_C1MR(*(Ipp16s *)buf, (Ipp16s *)src->data, dstep, roisize, mask.data, mstep);
00472             else if (depth0 == CV_32S)
00473                 status = ippiSet_32s_C1MR(*(Ipp32s *)buf, (Ipp32s *)src->data, dstep, roisize, mask.data, mstep);
00474             else if (depth0 == CV_32F)
00475                 status = ippiSet_32f_C1MR(*(Ipp32f *)buf, (Ipp32f *)src->data, dstep, roisize, mask.data, mstep);
00476         }
00477         else if (cn == 3 || cn == 4)
00478         {
00479 
00480 #define IPP_SET(ippfavor, ippcn) \
00481             do \
00482             { \
00483                 typedef Ipp##ippfavor ipptype; \
00484                 ipptype ippvalue[4] = { ((ipptype *)buf)[0], ((ipptype *)buf)[1], ((ipptype *)buf)[2], ((ipptype *)buf)[3] }; \
00485                 status = ippiSet_##ippfavor##_C##ippcn##MR(ippvalue, (ipptype *)src->data, dstep, roisize, mask.data, mstep); \
00486             } while ((void)0, 0)
00487 
00488 #define IPP_SET_CN(ippcn) \
00489             do \
00490             { \
00491                 if (cn == ippcn) \
00492                 { \
00493                     /*if (depth0 == CV_8U) \
00494                         IPP_SET(8u, ippcn); \
00495                     else*/ if (depth0 == CV_16U) \
00496                         IPP_SET(16u, ippcn); \
00497                     else if (depth0 == CV_16S) \
00498                         IPP_SET(16s, ippcn); \
00499                     else if (depth0 == CV_32S) \
00500                         IPP_SET(32s, ippcn); \
00501                     else if (depth0 == CV_32F) \
00502                         IPP_SET(32f, ippcn); \
00503                 } \
00504             } while ((void)0, 0)
00505 
00506             IPP_SET_CN(3);
00507             IPP_SET_CN(4);
00508 
00509 #undef IPP_SET_CN
00510 #undef IPP_SET
00511         }
00512 
00513         if (status >= 0)
00514             return true;
00515     }
00516 
00517     return false;
00518 }
00519 #endif
00520 
00521 
00522 Mat& Mat::setTo(InputArray _value, InputArray _mask)
00523 {
00524     if( empty() )
00525         return *this;
00526 
00527     Mat value = _value.getMat(), mask = _mask.getMat();
00528 
00529     CV_Assert( checkScalar(value, type(), _value.kind(), _InputArray::MAT ));
00530     CV_Assert( mask.empty() || (mask.type() == CV_8U && size == mask.size) );
00531 
00532     CV_IPP_RUN(true, ipp_Mat_setTo((cv::Mat*)this, value, mask), *this)
00533 
00534     size_t esz = elemSize();
00535     BinaryFunc copymask = getCopyMaskFunc(esz);
00536 
00537     const Mat* arrays[] = { this, !mask.empty() ? &mask : 0, 0 };
00538     uchar* ptrs[2]={0,0};
00539     NAryMatIterator it(arrays, ptrs);
00540     int totalsz = (int)it.size, blockSize0 = std::min(totalsz, (int)((BLOCK_SIZE + esz-1)/esz));
00541     AutoBuffer<uchar>  _scbuf(blockSize0*esz + 32);
00542     uchar* scbuf = alignPtr((uchar*)_scbuf, (int)sizeof(double));
00543     convertAndUnrollScalar( value, type(), scbuf, blockSize0 );
00544 
00545     for( size_t i = 0; i < it.nplanes; i++, ++it )
00546     {
00547         for( int j = 0; j < totalsz; j += blockSize0 )
00548         {
00549             Size sz(std::min(blockSize0, totalsz - j), 1);
00550             size_t blockSize = sz.width*esz;
00551             if( ptrs[1] )
00552             {
00553                 copymask(scbuf, 0, ptrs[1], 0, ptrs[0], 0, sz, &esz);
00554                 ptrs[1] += sz.width;
00555             }
00556             else
00557                 memcpy(ptrs[0], scbuf, blockSize);
00558             ptrs[0] += blockSize;
00559         }
00560     }
00561     return *this;
00562 }
00563 
00564 
00565 static void
00566 flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, size_t esz )
00567 {
00568     int i, j, limit = (int)(((size.width + 1)/2)*esz);
00569     AutoBuffer<int>  _tab(size.width*esz);
00570     int* tab = _tab;
00571 
00572     for( i = 0; i < size.width; i++ )
00573         for( size_t k = 0; k < esz; k++ )
00574             tab[i*esz + k] = (int)((size.width - i - 1)*esz + k);
00575 
00576     for( ; size.height--; src += sstep, dst += dstep )
00577     {
00578         for( i = 0; i < limit; i++ )
00579         {
00580             j = tab[i];
00581             uchar t0 = src[i], t1 = src[j];
00582             dst[i] = t1; dst[j] = t0;
00583         }
00584     }
00585 }
00586 
00587 static void
00588 flipVert( const uchar* src0, size_t sstep, uchar* dst0, size_t dstep, Size size, size_t esz )
00589 {
00590     const uchar* src1 = src0 + (size.height - 1)*sstep;
00591     uchar* dst1 = dst0 + (size.height - 1)*dstep;
00592     size.width *= (int)esz;
00593 
00594     for( int y = 0; y < (size.height + 1)/2; y++, src0 += sstep, src1 -= sstep,
00595                                                   dst0 += dstep, dst1 -= dstep )
00596     {
00597         int i = 0;
00598         if( ((size_t)src0|(size_t)dst0|(size_t)src1|(size_t)dst1) % sizeof(int) == 0 )
00599         {
00600             for( ; i <= size.width - 16; i += 16 )
00601             {
00602                 int t0 = ((int*)(src0 + i))[0];
00603                 int t1 = ((int*)(src1 + i))[0];
00604 
00605                 ((int*)(dst0 + i))[0] = t1;
00606                 ((int*)(dst1 + i))[0] = t0;
00607 
00608                 t0 = ((int*)(src0 + i))[1];
00609                 t1 = ((int*)(src1 + i))[1];
00610 
00611                 ((int*)(dst0 + i))[1] = t1;
00612                 ((int*)(dst1 + i))[1] = t0;
00613 
00614                 t0 = ((int*)(src0 + i))[2];
00615                 t1 = ((int*)(src1 + i))[2];
00616 
00617                 ((int*)(dst0 + i))[2] = t1;
00618                 ((int*)(dst1 + i))[2] = t0;
00619 
00620                 t0 = ((int*)(src0 + i))[3];
00621                 t1 = ((int*)(src1 + i))[3];
00622 
00623                 ((int*)(dst0 + i))[3] = t1;
00624                 ((int*)(dst1 + i))[3] = t0;
00625             }
00626 
00627             for( ; i <= size.width - 4; i += 4 )
00628             {
00629                 int t0 = ((int*)(src0 + i))[0];
00630                 int t1 = ((int*)(src1 + i))[0];
00631 
00632                 ((int*)(dst0 + i))[0] = t1;
00633                 ((int*)(dst1 + i))[0] = t0;
00634             }
00635         }
00636 
00637         for( ; i < size.width; i++ )
00638         {
00639             uchar t0 = src0[i];
00640             uchar t1 = src1[i];
00641 
00642             dst0[i] = t1;
00643             dst1[i] = t0;
00644         }
00645     }
00646 }
00647 
00648 #ifdef HAVE_OPENCL
00649 
00650 enum { FLIP_COLS = 1 << 0, FLIP_ROWS = 1 << 1, FLIP_BOTH = FLIP_ROWS | FLIP_COLS };
00651 
00652 static bool ocl_flip(InputArray _src, OutputArray _dst, int flipCode )
00653 {
00654     CV_Assert(flipCode >= -1 && flipCode <= 1);
00655 
00656     const ocl::Device & dev = ocl::Device::getDefault();
00657     int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type),
00658             flipType, kercn = std::min(ocl::predictOptimalVectorWidth(_src, _dst), 4);
00659 
00660     bool doubleSupport = dev.doubleFPConfig() > 0;
00661     if (!doubleSupport && depth == CV_64F)
00662         kercn = cn;
00663 
00664     if (cn > 4)
00665         return false;
00666 
00667     const char * kernelName;
00668     if (flipCode == 0)
00669         kernelName = "arithm_flip_rows", flipType = FLIP_ROWS;
00670     else if (flipCode > 0)
00671         kernelName = "arithm_flip_cols", flipType = FLIP_COLS;
00672     else
00673         kernelName = "arithm_flip_rows_cols", flipType = FLIP_BOTH;
00674 
00675     int pxPerWIy = (dev.isIntel() && (dev.type() & ocl::Device::TYPE_GPU)) ? 4 : 1;
00676     kercn = (cn!=3 || flipType == FLIP_ROWS) ? std::max(kercn, cn) : cn;
00677 
00678     ocl::Kernel k(kernelName, ocl::core::flip_oclsrc,
00679         format( "-D T=%s -D T1=%s -D cn=%d -D PIX_PER_WI_Y=%d -D kercn=%d",
00680                 kercn != cn ? ocl::typeToStr(CV_MAKE_TYPE(depth, kercn)) : ocl::vecopTypeToStr(CV_MAKE_TYPE(depth, kercn)),
00681                 kercn != cn ? ocl::typeToStr(depth) : ocl::vecopTypeToStr(depth), cn, pxPerWIy, kercn));
00682     if (k.empty())
00683         return false;
00684 
00685     Size size = _src.size();
00686     _dst.create(size, type);
00687     UMat src = _src.getUMat(), dst = _dst.getUMat();
00688 
00689     int cols = size.width * cn / kercn, rows = size.height;
00690     cols = flipType == FLIP_COLS ? (cols + 1) >> 1 : cols;
00691     rows = flipType & FLIP_ROWS ? (rows + 1) >> 1 : rows;
00692 
00693     k.args(ocl::KernelArg::ReadOnlyNoSize(src),
00694            ocl::KernelArg::WriteOnly(dst, cn, kercn), rows, cols);
00695 
00696     size_t maxWorkGroupSize = dev.maxWorkGroupSize();
00697     CV_Assert(maxWorkGroupSize % 4 == 0);
00698 
00699     size_t globalsize[2] = { (size_t)cols, ((size_t)rows + pxPerWIy - 1) / pxPerWIy },
00700             localsize[2] = { maxWorkGroupSize / 4, 4 };
00701     return k.run(2, globalsize, (flipType == FLIP_COLS) && !dev.isIntel() ? localsize : NULL, false);
00702 }
00703 
00704 #endif
00705 
00706 #if defined HAVE_IPP
00707 static bool ipp_flip( Mat &src, Mat &dst, int flip_mode )
00708 {
00709     int type = src.type();
00710 
00711     typedef IppStatus (CV_STDCALL * ippiMirror)(const void * pSrc, int srcStep, void * pDst, int dstStep, IppiSize roiSize, IppiAxis flip);
00712     typedef IppStatus (CV_STDCALL * ippiMirrorI)(const void * pSrcDst, int srcDstStep, IppiSize roiSize, IppiAxis flip);
00713     ippiMirror ippFunc = 0;
00714     ippiMirrorI ippFuncI = 0;
00715 
00716     if (src.data == dst.data)
00717     {
00718         CV_SUPPRESS_DEPRECATED_START
00719         ippFuncI =
00720             type == CV_8UC1 ? (ippiMirrorI)ippiMirror_8u_C1IR :
00721             type == CV_8UC3 ? (ippiMirrorI)ippiMirror_8u_C3IR :
00722             type == CV_8UC4 ? (ippiMirrorI)ippiMirror_8u_C4IR :
00723             type == CV_16UC1 ? (ippiMirrorI)ippiMirror_16u_C1IR :
00724             type == CV_16UC3 ? (ippiMirrorI)ippiMirror_16u_C3IR :
00725             type == CV_16UC4 ? (ippiMirrorI)ippiMirror_16u_C4IR :
00726             type == CV_16SC1 ? (ippiMirrorI)ippiMirror_16s_C1IR :
00727             type == CV_16SC3 ? (ippiMirrorI)ippiMirror_16s_C3IR :
00728             type == CV_16SC4 ? (ippiMirrorI)ippiMirror_16s_C4IR :
00729             type == CV_32SC1 ? (ippiMirrorI)ippiMirror_32s_C1IR :
00730             type == CV_32SC3 ? (ippiMirrorI)ippiMirror_32s_C3IR :
00731             type == CV_32SC4 ? (ippiMirrorI)ippiMirror_32s_C4IR :
00732             type == CV_32FC1 ? (ippiMirrorI)ippiMirror_32f_C1IR :
00733             type == CV_32FC3 ? (ippiMirrorI)ippiMirror_32f_C3IR :
00734             type == CV_32FC4 ? (ippiMirrorI)ippiMirror_32f_C4IR : 0;
00735         CV_SUPPRESS_DEPRECATED_END
00736     }
00737     else
00738     {
00739         ippFunc =
00740             type == CV_8UC1 ? (ippiMirror)ippiMirror_8u_C1R :
00741             type == CV_8UC3 ? (ippiMirror)ippiMirror_8u_C3R :
00742             type == CV_8UC4 ? (ippiMirror)ippiMirror_8u_C4R :
00743             type == CV_16UC1 ? (ippiMirror)ippiMirror_16u_C1R :
00744             type == CV_16UC3 ? (ippiMirror)ippiMirror_16u_C3R :
00745             type == CV_16UC4 ? (ippiMirror)ippiMirror_16u_C4R :
00746             type == CV_16SC1 ? (ippiMirror)ippiMirror_16s_C1R :
00747             type == CV_16SC3 ? (ippiMirror)ippiMirror_16s_C3R :
00748             type == CV_16SC4 ? (ippiMirror)ippiMirror_16s_C4R :
00749             type == CV_32SC1 ? (ippiMirror)ippiMirror_32s_C1R :
00750             type == CV_32SC3 ? (ippiMirror)ippiMirror_32s_C3R :
00751             type == CV_32SC4 ? (ippiMirror)ippiMirror_32s_C4R :
00752             type == CV_32FC1 ? (ippiMirror)ippiMirror_32f_C1R :
00753             type == CV_32FC3 ? (ippiMirror)ippiMirror_32f_C3R :
00754             type == CV_32FC4 ? (ippiMirror)ippiMirror_32f_C4R : 0;
00755     }
00756     IppiAxis axis = flip_mode == 0 ? ippAxsHorizontal :
00757         flip_mode > 0 ? ippAxsVertical : ippAxsBoth;
00758     IppiSize roisize = { dst.cols, dst.rows };
00759 
00760     if (ippFunc != 0)
00761     {
00762         if (ippFunc(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, ippiSize(src.cols, src.rows), axis) >= 0)
00763             return true;
00764     }
00765     else if (ippFuncI != 0)
00766     {
00767         if (ippFuncI(dst.ptr(), (int)dst.step, roisize, axis) >= 0)
00768             return true;
00769     }
00770 
00771     return false;
00772 }
00773 #endif
00774 
00775 
00776 void flip( InputArray _src, OutputArray _dst, int flip_mode )
00777 {
00778     CV_Assert( _src.dims() <= 2 );
00779     Size size = _src.size();
00780 
00781     if (flip_mode < 0)
00782     {
00783         if (size.width == 1)
00784             flip_mode = 0;
00785         if (size.height == 1)
00786             flip_mode = 1;
00787     }
00788 
00789     if ((size.width == 1 && flip_mode > 0) ||
00790         (size.height == 1 && flip_mode == 0) ||
00791         (size.height == 1 && size.width == 1 && flip_mode < 0))
00792     {
00793         return _src.copyTo(_dst);
00794     }
00795 
00796 #ifdef HAVE_OPENCL
00797     CV_OCL_RUN( _dst.isUMat(), ocl_flip(_src, _dst, flip_mode))
00798 #endif
00799 
00800     Mat src = _src.getMat();
00801     int type = src.type();
00802     _dst.create( size, type );
00803     Mat dst = _dst.getMat();
00804 
00805     CV_IPP_RUN(true, ipp_flip(src, dst, flip_mode));
00806 
00807     size_t esz = CV_ELEM_SIZE(type);
00808 
00809     if( flip_mode <= 0 )
00810         flipVert( src.ptr(), src.step, dst.ptr(), dst.step, src.size(), esz );
00811     else
00812         flipHoriz( src.ptr(), src.step, dst.ptr(), dst.step, src.size(), esz );
00813 
00814     if( flip_mode < 0 )
00815         flipHoriz( dst.ptr(), dst.step, dst.ptr(), dst.step, dst.size(), esz );
00816 }
00817 
00818 #if defined HAVE_OPENCL && !defined __APPLE__
00819 
00820 static bool ocl_repeat(InputArray _src, int ny, int nx, OutputArray _dst)
00821 {
00822     if (ny == 1 && nx == 1)
00823     {
00824         _src.copyTo(_dst);
00825         return true;
00826     }
00827 
00828     int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type),
00829             rowsPerWI = ocl::Device::getDefault().isIntel() ? 4 : 1,
00830             kercn = ocl::predictOptimalVectorWidth(_src, _dst);
00831 
00832     ocl::Kernel k("repeat", ocl::core::repeat_oclsrc,
00833                   format("-D T=%s -D nx=%d -D ny=%d -D rowsPerWI=%d -D cn=%d",
00834                          ocl::memopTypeToStr(CV_MAKE_TYPE(depth, kercn)),
00835                          nx, ny, rowsPerWI, kercn));
00836     if (k.empty())
00837         return false;
00838 
00839     UMat src = _src.getUMat(), dst = _dst.getUMat();
00840     k.args(ocl::KernelArg::ReadOnly(src, cn, kercn), ocl::KernelArg::WriteOnlyNoSize(dst));
00841 
00842     size_t globalsize[] = { (size_t)src.cols * cn / kercn, ((size_t)src.rows + rowsPerWI - 1) / rowsPerWI };
00843     return k.run(2, globalsize, NULL, false);
00844 }
00845 
00846 #endif
00847 
00848 void repeat(InputArray _src, int ny, int nx, OutputArray _dst)
00849 {
00850     CV_Assert( _src.dims() <= 2 );
00851     CV_Assert( ny > 0 && nx > 0 );
00852 
00853     Size ssize = _src.size();
00854     _dst.create(ssize.height*ny, ssize.width*nx, _src.type());
00855 
00856 #if !defined __APPLE__
00857 #ifdef HAVE_OPENCL
00858     CV_OCL_RUN(_dst.isUMat(),
00859                ocl_repeat(_src, ny, nx, _dst))
00860 #endif
00861 #endif
00862 
00863     Mat src = _src.getMat(), dst = _dst.getMat();
00864     Size dsize = dst.size();
00865     int esz = (int)src.elemSize();
00866     int x, y;
00867     ssize.width *= esz; dsize.width *= esz;
00868 
00869     for( y = 0; y < ssize.height; y++ )
00870     {
00871         for( x = 0; x < dsize.width; x += ssize.width )
00872             memcpy( dst.ptr(y) + x, src.ptr(y), ssize.width );
00873     }
00874 
00875     for( ; y < dsize.height; y++ )
00876         memcpy( dst.ptr(y), dst.ptr(y - ssize.height), dsize.width );
00877 }
00878 
00879 Mat repeat(const Mat& src, int ny, int nx)
00880 {
00881     if( nx == 1 && ny == 1 )
00882         return src;
00883     Mat dst;
00884     repeat(src, ny, nx, dst);
00885     return dst;
00886 }
00887 
00888 
00889 } // cv
00890 
00891 
00892 /*
00893  Various border types, image boundaries are denoted with '|'
00894 
00895  * BORDER_REPLICATE:     aaaaaa|abcdefgh|hhhhhhh
00896  * BORDER_REFLECT:       fedcba|abcdefgh|hgfedcb
00897  * BORDER_REFLECT_101:   gfedcb|abcdefgh|gfedcba
00898  * BORDER_WRAP:          cdefgh|abcdefgh|abcdefg
00899  * BORDER_CONSTANT:      iiiiii|abcdefgh|iiiiiii  with some specified 'i'
00900  */
00901 int cv::borderInterpolate( int p, int len, int borderType )
00902 {
00903     if( (unsigned)p < (unsigned)len )
00904         ;
00905     else if( borderType == BORDER_REPLICATE )
00906         p = p < 0 ? 0 : len - 1;
00907     else if( borderType == BORDER_REFLECT || borderType == BORDER_REFLECT_101 )
00908     {
00909         int delta = borderType == BORDER_REFLECT_101;
00910         if( len == 1 )
00911             return 0;
00912         do
00913         {
00914             if( p < 0 )
00915                 p = -p - 1 + delta;
00916             else
00917                 p = len - 1 - (p - len) - delta;
00918         }
00919         while( (unsigned)p >= (unsigned)len );
00920     }
00921     else if( borderType == BORDER_WRAP )
00922     {
00923         CV_Assert(len > 0);
00924         if( p < 0 )
00925             p -= ((p-len+1)/len)*len;
00926         if( p >= len )
00927             p %= len;
00928     }
00929     else if( borderType == BORDER_CONSTANT )
00930         p = -1;
00931     else
00932         CV_Error( CV_StsBadArg, "Unknown/unsupported border type" );
00933     return p;
00934 }
00935 
00936 namespace
00937 {
00938 
00939 void copyMakeBorder_8u( const uchar* src, size_t srcstep, cv::Size srcroi,
00940                         uchar* dst, size_t dststep, cv::Size dstroi,
00941                         int top, int left, int cn, int borderType )
00942 {
00943     const int isz = (int)sizeof(int);
00944     int i, j, k, elemSize = 1;
00945     bool intMode = false;
00946 
00947     if( (cn | srcstep | dststep | (size_t)src | (size_t)dst) % isz == 0 )
00948     {
00949         cn /= isz;
00950         elemSize = isz;
00951         intMode = true;
00952     }
00953 
00954     cv::AutoBuffer<int>  _tab((dstroi.width - srcroi.width)*cn);
00955     int* tab = _tab;
00956     int right = dstroi.width - srcroi.width - left;
00957     int bottom = dstroi.height - srcroi.height - top;
00958 
00959     for( i = 0; i < left; i++ )
00960     {
00961         j = cv::borderInterpolate(i - left, srcroi.width, borderType)*cn;
00962         for( k = 0; k < cn; k++ )
00963             tab[i*cn + k] = j + k;
00964     }
00965 
00966     for( i = 0; i < right; i++ )
00967     {
00968         j = cv::borderInterpolate(srcroi.width + i, srcroi.width, borderType)*cn;
00969         for( k = 0; k < cn; k++ )
00970             tab[(i+left)*cn + k] = j + k;
00971     }
00972 
00973     srcroi.width *= cn;
00974     dstroi.width *= cn;
00975     left *= cn;
00976     right *= cn;
00977 
00978     uchar* dstInner = dst + dststep*top + left*elemSize;
00979 
00980     for( i = 0; i < srcroi.height; i++, dstInner += dststep, src += srcstep )
00981     {
00982         if( dstInner != src )
00983             memcpy(dstInner, src, srcroi.width*elemSize);
00984 
00985         if( intMode )
00986         {
00987             const int* isrc = (int*)src;
00988             int* idstInner = (int*)dstInner;
00989             for( j = 0; j < left; j++ )
00990                 idstInner[j - left] = isrc[tab[j]];
00991             for( j = 0; j < right; j++ )
00992                 idstInner[j + srcroi.width] = isrc[tab[j + left]];
00993         }
00994         else
00995         {
00996             for( j = 0; j < left; j++ )
00997                 dstInner[j - left] = src[tab[j]];
00998             for( j = 0; j < right; j++ )
00999                 dstInner[j + srcroi.width] = src[tab[j + left]];
01000         }
01001     }
01002 
01003     dstroi.width *= elemSize;
01004     dst += dststep*top;
01005 
01006     for( i = 0; i < top; i++ )
01007     {
01008         j = cv::borderInterpolate(i - top, srcroi.height, borderType);
01009         memcpy(dst + (i - top)*dststep, dst + j*dststep, dstroi.width);
01010     }
01011 
01012     for( i = 0; i < bottom; i++ )
01013     {
01014         j = cv::borderInterpolate(i + srcroi.height, srcroi.height, borderType);
01015         memcpy(dst + (i + srcroi.height)*dststep, dst + j*dststep, dstroi.width);
01016     }
01017 }
01018 
01019 
01020 void copyMakeConstBorder_8u( const uchar* src, size_t srcstep, cv::Size srcroi,
01021                              uchar* dst, size_t dststep, cv::Size dstroi,
01022                              int top, int left, int cn, const uchar* value )
01023 {
01024     int i, j;
01025     cv::AutoBuffer<uchar>  _constBuf(dstroi.width*cn);
01026     uchar* constBuf = _constBuf;
01027     int right = dstroi.width - srcroi.width - left;
01028     int bottom = dstroi.height - srcroi.height - top;
01029 
01030     for( i = 0; i < dstroi.width; i++ )
01031     {
01032         for( j = 0; j < cn; j++ )
01033             constBuf[i*cn + j] = value[j];
01034     }
01035 
01036     srcroi.width *= cn;
01037     dstroi.width *= cn;
01038     left *= cn;
01039     right *= cn;
01040 
01041     uchar* dstInner = dst + dststep*top + left;
01042 
01043     for( i = 0; i < srcroi.height; i++, dstInner += dststep, src += srcstep )
01044     {
01045         if( dstInner != src )
01046             memcpy( dstInner, src, srcroi.width );
01047         memcpy( dstInner - left, constBuf, left );
01048         memcpy( dstInner + srcroi.width, constBuf, right );
01049     }
01050 
01051     dst += dststep*top;
01052 
01053     for( i = 0; i < top; i++ )
01054         memcpy(dst + (i - top)*dststep, constBuf, dstroi.width);
01055 
01056     for( i = 0; i < bottom; i++ )
01057         memcpy(dst + (i + srcroi.height)*dststep, constBuf, dstroi.width);
01058 }
01059 
01060 }
01061 
01062 #ifdef HAVE_OPENCL
01063 
01064 namespace cv {
01065 
01066 static bool ocl_copyMakeBorder( InputArray _src, OutputArray _dst, int top, int bottom,
01067                                 int left, int right, int borderType, const Scalar& value )
01068 {
01069     int type = _src.type(), cn = CV_MAT_CN(type), depth = CV_MAT_DEPTH(type),
01070             rowsPerWI = ocl::Device::getDefault().isIntel() ? 4 : 1;
01071     bool isolated = (borderType & BORDER_ISOLATED) != 0;
01072     borderType &= ~cv::BORDER_ISOLATED;
01073 
01074     if ( !(borderType == BORDER_CONSTANT || borderType == BORDER_REPLICATE || borderType == BORDER_REFLECT ||
01075            borderType == BORDER_WRAP || borderType == BORDER_REFLECT_101) ||
01076          cn > 4)
01077         return false;
01078 
01079     const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", "BORDER_WRAP", "BORDER_REFLECT_101" };
01080     int scalarcn = cn == 3 ? 4 : cn;
01081     int sctype = CV_MAKETYPE(depth, scalarcn);
01082     String buildOptions = format("-D T=%s -D %s -D T1=%s -D cn=%d -D ST=%s -D rowsPerWI=%d",
01083                                  ocl::memopTypeToStr(type), borderMap[borderType],
01084                                  ocl::memopTypeToStr(depth), cn,
01085                                  ocl::memopTypeToStr(sctype), rowsPerWI);
01086 
01087     ocl::Kernel k("copyMakeBorder", ocl::core::copymakeborder_oclsrc, buildOptions);
01088     if (k.empty())
01089         return false;
01090 
01091     UMat src = _src.getUMat();
01092     if( src.isSubmatrix() && !isolated )
01093     {
01094         Size wholeSize;
01095         Point ofs;
01096         src.locateROI(wholeSize, ofs);
01097         int dtop = std::min(ofs.y, top);
01098         int dbottom = std::min(wholeSize.height - src.rows - ofs.y, bottom);
01099         int dleft = std::min(ofs.x, left);
01100         int dright = std::min(wholeSize.width - src.cols - ofs.x, right);
01101         src.adjustROI(dtop, dbottom, dleft, dright);
01102         top -= dtop;
01103         left -= dleft;
01104         bottom -= dbottom;
01105         right -= dright;
01106     }
01107 
01108     _dst.create(src.rows + top + bottom, src.cols + left + right, type);
01109     UMat dst = _dst.getUMat();
01110 
01111     if (top == 0 && left == 0 && bottom == 0 && right == 0)
01112     {
01113         if(src.u != dst.u || src.step != dst.step)
01114             src.copyTo(dst);
01115         return true;
01116     }
01117 
01118     k.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::WriteOnly(dst),
01119            top, left, ocl::KernelArg::Constant(Mat(1, 1, sctype, value)));
01120 
01121     size_t globalsize[2] = { (size_t)dst.cols, ((size_t)dst.rows + rowsPerWI - 1) / rowsPerWI };
01122     return k.run(2, globalsize, NULL, false);
01123 }
01124 
01125 }
01126 
01127 #endif
01128 
01129 void cv::copyMakeBorder( InputArray _src, OutputArray _dst, int top, int bottom,
01130                          int left, int right, int borderType, const Scalar & value )
01131 {
01132     CV_Assert( top >= 0 && bottom >= 0 && left >= 0 && right >= 0 );
01133 
01134 #ifdef HAVE_OPENCL
01135     CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2,
01136                ocl_copyMakeBorder(_src, _dst, top, bottom, left, right, borderType, value))
01137 #endif
01138 
01139     Mat src = _src.getMat();
01140     int type = src.type();
01141 
01142     if( src.isSubmatrix() && (borderType & BORDER_ISOLATED) == 0 )
01143     {
01144         Size wholeSize;
01145         Point ofs;
01146         src.locateROI(wholeSize, ofs);
01147         int dtop = std::min(ofs.y, top);
01148         int dbottom = std::min(wholeSize.height - src.rows - ofs.y, bottom);
01149         int dleft = std::min(ofs.x, left);
01150         int dright = std::min(wholeSize.width - src.cols - ofs.x, right);
01151         src.adjustROI(dtop, dbottom, dleft, dright);
01152         top -= dtop;
01153         left -= dleft;
01154         bottom -= dbottom;
01155         right -= dright;
01156     }
01157 
01158     _dst.create( src.rows + top + bottom, src.cols + left + right, type );
01159     Mat dst = _dst.getMat();
01160 
01161     if(top == 0 && left == 0 && bottom == 0 && right == 0)
01162     {
01163         if(src.data != dst.data || src.step != dst.step)
01164             src.copyTo(dst);
01165         return;
01166     }
01167 
01168     borderType &= ~BORDER_ISOLATED;
01169 
01170 #if defined HAVE_IPP && IPP_DISABLE_BLOCK
01171     CV_IPP_CHECK()
01172     {
01173         typedef IppStatus (CV_STDCALL * ippiCopyMakeBorder)(const void * pSrc, int srcStep, IppiSize srcRoiSize, void * pDst,
01174                                                             int dstStep, IppiSize dstRoiSize, int topBorderHeight, int leftBorderWidth);
01175         typedef IppStatus (CV_STDCALL * ippiCopyMakeBorderI)(const void * pSrc, int srcDstStep, IppiSize srcRoiSize, IppiSize dstRoiSize,
01176                                                              int topBorderHeight, int leftborderwidth);
01177         typedef IppStatus (CV_STDCALL * ippiCopyConstBorder)(const void * pSrc, int srcStep, IppiSize srcRoiSize, void * pDst, int dstStep,
01178                                                              IppiSize dstRoiSize, int topBorderHeight, int leftBorderWidth, void * value);
01179 
01180         IppiSize srcRoiSize = { src.cols, src.rows }, dstRoiSize = { dst.cols, dst.rows };
01181         ippiCopyMakeBorder ippFunc = 0;
01182         ippiCopyMakeBorderI ippFuncI = 0;
01183         ippiCopyConstBorder ippFuncConst = 0;
01184         bool inplace = dst.datastart == src.datastart;
01185 
01186         if (borderType == BORDER_CONSTANT)
01187         {
01188              ippFuncConst =
01189     //             type == CV_8UC1 ? (ippiCopyConstBorder)ippiCopyConstBorder_8u_C1R : bug in IPP 8.1
01190                  type == CV_16UC1 ? (ippiCopyConstBorder)ippiCopyConstBorder_16u_C1R :
01191     //             type == CV_16SC1 ? (ippiCopyConstBorder)ippiCopyConstBorder_16s_C1R : bug in IPP 8.1
01192     //             type == CV_32SC1 ? (ippiCopyConstBorder)ippiCopyConstBorder_32s_C1R : bug in IPP 8.1
01193     //             type == CV_32FC1 ? (ippiCopyConstBorder)ippiCopyConstBorder_32f_C1R : bug in IPP 8.1
01194                  type == CV_8UC3 ? (ippiCopyConstBorder)ippiCopyConstBorder_8u_C3R :
01195                  type == CV_16UC3 ? (ippiCopyConstBorder)ippiCopyConstBorder_16u_C3R :
01196                  type == CV_16SC3 ? (ippiCopyConstBorder)ippiCopyConstBorder_16s_C3R :
01197                  type == CV_32SC3 ? (ippiCopyConstBorder)ippiCopyConstBorder_32s_C3R :
01198                  type == CV_32FC3 ? (ippiCopyConstBorder)ippiCopyConstBorder_32f_C3R :
01199                  type == CV_8UC4 ? (ippiCopyConstBorder)ippiCopyConstBorder_8u_C4R :
01200                  type == CV_16UC4 ? (ippiCopyConstBorder)ippiCopyConstBorder_16u_C4R :
01201                  type == CV_16SC4 ? (ippiCopyConstBorder)ippiCopyConstBorder_16s_C4R :
01202                  type == CV_32SC4 ? (ippiCopyConstBorder)ippiCopyConstBorder_32s_C4R :
01203                  type == CV_32FC4 ? (ippiCopyConstBorder)ippiCopyConstBorder_32f_C4R : 0;
01204         }
01205         else if (borderType == BORDER_WRAP)
01206         {
01207             if (inplace)
01208             {
01209                 CV_SUPPRESS_DEPRECATED_START
01210                 ippFuncI =
01211                     type == CV_32SC1 ? (ippiCopyMakeBorderI)ippiCopyWrapBorder_32s_C1IR :
01212                     type == CV_32FC1 ? (ippiCopyMakeBorderI)ippiCopyWrapBorder_32s_C1IR : 0;
01213                 CV_SUPPRESS_DEPRECATED_END
01214             }
01215             else
01216             {
01217                 ippFunc =
01218                     type == CV_32SC1 ? (ippiCopyMakeBorder)ippiCopyWrapBorder_32s_C1R :
01219                     type == CV_32FC1 ? (ippiCopyMakeBorder)ippiCopyWrapBorder_32s_C1R : 0;
01220             }
01221         }
01222         else if (borderType == BORDER_REPLICATE)
01223         {
01224             if (inplace)
01225             {
01226                 CV_SUPPRESS_DEPRECATED_START
01227                 ippFuncI =
01228                     type == CV_8UC1 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_8u_C1IR :
01229                     type == CV_16UC1 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_16u_C1IR :
01230                     type == CV_16SC1 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_16s_C1IR :
01231                     type == CV_32SC1 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_32s_C1IR :
01232                     type == CV_32FC1 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_32f_C1IR :
01233                     type == CV_8UC3 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_8u_C3IR :
01234                     type == CV_16UC3 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_16u_C3IR :
01235                     type == CV_16SC3 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_16s_C3IR :
01236                     type == CV_32SC3 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_32s_C3IR :
01237                     type == CV_32FC3 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_32f_C3IR :
01238                     type == CV_8UC4 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_8u_C4IR :
01239                     type == CV_16UC4 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_16u_C4IR :
01240                     type == CV_16SC4 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_16s_C4IR :
01241                     type == CV_32SC4 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_32s_C4IR :
01242                     type == CV_32FC4 ? (ippiCopyMakeBorderI)ippiCopyReplicateBorder_32f_C4IR : 0;
01243                 CV_SUPPRESS_DEPRECATED_END
01244             }
01245             else
01246             {
01247                  ippFunc =
01248                      type == CV_8UC1 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_8u_C1R :
01249                      type == CV_16UC1 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_16u_C1R :
01250                      type == CV_16SC1 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_16s_C1R :
01251                      type == CV_32SC1 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_32s_C1R :
01252                      type == CV_32FC1 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_32f_C1R :
01253                      type == CV_8UC3 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_8u_C3R :
01254                      type == CV_16UC3 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_16u_C3R :
01255                      type == CV_16SC3 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_16s_C3R :
01256                      type == CV_32SC3 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_32s_C3R :
01257                      type == CV_32FC3 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_32f_C3R :
01258                      type == CV_8UC4 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_8u_C4R :
01259                      type == CV_16UC4 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_16u_C4R :
01260                      type == CV_16SC4 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_16s_C4R :
01261                      type == CV_32SC4 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_32s_C4R :
01262                      type == CV_32FC4 ? (ippiCopyMakeBorder)ippiCopyReplicateBorder_32f_C4R : 0;
01263             }
01264         }
01265 
01266         if (ippFunc || ippFuncI || ippFuncConst)
01267         {
01268             uchar scbuf[32];
01269             scalarToRawData(value, scbuf, type);
01270 
01271             if ( (ippFunc && ippFunc(src.data, (int)src.step, srcRoiSize, dst.data, (int)dst.step, dstRoiSize, top, left) >= 0) ||
01272                  (ippFuncI && ippFuncI(src.data, (int)src.step, srcRoiSize, dstRoiSize, top, left) >= 0) ||
01273                  (ippFuncConst && ippFuncConst(src.data, (int)src.step, srcRoiSize, dst.data, (int)dst.step,
01274                                                dstRoiSize, top, left, scbuf) >= 0))
01275             {
01276                 CV_IMPL_ADD(CV_IMPL_IPP);
01277                 return;
01278             }
01279 
01280             setIppErrorStatus();
01281         }
01282     }
01283 #endif
01284 
01285     if( borderType != BORDER_CONSTANT )
01286         copyMakeBorder_8u( src.ptr(), src.step, src.size(),
01287                            dst.ptr(), dst.step, dst.size(),
01288                            top, left, (int)src.elemSize(), borderType );
01289     else
01290     {
01291         int cn = src.channels(), cn1 = cn;
01292         AutoBuffer<double> buf(cn);
01293         if( cn > 4 )
01294         {
01295             CV_Assert( value[0] == value[1] && value[0] == value[2] && value[0] == value[3] );
01296             cn1 = 1;
01297         }
01298         scalarToRawData(value, buf, CV_MAKETYPE(src.depth(), cn1), cn);
01299         copyMakeConstBorder_8u( src.ptr(), src.step, src.size(),
01300                                 dst.ptr(), dst.step, dst.size(),
01301                                 top, left, (int)src.elemSize(), (uchar*)(double*)buf );
01302     }
01303 }
01304 
01305 /* dst = src */
01306 CV_IMPL void
01307 cvCopy( const void* srcarr, void* dstarr, const void* maskarr )
01308 {
01309     if( CV_IS_SPARSE_MAT(srcarr) && CV_IS_SPARSE_MAT(dstarr))
01310     {
01311         CV_Assert( maskarr == 0 );
01312         CvSparseMat* src1 = (CvSparseMat*)srcarr;
01313         CvSparseMat* dst1 = (CvSparseMat*)dstarr;
01314         CvSparseMatIterator iterator;
01315         CvSparseNode* node;
01316 
01317         dst1->dims = src1->dims;
01318         memcpy( dst1->size, src1->size, src1->dims*sizeof(src1->size[0]));
01319         dst1->valoffset = src1->valoffset;
01320         dst1->idxoffset = src1->idxoffset;
01321         cvClearSet( dst1->heap );
01322 
01323         if( src1->heap->active_count >= dst1->hashsize*CV_SPARSE_HASH_RATIO )
01324         {
01325             cvFree( &dst1->hashtable );
01326             dst1->hashsize = src1->hashsize;
01327             dst1->hashtable =
01328                 (void**)cvAlloc( dst1->hashsize*sizeof(dst1->hashtable[0]));
01329         }
01330 
01331         memset( dst1->hashtable, 0, dst1->hashsize*sizeof(dst1->hashtable[0]));
01332 
01333         for( node = cvInitSparseMatIterator( src1, &iterator );
01334              node != 0; node = cvGetNextSparseNode( &iterator ))
01335         {
01336             CvSparseNode* node_copy = (CvSparseNode*)cvSetNew( dst1->heap );
01337             int tabidx = node->hashval & (dst1->hashsize - 1);
01338             memcpy( node_copy, node, dst1->heap->elem_size );
01339             node_copy->next = (CvSparseNode*)dst1->hashtable[tabidx];
01340             dst1->hashtable[tabidx] = node_copy;
01341         }
01342         return;
01343     }
01344     cv::Mat src = cv::cvarrToMat(srcarr, false, true, 1), dst = cv::cvarrToMat(dstarr, false, true, 1);
01345     CV_Assert( src.depth() == dst.depth() && src.size == dst.size );
01346 
01347     int coi1 = 0, coi2 = 0;
01348     if( CV_IS_IMAGE(srcarr) )
01349         coi1 = cvGetImageCOI((const IplImage*)srcarr);
01350     if( CV_IS_IMAGE(dstarr) )
01351         coi2 = cvGetImageCOI((const IplImage*)dstarr);
01352 
01353     if( coi1 || coi2 )
01354     {
01355         CV_Assert( (coi1 != 0 || src.channels() == 1) &&
01356             (coi2 != 0 || dst.channels() == 1) );
01357 
01358         int pair[] = { std::max(coi1-1, 0), std::max(coi2-1, 0) };
01359         cv::mixChannels( &src, 1, &dst, 1, pair, 1 );
01360         return;
01361     }
01362     else
01363         CV_Assert( src.channels() == dst.channels() );
01364 
01365     if( !maskarr )
01366         src.copyTo(dst);
01367     else
01368         src.copyTo(dst, cv::cvarrToMat(maskarr));
01369 }
01370 
01371 CV_IMPL void
01372 cvSet( void* arr, CvScalar  value, const void* maskarr )
01373 {
01374     cv::Mat m = cv::cvarrToMat(arr);
01375     if( !maskarr )
01376         m = value;
01377     else
01378         m.setTo(cv::Scalar (value), cv::cvarrToMat(maskarr));
01379 }
01380 
01381 CV_IMPL void
01382 cvSetZero( CvArr* arr )
01383 {
01384     if( CV_IS_SPARSE_MAT(arr) )
01385     {
01386         CvSparseMat* mat1 = (CvSparseMat*)arr;
01387         cvClearSet( mat1->heap );
01388         if( mat1->hashtable )
01389             memset( mat1->hashtable, 0, mat1->hashsize*sizeof(mat1->hashtable[0]));
01390         return;
01391     }
01392     cv::Mat m = cv::cvarrToMat(arr);
01393     m = cv::Scalar (0);
01394 }
01395 
01396 CV_IMPL void
01397 cvFlip( const CvArr* srcarr, CvArr* dstarr, int flip_mode )
01398 {
01399     cv::Mat src = cv::cvarrToMat(srcarr);
01400     cv::Mat dst;
01401 
01402     if (!dstarr)
01403       dst = src;
01404     else
01405       dst = cv::cvarrToMat(dstarr);
01406 
01407     CV_Assert( src.type() == dst.type() && src.size() == dst.size() );
01408     cv::flip( src, dst, flip_mode );
01409 }
01410 
01411 CV_IMPL void
01412 cvRepeat( const CvArr* srcarr, CvArr* dstarr )
01413 {
01414     cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
01415     CV_Assert( src.type() == dst.type() &&
01416         dst.rows % src.rows == 0 && dst.cols % src.cols == 0 );
01417     cv::repeat(src, dst.rows/src.rows, dst.cols/src.cols, dst);
01418 }
01419 
01420 /* End of file. */
01421