updated the new arithmetic tests
authorVadim Pisarevsky <no@email>
Tue, 11 Jan 2011 11:55:58 +0000 (11:55 +0000)
committerVadim Pisarevsky <no@email>
Tue, 11 Jan 2011 11:55:58 +0000 (11:55 +0000)
modules/core/test/test_arithm.cpp
modules/gtest/include/opencv2/gtest/gtestcv.hpp
modules/gtest/src/gtestcv.cpp

index 6ad486f..adcb862 100644 (file)
@@ -1,25 +1,61 @@
 #include "precomp.hpp"
+#include <iostream>
 
 using namespace cv;
+using namespace std;
+
+const int ARITHM_NTESTS = 1000;
+const int ARITHM_RNG_SEED = -1;
+const int ARITHM_MAX_NDIMS = 4;
+const int ARITHM_MAX_SIZE_LOG = 10;
+const int ARITHM_MAX_CHANNELS = 4;
+
+static void getArithmValueRange(int depth, double& minval, double& maxval)
+{
+    minval = depth < CV_32S ? cvtest::getMinVal(depth) : depth == CV_32S ? -1000000 : -1000.;
+    maxval = depth < CV_32S ? cvtest::getMinVal(depth) : depth == CV_32S ? 1000000 : 1000.;
+}
+
+static double getArithmMaxErr(int depth)
+{
+    return depth < CV_32F ? 0 : 4;
+}
 
 TEST(ArithmTest, add)
 {
-    typedef uchar _Tp;
-    
-    Mat A(30,30,DataType<_Tp>::type), B(A.size(), A.type()), C0, C;
-    RNG rng(-1);
-    rng.fill(A, RNG::UNIFORM, Scalar::all(0), Scalar::all(256));
-    rng.fill(B, RNG::UNIFORM, Scalar::all(0), Scalar::all(256));
-    C0.create(A.size(), A.type());
-    int i, j, cols = A.cols*A.channels();
-    for(i = 0; i < A.rows; i++)
+    int testIdx = 0;
+    RNG rng(ARITHM_RNG_SEED);
+    for( testIdx = 0; testIdx < ARITHM_NTESTS; testIdx++ )
     {
-        const _Tp* aptr = A.ptr<_Tp>(i);
-        const _Tp* bptr = B.ptr<_Tp>(i);
-        _Tp* cptr = C0.ptr<_Tp>(i);
-        for(j = 0; j < cols; j++)
-            cptr[j] = saturate_cast<_Tp>(aptr[j] + bptr[j]);
+        double minval, maxval;
+        vector<int> size;
+        cvtest::randomSize(rng, 2, ARITHM_MAX_NDIMS, ARITHM_MAX_SIZE_LOG, size);
+        int type = cvtest::randomType(rng, cvtest::TYPE_MASK_ALL, 1, ARITHM_MAX_CHANNELS);
+        int depth = CV_MAT_DEPTH(type);
+        bool haveMask = rng.uniform(0, 4) == 0;
+        
+        getArithmValueRange(depth, minval, maxval);
+        Mat src1 = cvtest::randomMat(rng, size, type, minval, maxval, true);
+        Mat src2 = cvtest::randomMat(rng, size, type, minval, maxval, true);
+        Mat dst0 = cvtest::randomMat(rng, size, type, minval, maxval, false);
+        Mat dst = cvtest::randomMat(rng, size, type, minval, maxval, true);
+        Mat mask;
+        if( haveMask )
+        {
+            mask = cvtest::randomMat(rng, size, CV_8U, 0, 2, true);
+            cvtest::copy(dst0, dst);
+            cvtest::add(src1, 1, src2, 1, Scalar::all(0), dst0, dst.type());
+            cvtest::copy(dst, dst0, mask, true);
+            add(src1, src2, dst, mask);
+        }
+        else
+        {
+            cvtest::add(src1, 1, src2, 1, Scalar::all(0), dst0, dst.type());
+            add(src1, src2, dst);
+        }
+        
+        double maxErr = getArithmMaxErr(depth);
+        vector<int> pos;
+        ASSERT_TRUE(cvtest::cmpEps(dst0, dst, maxErr, &pos)) << "position: " << Mat(pos);
     }
-    add(A, B, C);
-    EXPECT_EQ(norm(C, C0, NORM_INF), 0);
 }
index 8ec387d..2da7feb 100644 (file)
@@ -27,29 +27,38 @@ enum
     TYPE_MASK_ALL = (TYPE_MASK_64F<<1)-1,
     TYPE_MASK_ALL_BUT_8S = TYPE_MASK_ALL & ~TYPE_MASK_8S
 };
+
+CV_EXPORTS double getMinVal(int depth);
+CV_EXPORTS double getMaxVal(int depth);
     
 CV_EXPORTS Size randomSize(RNG& rng, double maxSizeLog);
 CV_EXPORTS void randomSize(RNG& rng, int minDims, int maxDims, double maxSizeLog, vector<int>& sz);    
 CV_EXPORTS int randomType(RNG& rng, int typeMask, int minChannels, int maxChannels);
-CV_EXPORTS Mat randomMat(RNG& rng, Size size, int type, bool useRoi);
-CV_EXPORTS Mat randomMat(RNG& rng, const vector<int>& size, int type, bool useRoi);
+CV_EXPORTS Mat randomMat(RNG& rng, Size size, int type, double minVal, double maxVal, bool useRoi);
+CV_EXPORTS Mat randomMat(RNG& rng, const vector<int>& size, int type, double minVal, double maxVal, bool useRoi);
 CV_EXPORTS void add(const Mat& a, double alpha, const Mat& b, double beta,
-                      Scalar gamma, Mat& c, int ctype, bool calcAbs);
-CV_EXPORTS void convert(const Mat& src, Mat& dst, int dtype, double alpha, double beta);
-CV_EXPORTS void copy(const Mat& src, Mat& dst, const Mat& mask=Mat());
+                      Scalar gamma, Mat& c, int ctype, bool calcAbs=false);
+CV_EXPORTS void convert(const Mat& src, Mat& dst, int dtype, double alpha=1, double beta=0);
+CV_EXPORTS void copy(const Mat& src, Mat& dst, const Mat& mask=Mat(), bool invertMask=false);
 CV_EXPORTS void set(Mat& dst, const Scalar& gamma, const Mat& mask=Mat());
