www.pudn.com > OpenCV-Intel.zip > cvutils.cpp


/*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. 
// 
// 
//                        Intel License Agreement 
//                For Open Source Computer Vision Library 
// 
// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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*/ 
 
#include "_cv.h" 
 
CV_IMPL CvSeq* cvPointSeqFromMat( int seq_kind, const CvArr* arr, 
                                  CvContour* contour_header, CvSeqBlock* block ) 
{ 
    CvSeq* contour = 0; 
 
    CV_FUNCNAME( "cvPointSeqFromMat" ); 
 
    assert( arr != 0 && contour_header != 0 && block != 0 ); 
 
    __BEGIN__; 
     
    int eltype; 
    CvMat* mat = (CvMat*)arr; 
     
    if( !CV_IS_MAT( mat )) 
        CV_ERROR( CV_StsBadArg, "Input array is not a valid matrix" );  
 
    eltype = CV_MAT_TYPE( mat->type ); 
    if( eltype != CV_32SC2 && eltype != CV_32FC2 ) 
        CV_ERROR( CV_StsUnsupportedFormat, 
        "The matrix can not be converted to point sequence because of " 
        "inappropriate element type" ); 
 
    if( mat->width != 1 && mat->height != 1 || !CV_IS_MAT_CONT(mat->type)) 
        CV_ERROR( CV_StsBadArg, 
        "The matrix converted to point sequence must be " 
        "1-dimensional and continuous" ); 
 
    CV_CALL( cvMakeSeqHeaderForArray( 
            (seq_kind & (CV_SEQ_KIND_MASK|CV_SEQ_FLAG_CLOSED)) | eltype, 
            sizeof(CvContour), CV_ELEM_SIZE(eltype), mat->data.ptr, 
            mat->width*mat->height, (CvSeq*)contour_header, block )); 
 
    contour = (CvSeq*)contour_header; 
 
    __END__; 
 
    return contour; 
} 
 
#if 0 
 
/*F/////////////////////////////////////////////////////////////////////////////////////// 
//    Names:      icvJacobiEigens_32f, icvJacobiEigens_64d 
//    Purpose:    Eigenvalues & eigenvectors calculation of a symmetric matrix: 
//                A Vi  =  Ei Vi 
//    Context:    
//    Parameters: A(n, n) - source symmetric matrix (n - rows & columns number), 
//                V(n, n) - matrix of its eigenvectors  
//                          (i-th row is an eigenvector Vi), 
//                E(n)    - vector of its eigenvalues 
//                          (i-th element is an eigenvalue Ei), 
//                eps     - accuracy of diagonalization. 
//                
//    Returns: 
//    CV_NO_ERROR or error code      
//    Notes: 
//        1. The functions destroy source matrix A, so if you need it further, you 
//           have to copy it before the processing. 
//        2. Eigenvalies and eigenvectors are sorted in Ei absolute value descending. 
//        3. Calculation time depends on eps value. If the time isn't very important, 
//           we recommend to set eps = 0. 
//F*/ 
 
/*=========================== Single precision function ================================*/ 
 
