Update to 2.0.0 tree from current Fremantle build
[opencv] / src / cxcore / cxcopy.cpp
diff --git a/src/cxcore/cxcopy.cpp b/src/cxcore/cxcopy.cpp
new file mode 100644 (file)
index 0000000..739e6b4
--- /dev/null
@@ -0,0 +1,541 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+//  By downloading, copying, installing or using the software you agree to this license.
+//  If you do not agree to this license, do not download, install,
+//  copy or use the software.
+//
+//
+//                           License Agreement
+//                For Open Source Computer Vision Library
+//
+// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
+// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+//   * Redistribution's of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//
+//   * Redistribution's in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//
+//   * The name of the copyright holders may not be used to endorse or promote products
+//     derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+/* ////////////////////////////////////////////////////////////////////
+//
+//  Mat basic operations: Copy, Set
+//
+// */
+
+#include "_cxcore.h"
+
+namespace cv
+{
+
+template<typename T> static void
+copyMask_(const Mat& srcmat, Mat& dstmat, const Mat& maskmat)
+{
+    const uchar* mask = maskmat.data;
+    size_t sstep = srcmat.step;
+    size_t dstep = dstmat.step;
+    size_t mstep = maskmat.step;
+    Size size = getContinuousSize(srcmat, dstmat, maskmat);
+
+    for( int y = 0; y < size.height; y++, mask += mstep )
+    {
+        const T* src = (const T*)(srcmat.data + sstep*y);
+        T* dst = (T*)(dstmat.data + dstep*y);
+        int x = 0;
+        for( ; x <= size.width - 4; x += 4 )
+        {
+            if( mask[x] )
+                dst[x] = src[x];
+            if( mask[x+1] )
+                dst[x+1] = src[x+1];
+            if( mask[x+2] )
+                dst[x+2] = src[x+2];
+            if( mask[x+3] )
+                dst[x+3] = src[x+3];
+        }
+        for( ; x < size.width; x++ )
+            if( mask[x] )
+                dst[x] = src[x];
+    }
+}
+
+template<typename T> static void
+setMask_(const void* _scalar, Mat& dstmat, const Mat& maskmat)
+{
+    T scalar = *(T*)_scalar;
+    const uchar* mask = maskmat.data;
+    size_t dstep = dstmat.step;
+    size_t mstep = maskmat.step;
+    Size size = dstmat.size();
+
+    if( dstmat.isContinuous() && maskmat.isContinuous() )
+    {
+        size.width *= size.height;
+        size.height = 1;
+    }
+
+    for( int y = 0; y < size.height; y++, mask += mstep )
+    {
+        T* dst = (T*)(dstmat.data + dstep*y);
+        int x = 0;
+        for( ; x <= size.width - 4; x += 4 )
+        {
+            if( mask[x] )
+                dst[x] = scalar;
+            if( mask[x+1] )
+                dst[x+1] = scalar;
+            if( mask[x+2] )
+                dst[x+2] = scalar;
+            if( mask[x+3] )
+                dst[x+3] = scalar;
+        }
+        for( ; x < size.width; x++ )
+            if( mask[x] )
+                dst[x] = scalar;
+    }
+}
+
+typedef void (*SetMaskFunc)(const void* scalar, Mat& dst, const Mat& mask);
+
+CopyMaskFunc g_copyMaskFuncTab[] =
+{
+    0,
+    copyMask_<uchar>, // 1
+    copyMask_<ushort>, // 2
+    copyMask_<Vec<uchar,3> >, // 3
+    copyMask_<int>, // 4
+    0,
+    copyMask_<Vec<ushort,3> >, // 6
+    0,
+    copyMask_<int64>, // 8
+    0, 0, 0,
+    copyMask_<Vec<int,3> >, // 12
+    0, 0, 0,
+    copyMask_<Vec<int64,2> >, // 16
+    0, 0, 0, 0, 0, 0, 0,
+    copyMask_<Vec<int64,3> >, // 24
+    0, 0, 0, 0, 0, 0, 0,
+    copyMask_<Vec<int64,4> > // 32
+};
+
+static SetMaskFunc setMaskFuncTab[] =
+{
+    0,
+    setMask_<uchar>, // 1
+    setMask_<ushort>, // 2
+    setMask_<Vec<uchar,3> >, // 3
+    setMask_<int>, // 4
+    0,
+    setMask_<Vec<ushort,3> >, // 6
+    0,
+    setMask_<int64>, // 8
+    0, 0, 0,
+    setMask_<Vec<int,3> >, // 12
+    0, 0, 0,
+    setMask_<Vec<int64,2> >, // 16
+    0, 0, 0, 0, 0, 0, 0,
+    setMask_<Vec<int64,3> >, // 24
+    0, 0, 0, 0, 0, 0, 0,
+    setMask_<Vec<int64,4> > // 32
+};
+
+
+/* dst = src */
+void Mat::copyTo( Mat& dst ) const
+{
+    if( data == dst.data )
+        return;
+
+    dst.create( rows, cols, type() );
+    Size sz = size();
+    const uchar* sptr = data;
+    uchar* dptr = dst.data;
+
+    sz.width *= (int)elemSize();
+    if( isContinuous() && dst.isContinuous() )
+    {
+        sz.width *= sz.height;
+        sz.height = 1;
+    }
+
+    for( ; sz.height--; sptr += step, dptr += dst.step )
+        memcpy( dptr, sptr, sz.width );
+}
+
+void Mat::copyTo( Mat& dst, const Mat& mask ) const
+{
+    if( !mask.data )
+    {
+        copyTo(dst);
+        return;
+    }
+
+    uchar* data0 = dst.data;
+    dst.create( size(), type() );
+    if( dst.data != data0 ) // do not leave dst uninitialized
+        dst = Scalar(0);
+    getCopyMaskFunc((int)elemSize())(*this, dst, mask);
+}
+
+Mat& Mat::operator = (const Scalar& s)
+{
+    Size sz = size();
+    uchar* dst = data;
+
+    sz.width *= (int)elemSize();
+    if( isContinuous() )
+    {
+        sz.width *= sz.height;
+        sz.height = 1;
+    }
+    
+    if( s[0] == 0 && s[1] == 0 && s[2] == 0 && s[3] == 0 )
+    {
+        for( ; sz.height--; dst += step )
+            memset( dst, 0, sz.width );
+    }
+    else
+    {
+        int t = type(), esz1 = (int)elemSize1();
+        double scalar[12];
+        scalarToRawData(s, scalar, t, 12);
+        int copy_len = 12*esz1;
+        uchar* dst_limit = dst + sz.width;
+        
+        if( sz.height-- )
+        {
+            while( dst + copy_len <= dst_limit )
+            {
+                memcpy( dst, scalar, copy_len );
+                dst += copy_len;
+            }
+            memcpy( dst, scalar, dst_limit - dst );
+        }
+
+        if( sz.height )
+        {
+            dst = dst_limit - sz.width + step;
+            for( ; sz.height--; dst += step )
+                memcpy( dst, data, sz.width );
+        }
+    }
+    return *this;
+}
+
+Mat& Mat::setTo(const Scalar& s, const Mat& mask)
+{
+    if( !mask.data )
+        *this = s;
+    else
+    {
+        CV_Assert( channels() <= 4 );
+        SetMaskFunc func = setMaskFuncTab[elemSize()];
+        CV_Assert( func != 0 );
+        double buf[4];
+        scalarToRawData(s, buf, type(), 0);
+        func(buf, *this, mask);
+    }
+    return *this;
+}
+
+
+template<typename T> static void
+flipHoriz_( const Mat& srcmat, Mat& dstmat, bool flipv )
+{
+    uchar* dst0 = dstmat.data;
+    size_t srcstep = srcmat.step;
+    int dststep = (int)dstmat.step;
+    Size size = srcmat.size();
+
+    if( flipv )
+    {
+        dst0 += (size.height - 1)*dststep;
+        dststep = -dststep;
+    }
+
+    for( int y = 0; y < size.height; y++ )
+    {
+        const T* src = (const T*)(srcmat.data + srcstep*y);
+        T* dst = (T*)(dst0 + dststep*y);
+
+        for( int i = 0; i < (size.width + 1)/2; i++ )
+        {
+            T t0 = src[i], t1 = src[size.width - i - 1];
+            dst[i] = t1; dst[size.width - i - 1] = t0;
+        }
+    }
+}
+
+typedef void (*FlipHorizFunc)( const Mat& src, Mat& dst, bool flipv );
+
+static void
+flipVert( const Mat& srcmat, Mat& dstmat )
+{
+    const uchar* src = srcmat.data;
+    uchar* dst = dstmat.data;
+    size_t srcstep = srcmat.step, dststep = dstmat.step;
+    Size size = srcmat.size();
+    const uchar* src1 = src + (size.height - 1)*srcstep;
+    uchar* dst1 = dst + (size.height - 1)*dststep;
+    size.width *= (int)srcmat.elemSize();
+
+    for( int y = 0; y < (size.height + 1)/2; y++, src += srcstep, src1 -= srcstep,
+                                              dst += dststep, dst1 -= dststep )
+    {
+        int i = 0;
+        if( ((size_t)(src)|(size_t)(dst)|(size_t)src1|(size_t)dst1) % sizeof(int) == 0 )
+        {
+            for( ; i <= size.width - 16; i += 16 )
+            {
+                int t0 = ((int*)(src + i))[0];
+                int t1 = ((int*)(src1 + i))[0];
+
+                ((int*)(dst + i))[0] = t1;
+                ((int*)(dst1 + i))[0] = t0;
+
+                t0 = ((int*)(src + i))[1];
+                t1 = ((int*)(src1 + i))[1];
+
+                ((int*)(dst + i))[1] = t1;
+                ((int*)(dst1 + i))[1] = t0;
+
+                t0 = ((int*)(src + i))[2];
+                t1 = ((int*)(src1 + i))[2];
+
+                ((int*)(dst + i))[2] = t1;
+                ((int*)(dst1 + i))[2] = t0;
+
+                t0 = ((int*)(src + i))[3];
+                t1 = ((int*)(src1 + i))[3];
+
+                ((int*)(dst + i))[3] = t1;
+                ((int*)(dst1 + i))[3] = t0;
+            }
+
+            for( ; i <= size.width - 4; i += 4 )
+            {
+                int t0 = ((int*)(src + i))[0];
+                int t1 = ((int*)(src1 + i))[0];
+
+                ((int*)(dst + i))[0] = t1;
+                ((int*)(dst1 + i))[0] = t0;
+            }
+        }
+
+        for( ; i < size.width; i++ )
+        {
+            uchar t0 = src[i];
+            uchar t1 = src1[i];
+
+            dst[i] = t1;
+            dst1[i] = t0;
+        }
+    }
+}
+
+void flip( const Mat& src, Mat& dst, int flip_mode )
+{
+    static FlipHorizFunc tab[] =
+    {
+        0,
+        flipHoriz_<uchar>, // 1
+        flipHoriz_<ushort>, // 2
+        flipHoriz_<Vec<uchar,3> >, // 3
+        flipHoriz_<int>, // 4
+        0,
+        flipHoriz_<Vec<ushort,3> >, // 6
+        0,
+        flipHoriz_<int64>, // 8
+        0, 0, 0,
+        flipHoriz_<Vec<int,3> >, // 12
+        0, 0, 0,
+        flipHoriz_<Vec<int64,2> >, // 16
+        0, 0, 0, 0, 0, 0, 0,
+        flipHoriz_<Vec<int64,3> >, // 24
+        0, 0, 0, 0, 0, 0, 0,
+        flipHoriz_<Vec<int64,4> > // 32
+    };
+    
+    dst.create( src.size(), src.type() );
+
+    if( flip_mode == 0 )
+        flipVert( src, dst );
+    else
+    {
+        int esz = (int)src.elemSize();
+        CV_Assert( esz <= 32 );
+        FlipHorizFunc func = tab[esz];
+        CV_Assert( func != 0 );
+
+        if( flip_mode > 0 )
+            func( src, dst, false );
+        else if( src.data != dst.data )
+            func( src, dst, true );
+        else
+        {
+            func( dst, dst, false );
+            flipVert( dst, dst );
+        }
+    }
+}
+
+
+void repeat(const Mat& src, int ny, int nx, Mat& dst)
+{
+    dst.create(src.rows*ny, src.cols*nx, src.type());
+    Size ssize = src.size(), dsize = dst.size();
+    int esz = (int)src.elemSize();
+    int x, y;
+    ssize.width *= esz; dsize.width *= esz;
+
+    for( y = 0; y < ssize.height; y++ )
+    {
+        for( x = 0; x < dsize.width; x += ssize.width )
+            memcpy( dst.data + y*dst.step + x, src.data + y*src.step, ssize.width );
+    }
+
+    for( ; y < dsize.height; y++ )
+        memcpy( dst.data + y*dst.step, dst.data + (y - ssize.height)*dst.step, dsize.width );
+}
+
+}
+
+/* dst = src */
+CV_IMPL void
+cvCopy( const void* srcarr, void* dstarr, const void* maskarr )
+{
+    if( CV_IS_SPARSE_MAT(srcarr) && CV_IS_SPARSE_MAT(dstarr))
+    {
+        CV_Assert( maskarr == 0 );
+        CvSparseMat* src1 = (CvSparseMat*)srcarr;
+        CvSparseMat* dst1 = (CvSparseMat*)dstarr;
+        CvSparseMatIterator iterator;
+        CvSparseNode* node;
+
+        dst1->dims = src1->dims;
+        memcpy( dst1->size, src1->size, src1->dims*sizeof(src1->size[0]));
+        dst1->valoffset = src1->valoffset;
+        dst1->idxoffset = src1->idxoffset;
+        cvClearSet( dst1->heap );
+
+        if( src1->heap->active_count >= dst1->hashsize*CV_SPARSE_HASH_RATIO )
+        {
+            cvFree( &dst1->hashtable );
+            dst1->hashsize = src1->hashsize;
+            dst1->hashtable =
+                (void**)cvAlloc( dst1->hashsize*sizeof(dst1->hashtable[0]));
+        }
+
+        memset( dst1->hashtable, 0, dst1->hashsize*sizeof(dst1->hashtable[0]));
+
+        for( node = cvInitSparseMatIterator( src1, &iterator );
+             node != 0; node = cvGetNextSparseNode( &iterator ))
+        {
+            CvSparseNode* node_copy = (CvSparseNode*)cvSetNew( dst1->heap );
+            int tabidx = node->hashval & (dst1->hashsize - 1);
+            CV_MEMCPY_AUTO( node_copy, node, dst1->heap->elem_size );
+            node_copy->next = (CvSparseNode*)dst1->hashtable[tabidx];
+            dst1->hashtable[tabidx] = node_copy;
+        }
+        return;
+    }
+    cv::Mat src = cv::cvarrToMat(srcarr, false, true, 1), dst = cv::cvarrToMat(dstarr, false, true, 1);
+    CV_Assert( src.depth() == dst.depth() && src.size() == dst.size() );
+    
+    int coi1 = 0, coi2 = 0;
+    if( CV_IS_IMAGE(srcarr) )
+        coi1 = cvGetImageCOI((const IplImage*)srcarr);
+    if( CV_IS_IMAGE(dstarr) )
+        coi2 = cvGetImageCOI((const IplImage*)dstarr);
+    
+    if( coi1 || coi2 )
+    {
+        CV_Assert( (coi1 != 0 || src.channels() == 1) &&
+            (coi2 != 0 || dst.channels() == 1) );
+        
+        int pair[] = { std::max(coi1-1, 0), std::max(coi2-1, 0) };
+        cv::mixChannels( &src, 1, &dst, 1, pair, 1 );
+        return;
+    }
+    else
+        CV_Assert( src.channels() == dst.channels() );
+    
+    if( !maskarr )
+        src.copyTo(dst);
+    else
+        src.copyTo(dst, cv::cvarrToMat(maskarr));
+}
+
+CV_IMPL void
+cvSet( void* arr, CvScalar value, const void* maskarr )
+{
+    cv::Mat m = cv::cvarrToMat(arr);
+    if( !maskarr )
+        m = value;
+    else
+        m.setTo(value, cv::cvarrToMat(maskarr));
+}
+
+CV_IMPL void
+cvSetZero( CvArr* arr )
+{
+    if( CV_IS_SPARSE_MAT(arr) )
+    {
+        CvSparseMat* mat1 = (CvSparseMat*)arr;
+        cvClearSet( mat1->heap );
+        if( mat1->hashtable )
+            memset( mat1->hashtable, 0, mat1->hashsize*sizeof(mat1->hashtable[0]));
+        return;
+    }
+    cv::Mat m = cv::cvarrToMat(arr);
+    m = cv::Scalar(0);
+}
+
+CV_IMPL void
+cvFlip( const CvArr* srcarr, CvArr* dstarr, int flip_mode )
+{
+    cv::Mat src = cv::cvarrToMat(srcarr);
+    cv::Mat dst;
+    
+    if (!dstarr)
+      dst = src;
+    else
+      dst = cv::cvarrToMat(dstarr);
+    
+    CV_Assert( src.type() == dst.type() && src.size() == dst.size() );
+    cv::flip( src, dst, flip_mode );
+}
+
+CV_IMPL void
+cvRepeat( const CvArr* srcarr, CvArr* dstarr )
+{
+    cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
+    CV_Assert( src.type() == dst.type() &&
+        dst.rows % src.rows == 0 && dst.cols % src.cols == 0 );
+    cv::repeat(src, dst.rows/src.rows, dst.cols/src.cols, dst);
+}
+
+/* End of file. */