-CV_EXPORTS void minMaxFilter(const Mat& a, Mat& maxresult, const Mat& minresult, const Mat& kernel, Point anchor);
-CV_EXPORTS void filter2D(const Mat& src, Mat& dst, int ddepth, const Mat& kernel, Point anchor, double delta, int borderType);
-CV_EXPORTS void copyMakeBorder(const Mat& src, Mat& dst, int top, int bottom, int left, int right, int borderType, Scalar borderValue);
+CV_EXPORTS void erode(const Mat& src, Mat& dst, const Mat& _kernel, Point anchor=Point(-1,-1),
+                      int borderType=IPL_BORDER_CONSTANT, const Scalar& borderValue=Scalar());
+CV_EXPORTS void dilate(const Mat& src, Mat& dst, const Mat& _kernel, Point anchor=Point(-1,-1),
+                       int borderType=IPL_BORDER_CONSTANT, const Scalar& borderValue=Scalar());
+CV_EXPORTS void filter2D(const Mat& src, Mat& dst, int ddepth, const Mat& kernel,
+                         Point anchor, double delta, int borderType,
+                         const Scalar& borderValue=Scalar());
+CV_EXPORTS void copyMakeBorder(const Mat& src, Mat& dst, int top, int bottom, int left, int right,
+                               int borderType, const Scalar& borderValue=Scalar());
 CV_EXPORTS void minMaxLoc(const Mat& src, double* maxval, double* minval,
                           vector<int>* maxloc, vector<int>* minloc, const Mat& mask=Mat());
 CV_EXPORTS double norm(const Mat& src, int normType, const Mat& mask=Mat());
 CV_EXPORTS double norm(const Mat& src1, const Mat& src2, int normType, const Mat& mask=Mat());
-CV_EXPORTS bool cmpEps(const Mat& src1, const Mat& src2, double maxDiff, vector<int>* loc);
+CV_EXPORTS bool cmpEps(const Mat& src1, const Mat& src2, int maxDiff, vector<int>* loc);
 CV_EXPORTS void logicOp(const Mat& src1, const Mat& src2, Mat& dst, char c);
 CV_EXPORTS void logicOp(const Mat& src, const Scalar& s, Mat& dst, char c);
 CV_EXPORTS void compare(const Mat& src1, const Mat& src2, Mat& dst, int cmpop);
-CV_EXPORTS void compare(const Mat& src, const Scalar& s, Mat& dst, int cmpop);    
+CV_EXPORTS void compare(const Mat& src, double s, Mat& dst, int cmpop);    
 CV_EXPORTS void gemm(const Mat& src1, const Mat& src2, double alpha,
                      const Mat& src3, double beta, Mat& dst, int flags);
 CV_EXPORTS void crosscorr(const Mat& src1, const Mat& src2, Mat& dst, int dtype);
index 6a434bb..25082ca 100644 (file)
@@ -1,4 +1,6 @@
 #include "precomp.hpp"
+#include <float.h>
+#include <limits.h>
 
 using namespace cv;
 
@@ -49,14 +51,65 @@ int randomType(RNG& rng, int typeMask, int minChannels, int maxChannels)
     return CV_MAKETYPE(depth, channels);
 }
 
-Mat randomMat(RNG& rng, Size size, int type, bool useRoi)
+double getMinVal(int depth)
 {
-    return Mat();
+    double val = depth == CV_8U ? 0 : depth == CV_8S ? SCHAR_MIN : depth == CV_16U ? 0 :
+    depth == CV_16S ? SHRT_MIN : depth == CV_32S ? INT_MIN :
+    depth == CV_32F ? -FLT_MAX : depth == CV_64F ? -DBL_MAX : -1;
+    CV_Assert(val != -1);
+    return val;
 }
 
-Mat randomMat(RNG& rng, const vector<int>& size, int type, bool useRoi)
+double getMaxVal(int depth)
 {
-    return Mat();
+    double val = depth == CV_8U ? UCHAR_MAX : depth == CV_8S ? SCHAR_MAX : depth == CV_16U ? USHRT_MAX :
+    depth == CV_16S ? SHRT_MAX : depth == CV_32S ? INT_MAX :
+    depth == CV_32F ? FLT_MAX : depth == CV_64F ? DBL_MAX : -1;
+    CV_Assert(val != -1);
+    return val;
+}    
+    
+Mat randomMat(RNG& rng, Size size, int type, double minVal, double maxVal, bool useRoi)
+{
+    Size size0 = size;
+    if( useRoi )
+    {
+        size0.width += std::max(rng.uniform(0, 10) - 5, 0);
+        size0.height += std::max(rng.uniform(0, 10) - 5, 0);
+    }
+        
+    Mat m(size0, type);
+    
+    rng.fill(m, RNG::UNIFORM, Scalar::all(minVal), Scalar::all(maxVal));
+    if( size0 == size )
+        return m;
+    return m(Rect((size0.width-size.width)/2, (size0.height-size.height)/2, size.width, size.height));
+}
+
+Mat randomMat(RNG& rng, const vector<int>& size, int type, double minVal, double maxVal, bool useRoi)
+{
+    int i, dims = (int)size.size();
+    vector<int> size0(dims);
+    vector<Range> r(dims);
+    bool eqsize = true;
+    for( i = 0; i < dims; i++ )
+    {
+        size0[i] = size[i];
+        r[i] = Range::all();
+        if( useRoi )
+        {
+            size0[i] += std::max(rng.uniform(0, 5) - 2, 0);
+            r[i] = Range((size0[i] - size[i])/2, (size0[i] - size[i])/2 + size[i]);
+        }
+        eqsize = eqsize && size[i] == size0[i];
+    }
+    
+    Mat m(dims, &size0[0], type);
+    
+    rng.fill(m, RNG::UNIFORM, Scalar::all(minVal), Scalar::all(maxVal));
+    if( eqsize )
+        return m;
+    return m(&r[0]);
 }
     
 void add(const Mat& _a, double alpha, const Mat& _b, double beta,
@@ -244,7 +297,7 @@ void convert(const Mat& src, Mat& dst, int dtype, double alpha, double beta)
 }
     
      