CvStatus CV_STDCALL icvJacobiEigens_32f(float *A, float *V, float *E, int n, float eps) 
{ 
    int i, j, k, ind, iters = 0; 
    float *AA = A, *VV = V; 
    double Amax, anorm = 0, ax; 
 
    if( A == NULL || V == NULL || E == NULL ) 
        return CV_NULLPTR_ERR; 
    if( n <= 0 ) 
        return CV_BADSIZE_ERR; 
    if( eps < DBL_EPSILON ) 
        eps = DBL_EPSILON; 
 
    /*-------- Prepare --------*/ 
    for( i = 0; i < n; i++, VV += n, AA += n ) 
    { 
        for( j = 0; j < i; j++ ) 
        { 
            double Am = AA[j]; 
 
            anorm += Am * Am; 
        } 
        for( j = 0; j < n; j++ ) 
            VV[j] = 0.f; 
        VV[i] = 1.f; 
    } 
 
    anorm = sqrt( anorm + anorm ); 
    ax = anorm * eps / n; 
    Amax = anorm; 
 
    while( Amax > ax && iters++ < 100 ) 
    { 
        Amax /= n; 
        do                      /* while (ind) */ 
        { 
            int p, q; 
            float *V1 = V, *A1 = A; 
 
            ind = 0; 
            for( p = 0; p < n - 1; p++, A1 += n, V1 += n ) 
            { 
                float *A2 = A + n * (p + 1), *V2 = V + n * (p + 1); 
 
                for( q = p + 1; q < n; q++, A2 += n, V2 += n ) 
                { 
                    double x, y, c, s, c2, s2, a; 
                    float *A3, Apq = A1[q], App, Aqq, Aip, Aiq, Vpi, Vqi; 
 
                    if( fabs( Apq ) < Amax ) 
                        continue; 
 
                    ind = 1; 
 
                    /*---- Calculation of rotation angle's sine & cosine ----*/ 
                    App = A1[p]; 
                    Aqq = A2[q]; 
                    y = 5.0e-1 * (App - Aqq); 
                    x = -Apq / sqrt( (double)Apq * Apq + (double)y * y ); 
                    if( y < 0.0 ) 
                        x = -x; 
                    s = x / sqrt( 2.0 * (1.0 + sqrt( 1.0 - (double)x * x ))); 
                    s2 = s * s; 
                    c = sqrt( 1.0 - s2 ); 
                    c2 = c * c; 
                    a = 2.0 * Apq * c * s; 
 
                    /*---- Apq annulation ----*/ 
                    A3 = A; 
                    for( i = 0; i < p; i++, A3 += n ) 
                    { 
                        Aip = A3[p]; 
                        Aiq = A3[q]; 
                        Vpi = V1[i]; 
                        Vqi = V2[i]; 
                        A3[p] = (float) (Aip * c - Aiq * s); 
                        A3[q] = (float) (Aiq * c + Aip * s); 
                        V1[i] = (float) (Vpi * c - Vqi * s); 
                        V2[i] = (float) (Vqi * c + Vpi * s); 
                    } 
                    for( ; i < q; i++, A3 += n ) 
                    { 
                        Aip = A1[i]; 
                        Aiq = A3[q]; 
                        Vpi = V1[i]; 
                        Vqi = V2[i]; 
                        A1[i] = (float) (Aip * c - Aiq * s); 
                        A3[q] = (float) (Aiq * c + Aip * s); 
                        V1[i] = (float) (Vpi * c - Vqi * s); 
                        V2[i] = (float) (Vqi * c + Vpi * s); 
                    } 
                    for( ; i < n; i++ ) 
                    { 
                        Aip = A1[i]; 
                        Aiq = A2[i]; 
                        Vpi = V1[i]; 
                        Vqi = V2[i]; 
                        A1[i] = (float) (Aip * c - Aiq * s); 
                        A2[i] = (float) (Aiq * c + Aip * s); 
                        V1[i] = (float) (Vpi * c - Vqi * s); 
                        V2[i] = (float) (Vqi * c + Vpi * s); 
                    } 
                    A1[p] = (float) (App * c2 + Aqq * s2 - a); 
                    A2[q] = (float) (App * s2 + Aqq * c2 + a); 
                    A1[q] = A2[p] = 0.0f; 
                }               /*q */ 
            }                   /*p */ 
        } 
        while( ind ); 
        Amax /= n; 
    }                           /* while ( Amax > ax ) */ 
 
    for( i = 0, k = 0; i < n; i++, k += n + 1 ) 
        E[i] = A[k]; 
    /*printf(" M = %d\n", M); */ 
 
    /* -------- ordering -------- */ 
    for( i = 0; i < n; i++ ) 
    { 
        int m = i; 
        float Em = (float) fabs( E[i] ); 
 
        for( j = i + 1; j < n; j++ ) 
        { 
            float Ej = (float) fabs( E[j] ); 
 
            m = (Em < Ej) ? j : m; 
            Em = (Em < Ej) ? Ej : Em; 
        } 
        if( m != i ) 
        { 
            int l; 
            float b = E[i]; 
 
            E[i] = E[m]; 
            E[m] = b; 
            for( j = 0, k = i * n, l = m * n; j < n; j++, k++, l++ ) 
            { 
                b = V[k]; 
                V[k] = V[l]; 
                V[l] = b; 
            } 
        } 
    } 
 
    return CV_NO_ERR; 
} 
 
