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.
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14 // Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
15 // Third party copyrights are property of their respective owners.
17 // Redistribution and use in source and binary forms, with or without modification,
18 // are permitted provided that the following conditions are met:
20 // * Redistribution's of source code must retain the above copyright notice,
21 // this list of conditions and the following disclaimer.
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.
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.
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.
43 /* ////////////////////////////////////////////////////////////////////
45 // Mat basic operations: Copy, Set
49 #include "precomp.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 for( ; size.height--; mask += mstep, _src += sstep, _dst += dstep )
86 const uchar* src = (const uchar*)_src;
87 uchar* dst = (uchar*)_dst;
92 __m128i zero = _mm_setzero_si128 ();
94 for( ; x <= size.width - 16; x += 16 )
96 const __m128i rSrc = _mm_lddqu_si128((const __m128i*)(src+x));
97 __m128i _mask = _mm_lddqu_si128((const __m128i*)(mask+x));
98 __m128i rDst = _mm_lddqu_si128((__m128i*)(dst+x));
99 __m128i _negMask = _mm_cmpeq_epi8(_mask, zero);
100 rDst = _mm_blendv_epi8(rSrc, rDst, _negMask);
101 _mm_storeu_si128((__m128i*)(dst + x), rDst);
105 for( ; x < size.width; x++ )
112 copyMask_<ushort>(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size)
114 for( ; size.height--; mask += mstep, _src += sstep, _dst += dstep )
116 const ushort* src = (const ushort*)_src;
117 ushort* dst = (ushort*)_dst;
122 __m128i zero = _mm_setzero_si128 ();
123 for( ; x <= size.width - 8; x += 8 )
125 const __m128i rSrc =_mm_lddqu_si128((const __m128i*)(src+x));
126 __m128i _mask = _mm_loadl_epi64((const __m128i*)(mask+x));
127 _mask = _mm_unpacklo_epi8(_mask, _mask);
128 __m128i rDst = _mm_lddqu_si128((const __m128i*)(dst+x));
129 __m128i _negMask = _mm_cmpeq_epi8(_mask, zero);
130 rDst = _mm_blendv_epi8(rSrc, rDst, _negMask);
131 _mm_storeu_si128((__m128i*)(dst + x), rDst);
135 for( ; x < size.width; x++ )
142 copyMaskGeneric(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size, void* _esz)
144 size_t k, esz = *(size_t*)_esz;
145 for( ; size.height--; mask += mstep, _src += sstep, _dst += dstep )
147 const uchar* src = _src;
150 for( ; x < size.width; x++, src += esz, dst += esz )
154 for( k = 0; k < esz; k++ )
161 #define DEF_COPY_MASK(suffix, type) \
162 static void copyMask##suffix(const uchar* src, size_t sstep, const uchar* mask, size_t mstep, \
163 uchar* dst, size_t dstep, Size size, void*) \
165 copyMask_<type>(src, sstep, mask, mstep, dst, dstep, size); \
169 DEF_COPY_MASK(8u, uchar)
170 DEF_COPY_MASK(16u, ushort)
171 DEF_COPY_MASK(8uC3, Vec3b)
172 DEF_COPY_MASK(32s, int)
173 DEF_COPY_MASK(16uC3, Vec3s)
174 DEF_COPY_MASK(32sC2, Vec2i)
175 DEF_COPY_MASK(32sC3, Vec3i)
176 DEF_COPY_MASK(32sC4, Vec4i)
177 DEF_COPY_MASK(32sC6, Vec6i)
178 DEF_COPY_MASK(32sC8, Vec8i)
180 BinaryFunc copyMaskTab[] =
201 BinaryFunc getCopyMaskFunc(size_t esz)
203 return esz <= 32 && copyMaskTab[esz] ? copyMaskTab[esz] : copyMaskGeneric;
207 void Mat::copyTo( OutputArray _dst ) const
209 int dtype = _dst.type();
210 if( _dst.fixedType() && dtype != type() )
212 CV_Assert( channels() == CV_MAT_CN(dtype) );
213 convertTo( _dst, dtype );
225 _dst.create( rows, cols, type() );
226 Mat dst = _dst.getMat();
227 if( data == dst.data )
230 if( rows > 0 && cols > 0 )
232 const uchar* sptr = data;
233 uchar* dptr = dst.data;
235 Size sz = getContinuousSize(*this, dst);
236 size_t len = sz.width*elemSize();
238 for( ; sz.height--; sptr += step, dptr += dst.step )
239 memcpy( dptr, sptr, len );
244 _dst.create( dims, size, type() );
245 Mat dst = _dst.getMat();
246 if( data == dst.data )
251 const Mat* arrays[] = { this, &dst };
253 NAryMatIterator it(arrays, ptrs, 2);
254 size_t sz = it.size*elemSize();
256 for( size_t i = 0; i < it.nplanes; i++, ++it )
257 memcpy(ptrs[1], ptrs[0], sz);
261 void Mat::copyTo( OutputArray _dst, InputArray _mask ) const
263 Mat mask = _mask.getMat();
270 int cn = channels(), mcn = mask.channels();
271 CV_Assert( mask.depth() == CV_8U && (mcn == 1 || mcn == cn) );
272 bool colorMask = mcn > 1;
274 size_t esz = colorMask ? elemSize1() : elemSize();
275 BinaryFunc copymask = getCopyMaskFunc(esz);
277 uchar* data0 = _dst.getMat().data;
278 _dst.create( dims, size, type() );
279 Mat dst = _dst.getMat();
281 if( dst.data != data0 ) // do not leave dst uninitialized
286 CV_Assert( size() == mask.size() );
287 Size sz = getContinuousSize(*this, dst, mask, mcn);
288 copymask(data, step, mask.data, mask.step, dst.data, dst.step, sz, &esz);
292 const Mat* arrays[] = { this, &dst, &mask, 0 };
294 NAryMatIterator it(arrays, ptrs);
295 Size sz((int)(it.size*mcn), 1);
297 for( size_t i = 0; i < it.nplanes; i++, ++it )
298 copymask(ptrs[0], 0, ptrs[2], 0, ptrs[1], 0, sz, &esz);
301 Mat& Mat::operator = (const Scalar& s)
303 const Mat* arrays[] = { this };
305 NAryMatIterator it(arrays, &dptr, 1);
306 size_t elsize = it.size*elemSize();
307 const int64* is = (const int64*)&s.val[0];
309 if( is[0] == 0 && is[1] == 0 && is[2] == 0 && is[3] == 0 )
311 for( size_t i = 0; i < it.nplanes; i++, ++it )
312 memset( dptr, 0, elsize );
319 scalarToRawData(s, scalar, type(), 12);
320 size_t blockSize = 12*elemSize1();
322 for( size_t j = 0; j < elsize; j += blockSize )
324 size_t sz = MIN(blockSize, elsize - j);
325 memcpy( dptr + j, scalar, sz );
329 for( size_t i = 1; i < it.nplanes; i++ )
332 memcpy( dptr, data, elsize );
339 Mat& Mat::setTo(InputArray _value, InputArray _mask)
344 Mat value = _value.getMat(), mask = _mask.getMat();
346 CV_Assert( checkScalar(value, type(), _value.kind(), _InputArray::MAT ));
347 CV_Assert( mask.empty() || mask.type() == CV_8U );
349 size_t esz = elemSize();
350 BinaryFunc copymask = getCopyMaskFunc(esz);
352 const Mat* arrays[] = { this, !mask.empty() ? &mask : 0, 0 };
353 uchar* ptrs[2]={0,0};
354 NAryMatIterator it(arrays, ptrs);
355 int totalsz = (int)it.size, blockSize0 = std::min(totalsz, (int)((BLOCK_SIZE + esz-1)/esz));
356 AutoBuffer<uchar> _scbuf(blockSize0*esz + 32);
357 uchar* scbuf = alignPtr((uchar*)_scbuf, (int)sizeof(double));
358 convertAndUnrollScalar( value, type(), scbuf, blockSize0 );
360 for( size_t i = 0; i < it.nplanes; i++, ++it )
362 for( int j = 0; j < totalsz; j += blockSize0 )
364 Size sz(std::min(blockSize0, totalsz - j), 1);
365 size_t blockSize = sz.width*esz;
368 copymask(scbuf, 0, ptrs[1], 0, ptrs[0], 0, sz, &esz);
372 memcpy(ptrs[0], scbuf, blockSize);
373 ptrs[0] += blockSize;
381 flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, size_t esz )
383 int i, j, limit = (int)(((size.width + 1)/2)*esz);
384 AutoBuffer<int> _tab(size.width*esz);
387 for( i = 0; i < size.width; i++ )
388 for( size_t k = 0; k < esz; k++ )
389 tab[i*esz + k] = (int)((size.width - i - 1)*esz + k);
391 for( ; size.height--; src += sstep, dst += dstep )
393 for( i = 0; i < limit; i++ )
396 uchar t0 = src[i], t1 = src[j];
397 dst[i] = t1; dst[j] = t0;
403 flipVert( const uchar* src0, size_t sstep, uchar* dst0, size_t dstep, Size size, size_t esz )
405 const uchar* src1 = src0 + (size.height - 1)*sstep;
406 uchar* dst1 = dst0 + (size.height - 1)*dstep;
407 size.width *= (int)esz;
409 for( int y = 0; y < (size.height + 1)/2; y++, src0 += sstep, src1 -= sstep,
410 dst0 += dstep, dst1 -= dstep )
413 if( ((size_t)src0|(size_t)dst0|(size_t)src1|(size_t)dst1) % sizeof(int) == 0 )
415 for( ; i <= size.width - 16; i += 16 )
417 int t0 = ((int*)(src0 + i))[0];
418 int t1 = ((int*)(src1 + i))[0];
420 ((int*)(dst0 + i))[0] = t1;
421 ((int*)(dst1 + i))[0] = t0;
423 t0 = ((int*)(src0 + i))[1];
424 t1 = ((int*)(src1 + i))[1];
426 ((int*)(dst0 + i))[1] = t1;
427 ((int*)(dst1 + i))[1] = t0;
429 t0 = ((int*)(src0 + i))[2];
430 t1 = ((int*)(src1 + i))[2];
432 ((int*)(dst0 + i))[2] = t1;
433 ((int*)(dst1 + i))[2] = t0;
435 t0 = ((int*)(src0 + i))[3];
436 t1 = ((int*)(src1 + i))[3];
438 ((int*)(dst0 + i))[3] = t1;
439 ((int*)(dst1 + i))[3] = t0;
442 for( ; i <= size.width - 4; i += 4 )
444 int t0 = ((int*)(src0 + i))[0];
445 int t1 = ((int*)(src1 + i))[0];
447 ((int*)(dst0 + i))[0] = t1;
448 ((int*)(dst1 + i))[0] = t0;
452 for( ; i < size.width; i++ )
463 void flip( InputArray _src, OutputArray _dst, int flip_mode )
465 Mat src = _src.getMat();
467 CV_Assert( src.dims <= 2 );
468 _dst.create( src.size(), src.type() );
469 Mat dst = _dst.getMat();
470 size_t esz = src.elemSize();
473 flipVert( src.data, src.step, dst.data, dst.step, src.size(), esz );
475 flipHoriz( src.data, src.step, dst.data, dst.step, src.size(), esz );
478 flipHoriz( dst.data, dst.step, dst.data, dst.step, dst.size(), esz );
482 void repeat(InputArray _src, int ny, int nx, OutputArray _dst)
484 Mat src = _src.getMat();
485 CV_Assert( src.dims <= 2 );
486 CV_Assert( ny > 0 && nx > 0 );
488 _dst.create(src.rows*ny, src.cols*nx, src.type());
489 Mat dst = _dst.getMat();
490 Size ssize = src.size(), dsize = dst.size();
491 int esz = (int)src.elemSize();
493 ssize.width *= esz; dsize.width *= esz;
495 for( y = 0; y < ssize.height; y++ )
497 for( x = 0; x < dsize.width; x += ssize.width )
498 memcpy( dst.data + y*dst.step + x, src.data + y*src.step, ssize.width );
501 for( ; y < dsize.height; y++ )
502 memcpy( dst.data + y*dst.step, dst.data + (y - ssize.height)*dst.step, dsize.width );
505 Mat repeat(const Mat& src, int ny, int nx)
507 if( nx == 1 && ny == 1 )
510 repeat(src, ny, nx, dst);
518 cvCopy( const void* srcarr, void* dstarr, const void* maskarr )
520 if( CV_IS_SPARSE_MAT(srcarr) && CV_IS_SPARSE_MAT(dstarr))
522 CV_Assert( maskarr == 0 );
523 CvSparseMat* src1 = (CvSparseMat*)srcarr;
524 CvSparseMat* dst1 = (CvSparseMat*)dstarr;
525 CvSparseMatIterator iterator;
528 dst1->dims = src1->dims;
529 memcpy( dst1->size, src1->size, src1->dims*sizeof(src1->size[0]));
530 dst1->valoffset = src1->valoffset;
531 dst1->idxoffset = src1->idxoffset;
532 cvClearSet( dst1->heap );
534 if( src1->heap->active_count >= dst1->hashsize*CV_SPARSE_HASH_RATIO )
536 cvFree( &dst1->hashtable );
537 dst1->hashsize = src1->hashsize;
539 (void**)cvAlloc( dst1->hashsize*sizeof(dst1->hashtable[0]));
542 memset( dst1->hashtable, 0, dst1->hashsize*sizeof(dst1->hashtable[0]));
544 for( node = cvInitSparseMatIterator( src1, &iterator );
545 node != 0; node = cvGetNextSparseNode( &iterator ))
547 CvSparseNode* node_copy = (CvSparseNode*)cvSetNew( dst1->heap );
548 int tabidx = node->hashval & (dst1->hashsize - 1);
549 memcpy( node_copy, node, dst1->heap->elem_size );
550 node_copy->next = (CvSparseNode*)dst1->hashtable[tabidx];
551 dst1->hashtable[tabidx] = node_copy;
555 cv::Mat src = cv::cvarrToMat(srcarr, false, true, 1), dst = cv::cvarrToMat(dstarr, false, true, 1);
556 CV_Assert( src.depth() == dst.depth() && src.size == dst.size );
558 int coi1 = 0, coi2 = 0;
559 if( CV_IS_IMAGE(srcarr) )
560 coi1 = cvGetImageCOI((const IplImage*)srcarr);
561 if( CV_IS_IMAGE(dstarr) )
562 coi2 = cvGetImageCOI((const IplImage*)dstarr);
566 CV_Assert( (coi1 != 0 || src.channels() == 1) &&
567 (coi2 != 0 || dst.channels() == 1) );
569 int pair[] = { std::max(coi1-1, 0), std::max(coi2-1, 0) };
570 cv::mixChannels( &src, 1, &dst, 1, pair, 1 );
574 CV_Assert( src.channels() == dst.channels() );
579 src.copyTo(dst, cv::cvarrToMat(maskarr));
583 cvSet( void* arr, CvScalar value, const void* maskarr )
585 cv::Mat m = cv::cvarrToMat(arr);
589 m.setTo(cv::Scalar(value), cv::cvarrToMat(maskarr));
593 cvSetZero( CvArr* arr )
595 if( CV_IS_SPARSE_MAT(arr) )
597 CvSparseMat* mat1 = (CvSparseMat*)arr;
598 cvClearSet( mat1->heap );
599 if( mat1->hashtable )
600 memset( mat1->hashtable, 0, mat1->hashsize*sizeof(mat1->hashtable[0]));
603 cv::Mat m = cv::cvarrToMat(arr);
608 cvFlip( const CvArr* srcarr, CvArr* dstarr, int flip_mode )
610 cv::Mat src = cv::cvarrToMat(srcarr);
616 dst = cv::cvarrToMat(dstarr);
618 CV_Assert( src.type() == dst.type() && src.size() == dst.size() );
619 cv::flip( src, dst, flip_mode );
623 cvRepeat( const CvArr* srcarr, CvArr* dstarr )
625 cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
626 CV_Assert( src.type() == dst.type() &&
627 dst.rows % src.rows == 0 && dst.cols % src.cols == 0 );
628 cv::repeat(src, dst.rows/src.rows, dst.cols/src.cols, dst);