-void copy(const Mat& src, Mat& dst, const Mat& mask)
+void copy(const Mat& src, Mat& dst, const Mat& mask, bool invertMask)
 {
     dst.create(src.dims, &src.size[0], src.type());
     
@@ -279,7 +332,7 @@ void copy(const Mat& src, Mat& dst, const Mat& mask)
         
         for( j = 0; j < total; j++, sptr += elemSize, dptr += elemSize )
         {
-            if( mptr[j] )
+            if( (mptr[j] != 0) ^ invertMask )
                 for( k = 0; k < elemSize; k++ )
                     dptr[k] = sptr[k];
         }
@@ -345,19 +398,1046 @@ void set(Mat& dst, const Scalar& gamma, const Mat& mask)
         }
     }
 }
+
+    
+template<typename _Tp> static void
+erode_(const Mat& src, Mat& dst, const vector<int>& ofsvec)
+{
+    int width = src.cols*src.channels(), n = (int)ofsvec.size();
+    const int* ofs = &ofsvec[0];
+    
+    for( int y = 0; y < dst.rows; y++ )
+    {
+        const _Tp* sptr = src.ptr<_Tp>(y);
+        _Tp* dptr = dst.ptr<_Tp>(y);
+        
+        for( int x = 0; x < width; x++ )
+        {
+            _Tp result = sptr[x + ofs[0]];
+            for( int i = 1; i < n; i++ )
+                result = std::min(result, sptr[x + ofs[i]]);
+            dptr[x] = result;
+        }
+    }
+}
+
+    
+template<typename _Tp> static void
+dilate_(const Mat& src, Mat& dst, const vector<int>& ofsvec)
+{
+    int width = src.cols*src.channels(), n = (int)ofsvec.size();
+    const int* ofs = &ofsvec[0];
+    
+    for( int y = 0; y < dst.rows; y++ )
+    {
+        const _Tp* sptr = src.ptr<_Tp>(y);
+        _Tp* dptr = dst.ptr<_Tp>(y);
+        
+        for( int x = 0; x < width; x++ )
+        {
+            _Tp result = sptr[x + ofs[0]];
+            for( int i = 1; i < n; i++ )
+                result = std::max(result, sptr[x + ofs[i]]);
+            dptr[x] = result;
+        }
+    }
+}
+    
+    
+void erode(const Mat& _src, Mat& dst, const Mat& _kernel, Point anchor,
+           int borderType, const Scalar& _borderValue)
+{
+    Mat kernel = _kernel, src;
+    Scalar borderValue = _borderValue;
+    if( kernel.empty() )
+        kernel = Mat::ones(3, 3, CV_8U);
+    else
+    {
+        CV_Assert( kernel.type() == CV_8U );
+    }
+    if( anchor == Point(-1,-1) )
+        anchor = Point(kernel.cols/2, kernel.rows/2);
+    if( borderType == IPL_BORDER_CONSTANT )
+        borderValue = getMaxVal(src.depth());
+    copyMakeBorder(_src, src, anchor.y, kernel.rows - anchor.y - 1,
+                   anchor.x, kernel.cols - anchor.y - 1,
+                   borderType, borderValue);
+    dst.create( _src.size(), src.type() );
+    
+    vector<int> ofs;
+    int step = (int)(src.step/src.elemSize1()), cn = src.channels();
+    for( int i = 0; i < kernel.rows; i++ )
+        for( int j = 0; j < kernel.cols; j++ )
+            if( kernel.at<uchar>(i, j) != 0 )
+                ofs.push_back(i*step + j*cn);
+    if( ofs.empty() )
+        ofs.push_back(anchor.y*step + anchor.x*cn);
+    
+    switch( src.depth() )
+    {
+    case CV_8U:
+        erode_<uchar>(src, dst, ofs);
+        break;
+    case CV_8S:
+        erode_<schar>(src, dst, ofs);
+        break;
+    case CV_16U:
+        erode_<ushort>(src, dst, ofs);
+        break;
+    case CV_16S:
+        erode_<short>(src, dst, ofs);
+        break;
+    case CV_32S:
+        erode_<int>(src, dst, ofs);
+        break;
+    case CV_32F:
+        erode_<float>(src, dst, ofs);
+        break;
+    case CV_64F:
+        erode_<double>(src, dst, ofs);
+        break;
+    default:
+        CV_Assert(0);
+    }
+}
+
+void dilate(const Mat& _src, Mat& dst, const Mat& _kernel, Point anchor,
+            int borderType, const Scalar& _borderValue)
+{
+    Mat kernel = _kernel, src;
+    Scalar borderValue = _borderValue;
+    if( kernel.empty() )
+        kernel = Mat::ones(3, 3, CV_8U);
+    else
+    {
+        CV_Assert( kernel.type() == CV_8U );
+    }
+    if( anchor == Point(-1,-1) )
+        anchor = Point(kernel.cols/2, kernel.rows/2);
+    if( borderType == IPL_BORDER_CONSTANT )
+        borderValue = getMinVal(src.depth());
+    copyMakeBorder(_src, src, anchor.y, kernel.rows - anchor.y - 1,
+                   anchor.x, kernel.cols - anchor.y - 1,
+                   borderType, borderValue);
+    dst.create( _src.size(), src.type() );
+    
+    vector<int> ofs;
+    int step = (int)(src.step/src.elemSize1()), cn = src.channels();
+    for( int i = 0; i < kernel.rows; i++ )
+        for( int j = 0; j < kernel.cols; j++ )
+            if( kernel.at<uchar>(i, j) != 0 )
+                ofs.push_back(i*step + j*cn);
+    if( ofs.empty() )
+        ofs.push_back(anchor.y*step + anchor.x*cn);
+    
+    switch( src.depth() )
+    {
+    case CV_8U:
+        dilate_<uchar>(src, dst, ofs);
+        break;
+    case CV_8S:
+        dilate_<schar>(src, dst, ofs);
+        break;
+    case CV_16U:
+        dilate_<ushort>(src, dst, ofs);
+        break;
+    case CV_16S:
+        dilate_<short>(src, dst, ofs);
+        break;
+    case CV_32S:
+        dilate_<int>(src, dst, ofs);
+        break;
+    case CV_32F:
+        dilate_<float>(src, dst, ofs);
+        break;
+    case CV_64F:
+        dilate_<double>(src, dst, ofs);
+        break;
+    default:
+        CV_Assert(0);
+    }
+}    
+
+    
+template<typename _Tp> static void
+filter2D_(const Mat& src, Mat& dst, const vector<int>& ofsvec, const vector<double>& coeffvec)
+{
+    const int* ofs = &ofsvec[0];
+    const double* coeff = &coeffvec[0];
+    int width = dst.cols*dst.channels(), ncoeffs = (int)ofsvec.size();
+    
+    for( int y = 0; y < dst.rows; y++ )
+    {
+        const _Tp* sptr = src.ptr<_Tp>(y);
+        double* dptr = dst.ptr<double>(y);
+        
+        for( int x = 0; x < width; x++ )
+        {
+            double s = 0;
+            for( int i = 0; i < ncoeffs; i++ )
+                s += sptr[ofs[i]]*coeff[i];
+            dptr[x] = s;
+        }
+    }
+}
+    
+    
+void filter2D(const Mat& _src, Mat& dst, int ddepth, const Mat& _kernel,
+              Point anchor, double delta, int borderType, const Scalar& _borderValue)
+{
+    Mat kernel = _kernel, src, _dst;
+    Scalar borderValue = _borderValue;
+    CV_Assert( kernel.type() == CV_32F || kernel.type() == CV_64F );
+    if( anchor == Point(-1,-1) )
+        anchor = Point(kernel.cols/2, kernel.rows/2);
+    if( borderType == IPL_BORDER_CONSTANT )
+        borderValue = getMinVal(src.depth());
+    copyMakeBorder(_src, src, anchor.y, kernel.rows - anchor.y - 1,
+                   anchor.x, kernel.cols - anchor.y - 1,
+                   borderType, borderValue);
+    _dst.create( _src.size(), CV_MAKETYPE(CV_64F, src.channels()) );
+    
+    vector<int> ofs;
+    vector<double> coeff(kernel.rows*kernel.cols);
+    Mat cmat(kernel.rows, kernel.cols, CV_64F, &coeff[0]);
+    convert(kernel, cmat, cmat.type());
     
+    int step = (int)(src.step/src.elemSize1()), cn = src.channels();
+    for( int i = 0; i < kernel.rows; i++ )
+        for( int j = 0; j < kernel.cols; j++ )
+                ofs.push_back(i*step + j*cn);
+    
+    switch( src.depth() )
+    {
+    case CV_8U:
+        filter2D_<uchar>(src, _dst, ofs, coeff);
+        break;
+    case CV_8S:
+        filter2D_<schar>(src, _dst, ofs, coeff);
+        break;
+    case CV_16U:
+        filter2D_<ushort>(src, _dst, ofs, coeff);
+        break;
+    case CV_16S:
+        filter2D_<short>(src, _dst, ofs, coeff);
+        break;
+    case CV_32S:
+        filter2D_<int>(src, _dst, ofs, coeff);
+        break;
+    case CV_32F:
+        filter2D_<float>(src, _dst, ofs, coeff);
+        break;
+    case CV_64F:
+        filter2D_<double>(src, _dst, ofs, coeff);
+        break;
+    default:
+        CV_Assert(0);
+    }
+    
+    convert(_dst, dst, ddepth, 1, delta);
+}
+
+
+static int borderInterpolate( int p, int len, int borderType )
+{
+    if( (unsigned)p < (unsigned)len )
+        ;
+    else if( borderType == IPL_BORDER_REPLICATE )
+        p = p < 0 ? 0 : len - 1;
+    else if( borderType == IPL_BORDER_REFLECT || borderType == IPL_BORDER_REFLECT_101 )
+    {
+        int delta = borderType == IPL_BORDER_REFLECT_101;
+        if( len == 1 )
+            return 0;
+        do
+        {
+            if( p < 0 )
+                p = -p - 1 + delta;
+            else
+                p = len - 1 - (p - len) - delta;
+        }
+        while( (unsigned)p >= (unsigned)len );
+    }
+    else if( borderType == IPL_BORDER_WRAP )
+    {
+        if( p < 0 )
+            p -= ((p-len+1)/len)*len;
+        if( p >= len )
+            p %= len;
+    }
+    else if( borderType == IPL_BORDER_CONSTANT )
+        p = -1;
+    else
+        CV_Error( CV_StsBadArg, "Unknown/unsupported border type" );
+    return p;
+}    
+    
+    
+void copyMakeBorder(const Mat& src, Mat& dst, int top, int bottom, int left, int right,
+                    int borderType, const Scalar& borderValue)
+{
+    dst.create(src.rows + top + bottom, src.cols + left + right, src.type());
+    int i, j, k, esz = (int)src.elemSize();
+    int width = src.cols*esz, width1 = dst.cols*esz;
+    
+    if( borderType == IPL_BORDER_CONSTANT )
+    {
+        vector<uchar> valvec((src.cols + left + right)*esz);
+        uchar* val = &valvec[0];
+        scalarToRawData(borderValue, val, src.type(), (src.cols + left + right)*src.channels());
+        
+        left *= esz;
+        right *= esz;
+        for( i = 0; i < src.rows; i++ )
+        {
+            const uchar* sptr = src.ptr(i);
+            uchar* dptr = dst.ptr(i + top) + left;
+            for( j = 0; j < left; j++ )
+                dptr[j - left] = val[j];
+            if( dptr != sptr )
+                for( j = 0; j < width; j++ )
+                    dptr[j] = sptr[j];
+            for( j = 0; j < right; j++ )
+                dptr[j + width] = val[j];
+        }
+        
+        for( i = 0; i < top; i++ )
+        {
+            uchar* dptr = dst.ptr(i);
+            for( j = 0; j < width1; j++ )
+                dptr[j] = val[j];
+        }
+        
+        for( i = 0; i < bottom; i++ )
+        {
+            uchar* dptr = dst.ptr(i + top + src.rows);
+            for( j = 0; j < width1; j++ )
+                dptr[j] = val[j];
+        }
+    }
+    else
+    {
+        vector<int> tabvec((left + right)*esz);
+        int* ltab = &tabvec[0];
+        int* rtab = &tabvec[left*esz];
+        for( i = 0; i < left; i++ )
+        {
+            j = borderInterpolate(i - left, src.cols, borderType)*esz;
+            for( k = 0; k < esz; k++ )
+                ltab[i*esz + k] = j + k;
+        }
+        for( i = 0; i < right; i++ )
+        {
+            j = borderInterpolate(src.cols + i, src.cols, borderType)*esz;
+            for( k = 0; k < esz; k++ )
+                rtab[i*esz + k] = j + k;
+        }
+        
+        left *= esz;
+        right *= esz;
+        for( i = 0; i < src.rows; i++ )
+        {
+            const uchar* sptr = src.ptr(i);
+            uchar* dptr = dst.ptr(i + top);
+            
+            for( j = 0; j < left; j++ )
+                dptr[j] = sptr[ltab[j]];
+            if( dptr + left != sptr )
+            {
+                for( j = 0; j < width; j++ )
+                    dptr[j + left] = sptr[j];
+            }
+            for( j = 0; j < right; j++ )
+                dptr[j + left + width] = sptr[rtab[j]];
+        }
+        
+        for( i = 0; i < top; i++ )
+        {
+            j = borderInterpolate(i - top, src.rows, borderType);
+            const uchar* sptr = dst.ptr(j + top);
+            uchar* dptr = dst.ptr(i);
+            
+            for( k = 0; k < width1; k++ )
+                dptr[k] = sptr[k];
+        }
+        
+        for( i = 0; i < bottom; i++ )
+        {
+            j = borderInterpolate(i + src.rows, src.rows, borderType);
+            const uchar* sptr = dst.ptr(j + top);
+            uchar* dptr = dst.ptr(i + top + src.rows);
+            
+            for( k = 0; k < width1; k++ )
+                dptr[k] = sptr[k];
+        }
+    }
+}
+
+
+template<typename _Tp> static void
+minMaxLoc_(const _Tp* src, size_t total, size_t startidx,
+           double* _maxval, double* _minval,
+           size_t* _minpos, size_t* _maxpos,
+           const uchar* mask)
+{
+    _Tp maxval = saturate_cast<_Tp>(*_maxval), minval = saturate_cast<_Tp>(*_minval);
+    size_t minpos = *_minpos, maxpos = *_maxpos;
+    
+    if( !mask )
+    {
+        for( size_t i = 0; i < total; i++ )
+        {
+            _Tp val = src[i];
+            if( minval > val )
+            {
+                minval = val;
+                minpos = startidx + i;
+            }
+            if( maxval < val )
+            {
+                maxval = val;
+                maxpos = startidx + i;
+            }
+        }
+    }
+    else
+    {
+        for( size_t i = 0; i < total; i++ )
+        {
+            _Tp val = src[i];
+            if( minval > val && mask[i] )
+            {
+                minval = val;
+                minpos = startidx + i;
+            }
+            if( maxval < val && mask[i] )
+            {
+                maxval = val;
+                maxpos = startidx + i;
+            }
+        }
+    }
+    
+    *_maxval = maxval;
+    *_minval = minval;
+    *_maxpos = maxpos;
+    *_minpos = minpos;
+}
+
+
+static void setpos( const Mat& mtx, vector<int>& pos, size_t idx )
+{
+    pos.resize(mtx.dims);
+    for( int i = mtx.dims-1; i >= 0; i-- )
+    {
+        int sz = mtx.size[i]*(i == mtx.dims-1 ? mtx.channels() : 1);
+        pos[i] = idx % sz;
+        idx /= sz;
+    }
+}
+    
+void minMaxLoc(const Mat& src, double* _maxval, double* _minval,
+               vector<int>* _maxloc, vector<int>* _minloc,
+               const Mat& mask)
+{
+    CV_Assert( src.channels() == 1 );
+    const Mat *arrays[2]={&src, &mask};
+    Mat planes[2];
+    
+    NAryMatIterator it(arrays, planes, 2);
+    size_t startidx = 1, total = planes[0].total();
+    int i, nplanes = it.nplanes, depth = src.depth();
+    double maxval = depth < CV_32F ? INT_MIN : depth == CV_32F ? -FLT_MAX : -DBL_MAX;
+    double minval = depth < CV_32F ? INT_MAX : depth == CV_32F ? FLT_MAX : DBL_MAX;
+    size_t maxidx = 0, minidx = 0;
+    
+    for( i = 0; i < nplanes; i++, ++it, startidx += total )
+    {
+        const uchar* sptr = planes[0].data;
+        const uchar* mptr = planes[1].data;
+        
+        switch( depth )
+        {
+        case CV_8U:
+            minMaxLoc_((const uchar*)sptr, total, startidx,
+                       &maxval, &minval, &maxidx, &minidx, mptr);
+            break;
+        case CV_8S:
+            minMaxLoc_((const schar*)sptr, total, startidx,
+                       &maxval, &minval, &maxidx, &minidx, mptr);
+            break;
+        case CV_16U:
+            minMaxLoc_((const ushort*)sptr, total, startidx,
+                       &maxval, &minval, &maxidx, &minidx, mptr);
+            break;
+        case CV_16S:
+            minMaxLoc_((const short*)sptr, total, startidx,
+                       &maxval, &minval, &maxidx, &minidx, mptr);
+            break;
+        case CV_32S:
+            minMaxLoc_((const int*)sptr, total, startidx,
+                       &maxval, &minval, &maxidx, &minidx, mptr);
+            break;
+        case CV_32F:
+            minMaxLoc_((const float*)sptr, total, startidx,
+                       &maxval, &minval, &maxidx, &minidx, mptr);
+            break;
+        case CV_64F:
+            minMaxLoc_((const double*)sptr, total, startidx,
+                       &maxval, &minval, &maxidx, &minidx, mptr);
+            break;
+        default:
+            CV_Assert(0);
+        }
+    }
+    
+    if( _maxval )
+        *_maxval = maxval;
+    if( _minval )
+        *_minval = minval;
+    if( _maxloc )
+        setpos( src, *_maxloc, maxidx );
+    if( _minloc )
+        setpos( src, *_minloc, minidx );
+}
+
+    
+template<typename _Tp> static double
+norm_(const _Tp* src, size_t total, int normType, double startval, const uchar* mask)
+{
+    size_t i;
+    double result = startval;
+    
+    if( normType == NORM_INF )
+    {
+        if( !mask )
+            for( i = 0; i < total; i++ )
+                result = std::max(result, (double)std::abs(src[i]));
+        else
+            for( i = 0; i < total; i++ )
+                if( mask[i] )
+                    result = std::max(result, (double)std::abs(src[i]));
+    }
+    else if( normType == NORM_L1 )
+    {
+        if( !mask )
+            for( i = 0; i < total; i++ )
+                result += std::abs(src[i]);
+        else
+            for( i = 0; i < total; i++ )
+                if( mask[i] )
+                    result += std::abs(src[i]);
+    }
+    else
+    {
+        if( !mask )
+            for( i = 0; i < total; i++ )
+            {
+                double v = src[i];
+                result += v*v;
+            }
+        else
+            for( i = 0; i < total; i++ )
+                if( mask[i] )
+                {
+                    double v = src[i];
+                    result += v*v;
+                }
+    }
+    return result;
+}
+
+
+template<typename _Tp> static double
+norm_(const _Tp* src1, const _Tp* src2, size_t total, int normType, double startval, const uchar* mask)
+{
+    size_t i;
+    double result = startval;
+    
+    if( normType == NORM_INF )
+    {
+        if( !mask )
+            for( i = 0; i < total; i++ )
+                result = std::max(result, (double)std::abs(src1[i] - src2[i]));
+        else
+            for( i = 0; i < total; i++ )
+                if( mask[i] )
+                    result = std::max(result, (double)std::abs(src1[i] - src2[i]));
+    }
+    else if( normType == NORM_L1 )
+    {
+        if( !mask )
+            for( i = 0; i < total; i++ )
+                result += std::abs(src1[i] - src2[i]);
+        else
+            for( i = 0; i < total; i++ )
+                if( mask[i] )
+                    result += std::abs(src1[i] - src2[i]);
+    }
+    else
+    {
+        if( !mask )
+            for( i = 0; i < total; i++ )
+            {
+                double v = src1[i] - src2[i];
+                result += v*v;
+            }
+        else
+            for( i = 0; i < total; i++ )
+                if( mask[i] )
+                {
+                    double v = src1[i] - src2[i];
+                    result += v*v;
+                }
+    }
+    return result;
+}
+    
+    
+double norm(const Mat& src, int normType, const Mat& mask)
+{
+    CV_Assert( mask.empty() || (src.size == mask.size && mask.type() == CV_8U) );
+    CV_Assert( normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2 );
+    const Mat *arrays[2]={&src, &mask};
+    Mat planes[2];
+    
+    NAryMatIterator it(arrays, planes, 2);
+    size_t total = planes[0].total()*planes[0].channels();
+    int i, nplanes = it.nplanes, depth = src.depth();
+    double result = 0;
+    
+    for( i = 0; i < nplanes; i++, ++it )
+    {
+        const uchar* sptr = planes[0].data;
+        const uchar* mptr = planes[1].data;
+        
+        switch( depth )
+        {
+        case CV_8U:
+            result = norm_((const uchar*)sptr, total, normType, result, mptr);
+            break;
+        case CV_8S:
+            result = norm_((const schar*)sptr, total, normType, result, mptr);
+            break;
+        case CV_16U:
+            result = norm_((const ushort*)sptr, total, normType, result, mptr);
+            break;
+        case CV_16S:
+            result = norm_((const short*)sptr, total, normType, result, mptr);
+            break;
+        case CV_32S:
+            result = norm_((const int*)sptr, total, normType, result, mptr);
+            break;
+        case CV_32F:
+            result = norm_((const float*)sptr, total, normType, result, mptr);
+            break;
+        case CV_64F:
+            result = norm_((const double*)sptr, total, normType, result, mptr);
+            break;
+        default:
+            CV_Error(CV_StsUnsupportedFormat, "");
+        };
+    }
+    if( normType == NORM_L2 )
+        result = sqrt(result);
+    return result;
+}
+    
+double norm(const Mat& src1, const Mat& src2, int normType, const Mat& mask)
+{
+    CV_Assert( src1.type() == src2.type() && src1.size == src2.size );
+    CV_Assert( mask.empty() || (src1.size == mask.size && mask.type() == CV_8U) );
+    CV_Assert( normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2 );
+    const Mat *arrays[3]={&src1, &src2, &mask};
+    Mat planes[3];
+    
+    NAryMatIterator it(arrays, planes, 3);
+    size_t total = planes[0].total()*planes[0].channels();
+    int i, nplanes = it.nplanes, depth = src1.depth();
+    double result = 0;
+    
+    for( i = 0; i < nplanes; i++, ++it )
+    {
+        const uchar* sptr1 = planes[0].data;
+        const uchar* sptr2 = planes[1].data;
+        const uchar* mptr = planes[2].data;
+        
+        switch( depth )
+        {
+        case CV_8U:
+            result = norm_((const uchar*)sptr1, (const uchar*)sptr2, total, normType, result, mptr);
+            break;
+        case CV_8S:
+            result = norm_((const schar*)sptr1, (const schar*)sptr2, total, normType, result, mptr);
+            break;
+        case CV_16U:
+            result = norm_((const ushort*)sptr1, (const ushort*)sptr2, total, normType, result, mptr);
+            break;
+        case CV_16S:
+            result = norm_((const short*)sptr1, (const short*)sptr2, total, normType, result, mptr);
+            break;
+        case CV_32S:
+            result = norm_((const int*)sptr1, (const int*)sptr2, total, normType, result, mptr);
+            break;
+        case CV_32F:
+            result = norm_((const float*)sptr1, (const float*)sptr2, total, normType, result, mptr);
+            break;
+        case CV_64F:
+            result = norm_((const double*)sptr1, (const double*)sptr2, total, normType, result, mptr);
+            break;
+        default:
+            CV_Error(CV_StsUnsupportedFormat, "");
+        };
+    }
+    if( normType == NORM_L2 )
+        result = sqrt(result);
+    return result;
+}
     