/*=========================== Double precision function ================================*/ 
 
CvStatus CV_STDCALL icvJacobiEigens_64d(double *A, double *V, double *E, int n, double eps) 
{ 
    int i, j, k, p, q, ind, iters = 0; 
    double *A1 = A, *V1 = V, *A2 = A, *V2 = V; 
    double Amax = 0.0, anorm = 0.0, ax; 
 
    if( A == NULL || V == NULL || E == NULL ) 
        return CV_NULLPTR_ERR; 
    if( n <= 0 ) 
        return CV_BADSIZE_ERR; 
    if( eps < DBL_EPSILON ) 
        eps = DBL_EPSILON; 
 
    /*-------- Prepare --------*/ 
    for( i = 0; i < n; i++, V1 += n, A1 += n ) 
    { 
        for( j = 0; j < i; j++ ) 
        { 
            double Am = A1[j]; 
 
            anorm += Am * Am; 
        } 
        for( j = 0; j < n; j++ ) 
            V1[j] = 0.0; 
        V1[i] = 1.0; 
    } 
 
    anorm = sqrt( anorm + anorm ); 
    ax = anorm * eps / n; 
    Amax = anorm; 
 
    while( Amax > ax && iters++ < 100 ) 
    { 
        Amax /= n; 
        do                      /* while (ind) */ 
        { 
            ind = 0; 
            A1 = A; 
            V1 = V; 
            for( p = 0; p < n - 1; p++, A1 += n, V1 += n ) 
            { 
                A2 = A + n * (p + 1); 
                V2 = V + n * (p + 1); 
                for( q = p + 1; q < n; q++, A2 += n, V2 += n ) 
                { 
                    double x, y, c, s, c2, s2, a; 
                    double *A3, Apq, App, Aqq, App2, Aqq2, Aip, Aiq, Vpi, Vqi; 
 
                    if( fabs( A1[q] ) < Amax ) 
                        continue; 
                    Apq = A1[q]; 
 
                    ind = 1; 
 
                    /*---- Calculation of rotation angle's sine & cosine ----*/ 
                    App = A1[p]; 
                    Aqq = A2[q]; 
                    y = 5.0e-1 * (App - Aqq); 
                    x = -Apq / sqrt( Apq * Apq + (double)y * y ); 
                    if( y < 0.0 ) 
                        x = -x; 
                    s = x / sqrt( 2.0 * (1.0 + sqrt( 1.0 - (double)x * x ))); 
                    s2 = s * s; 
                    c = sqrt( 1.0 - s2 ); 
                    c2 = c * c; 
                    a = 2.0 * Apq * c * s; 
 
                    /*---- Apq annulation ----*/ 
                    A3 = A; 
                    for( i = 0; i < p; i++, A3 += n ) 
                    { 
                        Aip = A3[p]; 
                        Aiq = A3[q]; 
                        Vpi = V1[i]; 
                        Vqi = V2[i]; 
                        A3[p] = Aip * c - Aiq * s; 
                        A3[q] = Aiq * c + Aip * s; 
                        V1[i] = Vpi * c - Vqi * s; 
                        V2[i] = Vqi * c + Vpi * s; 
                    } 
                    for( ; i < q; i++, A3 += n ) 
                    { 
                        Aip = A1[i]; 
                        Aiq = A3[q]; 
                        Vpi = V1[i]; 
                        Vqi = V2[i]; 
                        A1[i] = Aip * c - Aiq * s; 
                        A3[q] = Aiq * c + Aip * s; 
                        V1[i] = Vpi * c - Vqi * s; 
                        V2[i] = Vqi * c + Vpi * s; 
                    } 
                    for( ; i < n; i++ ) 
                    { 
                        Aip = A1[i]; 
                        Aiq = A2[i]; 
                        Vpi = V1[i]; 
                        Vqi = V2[i]; 
                        A1[i] = Aip * c - Aiq * s; 
                        A2[i] = Aiq * c + Aip * s; 
                        V1[i] = Vpi * c - Vqi * s; 
                        V2[i] = Vqi * c + Vpi * s; 
                    } 
                    App2 = App * c2 + Aqq * s2 - a; 
                    Aqq2 = App * s2 + Aqq * c2 + a; 
                    A1[p] = App2; 
                    A2[q] = Aqq2; 
                    A1[q] = A2[p] = 0.0; 
                }               /*q */ 
            }                   /*p */ 
        } 
        while( ind ); 
    }                           /* while ( Amax > ax ) */ 
 
    for( i = 0, k = 0; i < n; i++, k += n + 1 ) 
        E[i] = A[k]; 
 
    /* -------- ordering -------- */ 
    for( i = 0; i < n; i++ ) 
    { 
        int m = i; 
        double Em = fabs( E[i] ); 
 
        for( j = i + 1; j < n; j++ ) 
        { 
            double Ej = fabs( E[j] ); 
 
            m = (Em < Ej) ? j : m; 
            Em = (Em < Ej) ? Ej : Em; 
        } 
        if( m != i ) 
        { 
            int l; 
            double b = E[i]; 
 
            E[i] = E[m]; 
            E[m] = b; 
            for( j = 0, k = i * n, l = m * n; j < n; j++, k++, l++ ) 
            { 
                b = V[k]; 
                V[k] = V[l]; 
                V[l] = b; 
            } 
        } 
    } 
 
    return CV_NO_ERR; 
} 
 