-/*void minMaxFilter(const Mat& a, Mat& maxresult, const Mat& minresult, const Mat& kernel, Point anchor);
-void filter2D(const Mat& src, Mat& dst, int ddepth, const Mat& kernel, Point anchor, double delta, int borderType);
-void copyMakeBorder(const Mat& src, Mat& dst, int top, int bottom, int left, int right, int borderType, Scalar borderValue);
-void minMaxLoc(const Mat& src, double* maxval, double* minval,
-               vector<int>* maxloc, vector<int>* minloc, const Mat& mask=Mat());
-double norm(const Mat& src, int normType, const Mat& mask=Mat());
-double norm(const Mat& src1, const Mat& src2, int normType, const Mat& mask=Mat());
 bool cmpEps(const Mat& src1, const Mat& src2, int int_maxdiff, int flt_maxulp, vector<int>* loc);
-void logicOp(const Mat& src1, const Mat& src2, Mat& dst, char c);
-void logicOp(const Mat& src, const Scalar& s, Mat& dst, char c);
-void compare(const Mat& src1, const Mat& src2, Mat& dst, int cmpop);
-void compare(const Mat& src, const Scalar& s, Mat& dst, int cmpop);*/
+
+static void
+logicOp_(const uchar* src1, const uchar* src2, uchar* dst, size_t total, char c)
+{
+    size_t i;
+    if( c == '&' )
+        for( i = 0; i < total; i++ )
+            dst[i] = src1[i] & src2[i];
+    else if( c == '|' )
+        for( i = 0; i < total; i++ )
+            dst[i] = src1[i] | src2[i];
+    else
+        for( i = 0; i < total; i++ )
+            dst[i] = src1[i] ^ src2[i];
+}
+
+static void
+logicOpS_(const uchar* src, const uchar* scalar, uchar* dst, size_t total, char c)
+{
+    const size_t blockSize = 96;
+    size_t i, j;
+    if( c == '&' )
+        for( i = 0; i < total; i += blockSize, dst += blockSize, src += blockSize )
+        {
+            size_t sz = std::min(total - i, blockSize);
+            for( j = 0; j < sz; j++ )
+                dst[j] = src[j] & scalar[j];
+        }
+    else if( c == '|' )
+        for( i = 0; i < total; i += blockSize, dst += blockSize, src += blockSize )
+        {
+            size_t sz = std::min(total - i, blockSize);
+            for( j = 0; j < sz; j++ )
+                dst[j] = src[j] | scalar[j];
+        }
+    else if( c == '^' )
+    {
+        for( i = 0; i < total; i += blockSize, dst += blockSize, src += blockSize )
+        {
+            size_t sz = std::min(total - i, blockSize);
+            for( j = 0; j < sz; j++ )
+                dst[j] = src[j] ^ scalar[j];
+        }
+    }
+    else
+        for( i = 0; i < total; i++ )
+            dst[i] = ~src[i];
+}    
+    
+void logicOp( const Mat& src1, const Mat& src2, Mat& dst, char op )
+{
+    CV_Assert( op == '&' || op == '|' || op == '^' );
+    CV_Assert( src1.type() == src2.type() && src1.size == src2.size );
+    dst.create( src1.dims, &src1.size[0], src1.type() );
+    const Mat *arrays[3]={&src1, &src2, &dst};
+    Mat planes[3];
+    
+    NAryMatIterator it(arrays, planes, 3);
+    size_t total = planes[0].total()*planes[0].elemSize();
+    int i, nplanes = it.nplanes;
+    
+    for( i = 0; i < nplanes; i++, ++it )
+    {
+        const uchar* sptr1 = planes[0].data;
+        const uchar* sptr2 = planes[1].data;
+        uchar* dptr = planes[2].data;
+        
+        logicOp_(sptr1, sptr2, dptr, total, op);
+    }
+}
+    
+    
+void logicOp(const Mat& src, const Scalar& s, Mat& dst, char op)
+{
+    CV_Assert( op == '&' || op == '|' || op == '^' );
+    dst.create( src.dims, &src.size[0], src.type() );
+    const Mat *arrays[2]={&src, &dst};
+    Mat planes[2];
+    
+    NAryMatIterator it(arrays, planes, 2);
+    size_t total = planes[0].total()*planes[0].elemSize();
+    int i, nplanes = it.nplanes;
+    double buf[12];
+    scalarToRawData(s, buf, src.type(), 12);
+    
+    for( i = 0; i < nplanes; i++, ++it )
+    {
+        const uchar* sptr = planes[0].data;
+        uchar* dptr = planes[1].data;
+        
+        logicOpS_(sptr, (uchar*)&buf[0], dptr, total, op);
+    }
+}
+
+
+template<typename _Tp> static void
+compare_(const _Tp* src1, const _Tp* src2, uchar* dst, size_t total, int cmpop)
+{
+    size_t i;
+    switch( cmpop )
+    {
+    case CMP_LT:
+        for( i = 0; i < total; i++ )
+            dst[i] = src1[i] < src2[i] ? 255 : 0;
+        break;
+    case CMP_LE:
+        for( i = 0; i < total; i++ )
+            dst[i] = src1[i] <= src2[i] ? 255 : 0;
+        break;
+    case CMP_EQ:
+        for( i = 0; i < total; i++ )
+            dst[i] = src1[i] == src2[i] ? 255 : 0;
+        break;
+    case CMP_NE:
+        for( i = 0; i < total; i++ )
+            dst[i] = src1[i] != src2[i] ? 255 : 0;
+        break;
+    case CMP_GE:
+        for( i = 0; i < total; i++ )
+            dst[i] = src1[i] >= src2[i] ? 255 : 0;
+        break;
+    case CMP_GT:
+        for( i = 0; i < total; i++ )
+            dst[i] = src1[i] > src2[i] ? 255 : 0;
+        break;
+    default:
+        CV_Error(CV_StsBadArg, "Unknown comparison operation");
+    }
+}
+
+
+template<typename _Tp, typename _WTp> static void
+compareS_(const _Tp* src1, _WTp value, uchar* dst, size_t total, int cmpop)
+{
+    size_t i;
+    switch( cmpop )
+    {
+    case CMP_LT:
+        for( i = 0; i < total; i++ )
+            dst[i] = src1[i] < value ? 255 : 0;
+        break;
+    case CMP_LE:
+        for( i = 0; i < total; i++ )
+            dst[i] = src1[i] <= value ? 255 : 0;
+        break;
+    case CMP_EQ:
+        for( i = 0; i < total; i++ )
+            dst[i] = src1[i] == value ? 255 : 0;
+        break;
+    case CMP_NE:
+        for( i = 0; i < total; i++ )
+            dst[i] = src1[i] != value ? 255 : 0;
+        break;
+    case CMP_GE:
+        for( i = 0; i < total; i++ )
+            dst[i] = src1[i] >= value ? 255 : 0;
+        break;
+    case CMP_GT:
+        for( i = 0; i < total; i++ )
+            dst[i] = src1[i] > value ? 255 : 0;
+        break;
+    default:
+        CV_Error(CV_StsBadArg, "Unknown comparison operation");
+    }
+}    
+    
+    
+void compare(const Mat& src1, const Mat& src2, Mat& dst, int cmpop)
+{
+    CV_Assert( src1.type() == src2.type() && src1.channels() == 1 && src1.size == src2.size );
+    dst.create( src1.dims, &src1.size[0], CV_8U );
+    const Mat *arrays[3]={&src1, &src2, &dst};
+    Mat planes[3];
+    
+    NAryMatIterator it(arrays, planes, 3);
+    size_t total = planes[0].total()*planes[0].elemSize();
+    int i, nplanes = it.nplanes, depth = src1.depth();
+    
+    for( i = 0; i < nplanes; i++, ++it )
+    {
+        const uchar* sptr1 = planes[0].data;
+        const uchar* sptr2 = planes[1].data;
+        uchar* dptr = planes[2].data;
+        
+        switch( depth )
+        {
+        case CV_8U:
+            compare_((const uchar*)sptr1, (const uchar*)sptr2, dptr, total, cmpop);
+            break;
+        case CV_8S:
+            compare_((const schar*)sptr1, (const schar*)sptr2, dptr, total, cmpop);
+            break;
+        case CV_16U:
+            compare_((const ushort*)sptr1, (const ushort*)sptr2, dptr, total, cmpop);
+            break;
+        case CV_16S:
+            compare_((const short*)sptr1, (const short*)sptr2, dptr, total, cmpop);
+            break;
+        case CV_32S:
+            compare_((const int*)sptr1, (const int*)sptr2, dptr, total, cmpop);
+            break;
+        case CV_32F:
+            compare_((const float*)sptr1, (const float*)sptr2, dptr, total, cmpop);
+            break;
+        case CV_64F:
+            compare_((const double*)sptr1, (const double*)sptr2, dptr, total, cmpop);
+            break;
+        default:
+            CV_Error(CV_StsUnsupportedFormat, "");
+        }
+    }
+}
+    
+void compare(const Mat& src, double value, Mat& dst, int cmpop)
+{
+    CV_Assert( src.channels() == 1 );
+    dst.create( src.dims, &src.size[0], CV_8U );
+    const Mat *arrays[2]={&src, &dst};
+    Mat planes[2];
+    
+    NAryMatIterator it(arrays, planes, 2);
+    size_t total = planes[0].total()*planes[0].elemSize();
+    int i, nplanes = it.nplanes, depth = src.depth();
+    int ivalue = saturate_cast<int>(value);
+    
+    for( i = 0; i < nplanes; i++, ++it )
+    {
+        const uchar* sptr = planes[0].data;
+        uchar* dptr = planes[1].data;
+        
+        switch( depth )
+        {
+        case CV_8U:
+            compareS_((const uchar*)sptr, ivalue, dptr, total, cmpop);
+            break;
+        case CV_8S:
+            compareS_((const schar*)sptr, ivalue, dptr, total, cmpop);
+            break;
+        case CV_16U:
+            compareS_((const ushort*)sptr, ivalue, dptr, total, cmpop);
+            break;
+        case CV_16S:
+            compareS_((const short*)sptr, ivalue, dptr, total, cmpop);
+            break;
+        case CV_32S:
+            compareS_((const int*)sptr, ivalue, dptr, total, cmpop);
+            break;
+        case CV_32F:
+            compareS_((const float*)sptr, value, dptr, total, cmpop);
+            break;
+        case CV_64F:
+            compareS_((const double*)sptr, value, dptr, total, cmpop);
+            break;
+        default:
+            CV_Error(CV_StsUnsupportedFormat, "");
+        }
+    }
+}
+
+    
+template<typename _Tp> static bool
+cmpEpsInt_(const _Tp* src1, const _Tp* src2, int imaxdiff, size_t total, size_t startidx, size_t& idx)
+{
+    size_t i;
+    for( i = 0; i < total; i++ )
+        if( std::abs(src1[i] - src2[i]) > imaxdiff )
+        {
+            idx = i + startidx;
+            return false;
+        }
+    return true;
+}
+
+
+template<typename _Tp> static bool
+cmpEpsFlt_(const _Tp* src1, const _Tp* src2, size_t total, int imaxdiff, size_t startidx, size_t& idx)
+{
+    const _Tp C = ((_Tp)1 << (sizeof(_Tp)*8-1)) - 1;
+    size_t i;
+    for( i = 0; i < total; i++ )
+    {
+        _Tp a = src1[i], b = src2[i];
+        if( a < 0 ) a ^= C; if( b < 0 ) b ^= C;
+        _Tp d = std::abs(a - b);
+        if( d > imaxdiff )
+        {
+            idx = i + startidx;
+            return false;
+        }
+    }
+    return true;
+}
+    
+    
+bool cmpEps(const Mat& src1, const Mat& src2, int imaxDiff, vector<int>* loc)
+{
+    CV_Assert( src1.type() == src2.type() && src1.size == src2.size );
+    const Mat *arrays[2]={&src1, &src2};
+    Mat planes[2];
+    
+    NAryMatIterator it(arrays, planes, 2);
+    size_t total = planes[0].total()*planes[0].channels();
+    int i, nplanes = it.nplanes, depth = src1.depth();
+    size_t startidx = 0, idx = -1;
+    bool ok = true;
+    
+    for( i = 0; i < nplanes; i++, ++it, startidx += total )
+    {
+        const uchar* sptr1 = planes[0].data;
+        const uchar* sptr2 = planes[1].data;
+
+        switch( depth )
+        {
+        case CV_8U:
+            ok = cmpEpsInt_((const uchar*)sptr1, (const uchar*)sptr2, total, imaxDiff, startidx, idx);
+            break;
+        case CV_8S:
+            ok = cmpEpsInt_((const schar*)sptr1, (const schar*)sptr2, total, imaxDiff, startidx, idx);
+            break;
+        case CV_16U:
+            ok = cmpEpsInt_((const ushort*)sptr1, (const ushort*)sptr2, total, imaxDiff, startidx, idx);
+            break;
+        case CV_16S:
+            ok = cmpEpsInt_((const short*)sptr1, (const short*)sptr2, total, imaxDiff, startidx, idx);
+            break;
+        case CV_32S:
+            ok = cmpEpsInt_((const int*)sptr1, (const int*)sptr2, total, imaxDiff, startidx, idx);
+            break;
+        case CV_32F:
+            ok = cmpEpsFlt_((const int*)sptr1, (const int*)sptr2, total, imaxDiff, startidx, idx);
+            break;
+        case CV_64F:
+            ok = cmpEpsFlt_((const int64*)sptr1, (const int64*)sptr2, total, imaxDiff, startidx, idx);
+            break;
+        default:
+            CV_Error(CV_StsUnsupportedFormat, "");
+        }
+        if(!ok)
+            break;
+    }
+    if(!ok && loc)
+        setpos(src1, *loc, idx);
+    return ok;
+}
 
 }