#endif 
 
#define ICV_COPY_REPLICATE_BORDER_FUNC( flavor, arrtype, cn )   \ 
IPCVAPI_IMPL( CvStatus,                                         \ 
icvCopyReplicateBorder_##flavor, (                              \ 
    const arrtype *src, int srcstep, CvSize srcroi,             \ 
    arrtype* dst, int dststep, CvSize dstroi, int top, int left ),\ 
    (src, srcstep, srcroi, dst, dststep, dstroi, top, left))    \ 
{                                                               \ 
    int i, j;                                                   \ 
    srcstep /= sizeof(src[0]);                                  \ 
    dststep /= sizeof(dst[0]);                                  \ 
    srcroi.width *= cn;                                         \ 
    dstroi.width *= cn;                                         \ 
    left *= cn;                                                 \ 
                                                                \ 
    for( i = 0; i < dstroi.height; i++, dst += dststep )        \ 
    {                                                           \ 
        memcpy( dst + left, src, srcroi.width*sizeof(src[0]) ); \ 
        for( j = left - 1; j >= 0; j-- )                        \ 
            dst[j] = dst[j + cn];                               \ 
        for( j = left + srcroi.width; j < dstroi.width; j++ )   \ 
            dst[j] = dst[j - cn];                               \ 
        if( i >= top && i < top + srcroi.height - 1 )           \ 
            src += srcstep;                                     \ 
    }                                                           \ 
                                                                \ 
    return CV_OK;                                               \ 
} 
 
 
#define ICV_COPY_CONST_BORDER_FUNC_C1( flavor, arrtype )        \ 
IPCVAPI_IMPL( CvStatus,                                         \ 
icvCopyConstBorder_##flavor, (                                  \ 
    const arrtype *src, int srcstep, CvSize srcroi,             \ 
    arrtype* dst, int dststep, CvSize dstroi,                   \ 
    int top, int left, arrtype value ),                         \ 
    (src, srcstep, srcroi, dst, dststep, dstroi, top, left, value ))\ 
{                                                               \ 
    int i, j;                                                   \ 
    srcstep /= sizeof(src[0]);                                  \ 
    dststep /= sizeof(dst[0]);                                  \ 
                                                                \ 
    for( i = 0; i < dstroi.height; i++, dst += dststep )        \ 
    {                                                           \ 
        if( i == 0 || i == srcroi.height + top )                \ 
        {                                                       \ 
            int limit = i < top || i == srcroi.height + top ?   \ 
                        dstroi.width : left;                    \ 
            for( j = 0; j < limit; j++ )                        \ 
                dst[j] = value;                                 \ 
                                                                \ 
            if( limit == dstroi.width )                         \ 
                continue;                                       \ 
                                                                \ 
            for( j=srcroi.width+left; j < dstroi.width; j++ )   \ 
                dst[j] = value;                                 \ 
        }                                                       \ 
                                                                \ 
        if( i < top || i > srcroi.height + top )                \ 
            memcpy( dst, dst-dststep, dstroi.width*sizeof(dst[0]));\ 
        else                                                    \ 
        {                                                       \ 
            if( i > 0 )                                         \ 
            {                                                   \ 
                for( j = 0; j < left; j++ )                     \ 
                    dst[j] = dst[j - dststep];                  \ 
                for( j = srcroi.width + left; j < dstroi.width; j++ ) \ 
                    dst[j] = dst[j - dststep];                  \ 
            }                                                   \ 
            memcpy( dst, src, srcroi.width*sizeof(dst[0]));     \ 
            src += srcstep;                                     \ 
        }                                                       \ 
    }                                                           \ 
                                                                \ 
    return CV_OK;                                               \ 
} 
 
 
#define ICV_COPY_CONST_BORDER_FUNC_CN( flavor, arrtype, cn )    \ 
IPCVAPI_IMPL( CvStatus,                                         \ 
icvCopyConstBorder_##flavor, (                                  \ 
    const arrtype *src, int srcstep, CvSize srcroi,             \ 
    arrtype* dst, int dststep, CvSize dstroi,                   \ 
    int top, int left, const arrtype* value ),                  \ 
    (src, srcstep, srcroi, dst, dststep, dstroi, top, left, value ))\ 
{                                                               \ 
    int i, j, k;                                                \ 
    srcstep /= sizeof(src[0]);                                  \ 
    dststep /= sizeof(dst[0]);                                  \ 
    srcroi.width *= cn;                                         \ 
    dstroi.width *= cn;                                         \ 
    left *= cn;                                                 \ 
                                                                \ 
    for( i = 0; i < dstroi.height; i++, dst += dststep )        \ 
    {                                                           \ 
        if( i == 0 || i == srcroi.height + top )                \ 
        {                                                       \ 
            int limit = i < top || i == srcroi.height + top ?   \ 
                        dstroi.width : left;                    \ 
            for( j = 0; j < limit; j += cn )                    \ 
                for( k = 0; k < cn; k++ )                       \ 
                    dst[j+k] = value[k];                        \ 
                                                                \ 
            if( limit == dstroi.width )                         \ 
                continue;                                       \ 
                                                                \ 
            for( j=srcroi.width+left; j < dstroi.width; j+=cn ) \ 
                for( k = 0; k < cn; k++ )                       \ 
                    dst[j+k] = value[k];                        \ 
        }                                                       \ 
                                                                \ 
        if( i < top || i > srcroi.height + top )                \ 
            memcpy( dst, dst-dststep, dstroi.width*sizeof(dst[0]));\ 
        else                                                    \ 
        {                                                       \ 
            if( i > 0 )                                         \ 
            {                                                   \ 
                for( j = 0; j < left; j++ )                     \ 
                    dst[j] = dst[j - dststep];                  \ 
                for( j = srcroi.width + left; j < dstroi.width; j++ ) \ 
                    dst[j] = dst[j - dststep];                  \ 
            }                                                   \ 
            memcpy( dst, src, srcroi.width*sizeof(dst[0]));     \ 
            src += srcstep;                                     \ 
        }                                                       \ 
    }                                                           \ 
                                                                \ 
    return CV_OK;                                               \ 
} 
 
 
ICV_COPY_REPLICATE_BORDER_FUNC( 8u_C1R, uchar, 1 )  // 1 
ICV_COPY_REPLICATE_BORDER_FUNC( 16s_C1R, ushort, 1 )// 2 
ICV_COPY_REPLICATE_BORDER_FUNC( 8u_C3R, uchar, 3 )  // 3 
ICV_COPY_REPLICATE_BORDER_FUNC( 32s_C1R, int, 1 )   // 4 
ICV_COPY_REPLICATE_BORDER_FUNC( 16s_C3R, ushort, 3 )// 6 
ICV_COPY_REPLICATE_BORDER_FUNC( 16s_C4R, int, 2 )   // 8 
ICV_COPY_REPLICATE_BORDER_FUNC( 32s_C3R, int, 3 )   // 12 
ICV_COPY_REPLICATE_BORDER_FUNC( 32s_C4R, int, 4 )   // 16 
ICV_COPY_REPLICATE_BORDER_FUNC( 64f_C3R, int, 6 )   // 24 
ICV_COPY_REPLICATE_BORDER_FUNC( 64f_C4R, int, 8 )   // 32 
 
ICV_COPY_CONST_BORDER_FUNC_C1( 8u_C1R, uchar )      // 1 
ICV_COPY_CONST_BORDER_FUNC_C1( 16s_C1R, ushort )    // 2 
ICV_COPY_CONST_BORDER_FUNC_C1( 32s_C1R, int )       // 4 
 
ICV_COPY_CONST_BORDER_FUNC_CN( 8u_C3R, uchar, 3 )   // 3 
ICV_COPY_CONST_BORDER_FUNC_CN( 16s_C3R, ushort, 3 ) // 6 
ICV_COPY_CONST_BORDER_FUNC_CN( 16s_C4R, int, 2 )    // 8 
ICV_COPY_CONST_BORDER_FUNC_CN( 32s_C3R, int, 3 )    // 12 
ICV_COPY_CONST_BORDER_FUNC_CN( 32s_C4R, int, 4 )    // 16 
ICV_COPY_CONST_BORDER_FUNC_CN( 64f_C3R, int, 6 )    // 24 
ICV_COPY_CONST_BORDER_FUNC_CN( 64f_C4R, int, 8 )    // 32 
 
 
CvCopyNonConstBorderFunc icvGetCopyNonConstBorderFunc( int pix_size, int /*bordertype*/ ) 
{ 
    CvBtFuncTable borderrepl_tab; 
    int initflag = 0; 
 
    assert( (unsigned)pix_size <= 4*sizeof(double) ); 
 
    if( !initflag ) 
    { 
        borderrepl_tab.fn_2d[1] = (void*)icvCopyReplicateBorder_8u_C1R; 
        borderrepl_tab.fn_2d[2] = (void*)icvCopyReplicateBorder_16s_C1R; 
        borderrepl_tab.fn_2d[3] = (void*)icvCopyReplicateBorder_8u_C3R; 
        borderrepl_tab.fn_2d[4] = (void*)icvCopyReplicateBorder_32s_C1R; 
        borderrepl_tab.fn_2d[6] = (void*)icvCopyReplicateBorder_16s_C3R; 
        borderrepl_tab.fn_2d[8] = (void*)icvCopyReplicateBorder_16s_C4R; 
        borderrepl_tab.fn_2d[12] = (void*)icvCopyReplicateBorder_32s_C3R; 
        borderrepl_tab.fn_2d[16] = (void*)icvCopyReplicateBorder_32s_C4R; 
        borderrepl_tab.fn_2d[24] = (void*)icvCopyReplicateBorder_64f_C3R; 
        borderrepl_tab.fn_2d[32] = (void*)icvCopyReplicateBorder_64f_C4R; 
        initflag = 1; 
    } 
 
    return (CvCopyNonConstBorderFunc)borderrepl_tab.fn_2d[pix_size]; 
} 
 
 
CvCopyConstBorderFunc_Cn icvGetCopyConstBorderFunc_Cn( int pix_size ) 
{ 
    CvBtFuncTable borderconst_tab; 
    int initflag = 0; 
 
    assert( (unsigned)pix_size <= 4*sizeof(double) ); 
 
    if( !initflag ) 
    { 
        borderconst_tab.fn_2d[1] = 0; // manual handling 
        borderconst_tab.fn_2d[2] = 0; // manual handling 
        borderconst_tab.fn_2d[3] = (void*)icvCopyConstBorder_8u_C3R; 
        borderconst_tab.fn_2d[4] = 0; // manual handling 
        borderconst_tab.fn_2d[6] = (void*)icvCopyConstBorder_16s_C3R; 
        borderconst_tab.fn_2d[8] = (void*)icvCopyConstBorder_16s_C4R; 
        borderconst_tab.fn_2d[12] = (void*)icvCopyConstBorder_32s_C3R; 
        borderconst_tab.fn_2d[16] = (void*)icvCopyConstBorder_32s_C4R; 
        borderconst_tab.fn_2d[24] = (void*)icvCopyConstBorder_64f_C3R; 
        borderconst_tab.fn_2d[32] = (void*)icvCopyConstBorder_64f_C4R; 
        initflag = 1; 
    } 
 
    return (CvCopyConstBorderFunc_Cn)borderconst_tab.fn_2d[pix_size]; 
} 
 
 
CV_IMPL void 
cvCopyMakeBorder( const CvArr* srcarr, CvArr* dstarr, CvPoint offset, 
                  int bordertype, CvScalar value ) 
{ 
    CV_FUNCNAME( "cvCopyMakeBorder" ); 
 
    __BEGIN__; 
 
    CvMat srcstub, *src = (CvMat*)srcarr; 
    CvMat dststub, *dst = (CvMat*)dstarr; 
    CvSize srcsize, dstsize; 
    int srcstep, dststep; 
    int pix_size, type; 
 
    if( !CV_IS_MAT(src) ) 
        CV_CALL( src = cvGetMat( src, &srcstub )); 
     
    if( !CV_IS_MAT(dst) )     
        CV_CALL( dst = cvGetMat( dst, &dststub )); 
 
    if( offset.x < 0 || offset.y < 0 ) 
        CV_ERROR( CV_StsOutOfRange, "Offset (left/top border width) is negative" ); 
 
    if( src->rows + offset.y > dst->rows || src->cols + offset.x > dst->cols ) 
        CV_ERROR( CV_StsBadSize, "Source array is too big or destination array is too small" ); 
 
    if( !CV_ARE_TYPES_EQ( src, dst )) 
        CV_ERROR( CV_StsUnmatchedFormats, "" ); 
 
    type = CV_MAT_TYPE(src->type); 
    pix_size = CV_ELEM_SIZE(type); 
    srcsize = cvGetMatSize(src); 
    dstsize = cvGetMatSize(dst); 
    srcstep = src->step; 
    dststep = dst->step; 
    if( srcstep == 0 ) 
        srcstep = CV_STUB_STEP; 
    if( dststep == 0 ) 
        dststep = CV_STUB_STEP; 
 
    if( bordertype == IPL_BORDER_REPLICATE ) 
    { 
        CvCopyNonConstBorderFunc func = 
            icvGetCopyNonConstBorderFunc( pix_size, IPL_BORDER_REPLICATE ); 
        if( !func ) 
            CV_ERROR( CV_StsUnsupportedFormat, "" ); 
 
        IPPI_CALL( func( src->data.ptr, srcstep, srcsize, 
                         dst->data.ptr, dststep, dstsize, 
                         offset.y, offset.x )); 
    } 
    else if( bordertype == IPL_BORDER_CONSTANT ) 
    { 
        double buf[4]; 
        cvScalarToRawData( &value, buf, src->type, 0 ); 
 
        if( pix_size == 1 ) 
        { 
            IPPI_CALL( icvCopyConstBorder_8u_C1R( src->data.ptr, srcstep, srcsize, 
                                                  dst->data.ptr, dststep, dstsize, 
                                                  offset.y, offset.x, ((uchar*)buf)[0] )); 
        } 
        else if( pix_size == 2 ) 
        { 
            IPPI_CALL( icvCopyConstBorder_16s_C1R( (ushort*)src->data.ptr, srcstep, srcsize, 
                                                   (ushort*)dst->data.ptr, dststep, dstsize, 
                                                   offset.y, offset.x, ((ushort*)buf)[0] )); 
        } 
        else if( pix_size == 4 ) 
        { 
            IPPI_CALL( icvCopyConstBorder_32s_C1R( src->data.i, srcstep, srcsize, 
                                                   dst->data.i, dststep, dstsize, 
                                                   offset.y, offset.x, ((int*)buf)[0] )); 
        } 
        else 
        { 
            CvCopyConstBorderFunc_Cn func = 
                icvGetCopyConstBorderFunc_Cn( pix_size ); 
            if( !func ) 
                CV_ERROR( CV_StsUnsupportedFormat, "" ); 
 
            IPPI_CALL( func( src->data.ptr, srcstep, srcsize, 
                             dst->data.ptr, dststep, dstsize, 
                             offset.y, offset.x, buf )); 
        } 
    } 
    else 
        CV_ERROR( CV_StsBadFlag, "Unknown/unsupported border type" ); 
     
    __END__; 
} 
 
/* End of file. */