www.pudn.com > OpenCV-Intel.zip > cvmorph.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" 
#include  
#include  
 
#define IPCV_MORPHOLOGY_PTRS( morphtype, flavor )                                   \ 
icv##morphtype##Rect_##flavor##_C1R_t icv##morphtype##Rect_##flavor##_C1R_p = 0;    \ 
icv##morphtype##Rect_##flavor##_C3R_t icv##morphtype##Rect_##flavor##_C3R_p = 0;    \ 
icv##morphtype##Rect_##flavor##_C4R_t icv##morphtype##Rect_##flavor##_C4R_p = 0;    \ 
icv##morphtype##Any_##flavor##_C1R_t icv##morphtype##Any_##flavor##_C1R_p = 0;      \ 
icv##morphtype##Any_##flavor##_C3R_t icv##morphtype##Any_##flavor##_C3R_p = 0;      \ 
icv##morphtype##Any_##flavor##_C4R_t icv##morphtype##Any_##flavor##_C4R_p = 0; 
 
IPCV_MORPHOLOGY_PTRS( Erode, 8u ) 
IPCV_MORPHOLOGY_PTRS( Erode, 32f ) 
IPCV_MORPHOLOGY_PTRS( Dilate, 8u ) 
IPCV_MORPHOLOGY_PTRS( Dilate, 32f ) 
 
 
static CvFilterState* CV_STDCALL 
icvMorphologyInitAlloc( int roiWidth, CvDataType dataType, int channels, 
                        CvSize elSize, CvPoint elAnchor, int elShape, int* elData ) 
{ 
    CvFilterState* morphState = 0; 
 
    CV_FUNCNAME( "icvMorphologyInitAlloc" ); 
 
    __BEGIN__; 
     
    switch( elShape ) 
    { 
    case CV_SHAPE_RECT: 
        break; 
    case CV_SHAPE_CROSS: 
    case CV_SHAPE_ELLIPSE: 
    case CV_SHAPE_CUSTOM: 
        if( elData == 0 ) 
            CV_ERROR( CV_StsNullPtr, 
            "For non-rectangular strucuring element coefficient should be specified" ); 
        break; 
    default: 
        CV_ERROR( CV_StsBadFlag, "Unknown/unsupported type of structuring element" ); 
    } 
 
    morphState = icvFilterInitAlloc( roiWidth, dataType, channels, 
        cvSize(elSize.width, elSize.height + (elShape == CV_SHAPE_RECT)), 
        elAnchor, elShape != CV_SHAPE_RECT ? elData : 0, 
        ICV_MAKE_BINARY_KERNEL(elShape) ); 
 
    if( morphState ) 
        morphState->ker_height = elSize.height; 
 
    __END__; 
 
    return morphState; 
} 
 
 
static void CV_STDCALL 
icvMorphologyFree( CvFilterState** morphState ) 
{ 
    icvFilterFree( morphState ); 
} 
 
 
/****************************************************************************************\ 
*                 Erode/Dilate with rectangular element for integer types                * 
\****************************************************************************************/ 
 
#define ICV_DEF_MORPH_RECT_INT_FUNC( name, flavor, arrtype,                 \ 
                                     update_extr_macro )                    \ 
static CvStatus CV_STDCALL                                                  \ 
icv##name##Rect_##flavor( arrtype* src, int srcstep, arrtype* dst, int dststep,\ 
                          CvSize* roi, CvFilterState* state, int /*stage*/ ) \ 
{                                                                           \ 
    int src_height = roi->height;                                           \ 
    int dst_height = src_height;                                            \ 
    int x, y = 0, dy = 0, i;                                                \ 
                                                                            \ 
    int row_count, rows_wanted;                                             \ 
    arrtype** rows = (arrtype**)(state->rows);                              \ 
    arrtype *tbuf = (arrtype*)(state->tbuf), *tdst, *tsrc;                  \ 
                                                                            \ 
    int channels = state->channels;                                         \ 
    int ker_x_n = state->ker_x * channels;                                  \ 
    int ker_width_n = state->ker_width * channels;                          \ 
    int ker_y = state->ker_y;                                               \ 
    int ker_height = state->ker_height;                                     \ 
    int width_n = roi->width * channels;                                    \ 
                                                                            \ 
    /* initialize cyclic buffer when starting */                            \ 
    for( i = 0; i <= ker_height; i++ )                                      \ 
        rows[i] = (arrtype*)(state->buffer + state->buffer_step * i);       \ 
    row_count = 0;                                                          \ 
    rows_wanted = ker_height - ker_y + 1;                                   \ 
                                                                            \ 
    srcstep /= sizeof(src[0]);                                              \ 
    dststep /= sizeof(dst[0]);                                              \ 
                                                                            \ 
    for( y = 0; y < dst_height; y += dy )                                   \ 
    {                                                                       \ 
        int val0, val1, val2, val3, t;                                      \ 
        dy = MIN( dst_height - y, 2 );                                      \ 
                                                                            \ 
        /* fill cyclic buffer - apply horizontal filter */                  \ 
        for( ; row_count < rows_wanted; row_count++, src += srcstep )       \ 
        {                                                                   \ 
            tdst = rows[row_count];                                         \ 
            if( ker_height == 1 )                                           \ 
            {                                                               \ 
                tdst = dst;                                                 \ 
                dst += dststep;                                             \ 
            }                                                               \ 
                                                                            \ 
            if( src_height-- <= 0 )                                         \ 
                break;                                                      \ 
                                                                            \ 
            if( ker_width_n == channels )                                   \ 
            {                                                               \ 
                CV_COPY( tdst, src, width_n, x );                           \ 
                continue;                                                   \ 
            }                                                               \ 
                                                                            \ 
            CV_COPY( tbuf + ker_x_n, src, width_n, x );                     \ 
                                                                            \ 
            /* make replication borders */                                  \ 
            for( i = ker_x_n - 1; i >= 0; i-- )                             \ 
                tbuf[i] = tbuf[i + channels];                               \ 
            for( i = width_n + ker_x_n; i < width_n + ker_width_n; i++ )    \ 
                tbuf[i] = tbuf[i - channels];                               \ 
                                                                            \ 
            /* row processing */                                            \ 
            if( channels == 1 )                                             \ 
            {                                                               \ 
                for( x = 0; x <= width_n - 2; x += 2 )                      \ 
                {                                                           \ 
                    tsrc = tbuf + x;                                        \ 
                    val0 = tsrc[1];                                         \ 
                                                                            \ 
                    for( i = 2; i < ker_width_n; i++ )                      \ 
                    {                                                       \ 
                        t = tsrc[i]; update_extr_macro( val0, t );          \ 
                    }                                                       \ 
                    t = tsrc[0]; update_extr_macro( t, val0 ); tdst[x] = (arrtype)t;\ 
                    t = tsrc[i]; update_extr_macro( t, val0 ); tdst[x+1] = (arrtype)t;\ 
                }                                                           \ 
            }                                                               \ 
            else if( channels == 3 )                                        \ 
            {                                                               \ 
                for( x = 0; x <= width_n - 6; x += 6 )                      \ 
                {                                                           \ 
                    tsrc = tbuf + x;                                        \ 
                    val0 = tsrc[3]; val1 = tsrc[4]; val2 = tsrc[5];         \ 
                                                                            \ 
                    for( i = 6; i < ker_width_n; i += 3 )                   \ 
                    {                                                       \ 
                        t = tsrc[i]; update_extr_macro( val0, t );          \ 
                        t = tsrc[i+1]; update_extr_macro( val1, t );        \ 
                        t = tsrc[i+2]; update_extr_macro( val2, t );        \ 
                    }                                                       \ 
                    t = tsrc[0]; update_extr_macro( t, val0 ); tdst[x] = (arrtype)t;\ 
                    t = tsrc[i]; update_extr_macro( t, val0 ); tdst[x+3] = (arrtype)t;\ 
                                                                            \ 
                    t = tsrc[1]; update_extr_macro( t, val1 ); tdst[x+1] = (arrtype)t;\ 
                    t = tsrc[i+1]; update_extr_macro( t, val1 ); tdst[x+4] = (arrtype)t;\ 
                                                                            \ 
                    t = tsrc[2]; update_extr_macro( t, val2 ); tdst[x+2] = (arrtype)t;\ 
                    t = tsrc[i+2]; update_extr_macro( t, val2 ); tdst[x+5] = (arrtype)t;\ 
                }                                                           \ 
            }                                                               \ 
            else                                                            \ 
            {                                                               \ 
                assert( channels == 4 );                                    \ 
                for( x = 0; x <= width_n - 8; x += 8 )                      \ 
                {                                                           \ 
                    tsrc = tbuf + x;                                        \ 
                    val0 = tsrc[4]; val1 = tsrc[5];                         \ 
                    val2 = tsrc[6]; val3 = tsrc[7];                         \ 
                                                                            \ 
                    for( i = 8; i < ker_width_n; i += 4 )                   \ 
                    {                                                       \ 
                        t = tsrc[i]; update_extr_macro( val0, t );          \ 
                        t = tsrc[i+1]; update_extr_macro( val1, t );        \ 
                        t = tsrc[i+2]; update_extr_macro( val2, t );        \ 
                        t = tsrc[i+3]; update_extr_macro( val3, t );        \ 
                    }                                                       \ 
                    t = tsrc[0]; update_extr_macro( t, val0 ); tdst[x] = (arrtype)t;\ 
                    t = tsrc[i]; update_extr_macro( t, val0 ); tdst[x+4] = (arrtype)t;\ 
                                                                            \ 
                    t = tsrc[1]; update_extr_macro( t, val1 ); tdst[x+1] = (arrtype)t;\ 
                    t = tsrc[i+1]; update_extr_macro( t, val1 ); tdst[x+5] = (arrtype)t;\ 
                                                                            \ 
                    t = tsrc[2]; update_extr_macro( t, val2 ); tdst[x+2] = (arrtype)t;\ 
                    t = tsrc[i+2]; update_extr_macro( t, val2 ); tdst[x+6] = (arrtype)t;\ 
                                                                            \ 
                    t = tsrc[3]; update_extr_macro( t, val3 ); tdst[x+3] = (arrtype)t;\ 
                    t = tsrc[i+3]; update_extr_macro( t, val3 ); tdst[x+7] = (arrtype)t;\ 
                }                                                           \ 
            }                                                               \ 
                                                                            \ 
            for( ; x < width_n; x++ )                                       \ 
            {                                                               \ 
                val0 = tbuf[x];                                             \ 
                for( i = channels; i < ker_width_n; i += channels )         \ 
                {                                                           \ 
                    t = tbuf[x + i]; update_extr_macro( val0, t );          \ 
                }                                                           \ 
                tdst[x] = (arrtype)val0;                                    \ 
            }                                                               \ 
        }                                                                   \ 
                                                                            \ 
        /* apply vertical filter */                                         \ 
        if( ker_height == 1 )                                               \ 
        {                                                                   \ 
            row_count -= 2;                                                 \ 
            continue;                                                       \ 
        }                                                                   \ 
                                                                            \ 
        if( dy == 2 )                                                       \ 
        {                                                                   \ 
            int second_row = MIN((int)(y >= ker_y), row_count-1);           \ 
            int last_row = row_count - (src_height >= 0);                   \ 
                                                                            \ 
            for( x = 0; x <= width_n - 4; x += 4, dst += 4 )                \ 
            {                                                               \ 
                tsrc = rows[second_row] + x;                                \ 
                val0 = tsrc[0]; val1 = tsrc[1];                             \ 
                val2 = tsrc[2]; val3 = tsrc[3];                             \ 
                                                                            \ 
                for( i = second_row + 1; i < last_row; i++ )                \ 
                {                                                           \ 
                    tsrc = rows[i] + x;                                     \ 
                    t = tsrc[0]; update_extr_macro(val0, t);                \ 
                    t = tsrc[1]; update_extr_macro(val1, t);                \ 
                    t = tsrc[2]; update_extr_macro(val2, t);                \ 
                    t = tsrc[3]; update_extr_macro(val3, t);                \ 
                }                                                           \ 
                                                                            \ 
                tsrc = rows[0] + x;                                         \ 
                t = tsrc[0]; update_extr_macro(t, val0); dst[0] = (arrtype)t;\ 
                t = tsrc[1]; update_extr_macro(t, val1); dst[1] = (arrtype)t;\ 
                t = tsrc[2]; update_extr_macro(t, val2); dst[2] = (arrtype)t;\ 
                t = tsrc[3]; update_extr_macro(t, val3); dst[3] = (arrtype)t;\ 
                                                                            \ 
                tsrc = rows[row_count - 1] + x;                             \ 
                t = tsrc[0]; update_extr_macro(t, val0); dst[dststep] = (arrtype)t;\ 
                t = tsrc[1]; update_extr_macro(t, val1); dst[dststep+1] = (arrtype)t;\ 
                t = tsrc[2]; update_extr_macro(t, val2); dst[dststep+2] = (arrtype)t;\ 
                t = tsrc[3]; update_extr_macro(t, val3); dst[dststep+3] = (arrtype)t;\ 
            }                                                               \ 
                                                                            \ 
            for( ; x < width_n; x++, dst++ )                                \ 
            {                                                               \ 
                tsrc = rows[second_row] + x;                                \ 
                val0 = tsrc[0];                                             \ 
                                                                            \ 
                for( i = second_row + 1; i < last_row; i++ )                \ 
                {                                                           \ 
                    tsrc = rows[i] + x;                                     \ 
                    t = tsrc[0]; update_extr_macro(val0, t);                \ 
                }                                                           \ 
                                                                            \ 
                tsrc = rows[0] + x;                                         \ 
                t = tsrc[0]; update_extr_macro(t, val0); dst[0] = (arrtype)t;\ 
                tsrc = rows[row_count - 1] + x;                             \ 
                t = tsrc[0]; update_extr_macro(t, val0); dst[dststep] = (arrtype)t;\ 
            }                                                               \ 
            dst -= width_n;                                                 \ 
        }                                                                   \ 
        else                                                                \ 
        {                                                                   \ 
            for( x = 0; x < width_n; x++ )                                  \ 
            {                                                               \ 
                tsrc = rows[0] + x;                                         \ 
                val0 = tsrc[0];                                             \ 
                                                                            \ 
                for( i = 1; i < row_count; i++ )                            \ 
                {                                                           \ 
                    tsrc = rows[i] + x;                                     \ 
                    t = tsrc[0]; update_extr_macro(val0, t);                \ 
                }                                                           \ 
                                                                            \ 
                dst[x] = (arrtype)val0;                                     \ 
            }                                                               \ 
        }                                                                   \ 
                                                                            \ 
        if( y+dy > ker_y && row_count > 1 )                                 \ 
        {                                                                   \ 
            /* rotate buffer */                                             \ 
            int shift = dy - (y < ker_y);                                   \ 
            arrtype* row0 = rows[0];                                        \ 
            arrtype* row1 = rows[1];                                        \ 
            if( row_count <= shift && src_height <= 0 )                     \ 
                shift = 1;                                                  \ 
                                                                            \ 
            CV_COPY( rows, rows + shift, ker_height + 1 - shift, i );       \ 
                                                                            \ 
            if( shift == 2 )                                                \ 
            {                                                               \ 
                rows[ker_height - 1] = row0;                                \ 
                rows[ker_height] = row1;                                    \ 
            }                                                               \ 
            else                                                            \ 
                rows[ker_height] = row0;                                    \ 
            row_count -= shift;                                             \ 
        }                                                                   \ 
                                                                            \ 
        rows_wanted = MIN(rows_wanted + 2, ker_height + 1);                 \ 
        dst += dststep*dy;                                                  \ 
    }                                                                       \ 
                                                                            \ 
    return CV_OK;                                                           \ 
} 
 
 
/****************************************************************************************\ 
*                    Erode/Dilate with rectangular element for 32f type                  * 
\****************************************************************************************/ 
 
#define ICV_DEF_MORPH_RECT_FLT_FUNC( name, update_extr_macro )              \ 
static CvStatus CV_STDCALL                                                  \ 
icv##name##Rect_32f( int* src, int srcstep, int* dst, int dststep,          \ 
                     CvSize* roi, CvFilterState* state, int /*stage*/ )      \ 
{                                                                           \ 
    int src_height = roi->height;                                           \ 
    int dst_height = src_height;                                            \ 
    int x, y = 0, dy = 0, i;                                                \ 
                                                                            \ 
    int row_count, rows_wanted;                                             \ 
    int** rows = (int**)(state->rows);                                      \ 
    int *tbuf = (int*)(state->tbuf), *tdst, *tsrc;                          \ 
                                                                            \ 
    int channels = state->channels;                                         \ 
    int ker_x_n = state->ker_x * channels;                                  \ 
    int ker_width_n = state->ker_width * channels;                          \ 
    int ker_y = state->ker_y;                                               \ 
    int ker_height = state->ker_height;                                     \ 
    int width_n = roi->width * channels;                                    \ 
                                                                            \ 
    /* initialize cyclic buffer when starting */                            \ 
    for( i = 0; i <= ker_height; i++ )                                      \ 
        rows[i] = (int*)(state->buffer + state->buffer_step * i);           \ 
    row_count = 0;                                                          \ 
    rows_wanted = ker_height - ker_y + 1;                                   \ 
                                                                            \ 
    srcstep /= sizeof(src[0]);                                              \ 
    dststep /= sizeof(dst[0]);                                              \ 
                                                                            \ 
    for( y = 0; y < dst_height; y += dy )                                   \ 
    {                                                                       \ 
        int val0, val1, val2, val3, t;                                      \ 
        dy = MIN( dst_height - y, 2 );                                      \ 
                                                                            \ 
        /* fill cyclic buffer - apply horizontal filter */                  \ 
        for( ; row_count < rows_wanted; row_count++, src += srcstep )       \ 
        {                                                                   \ 
            tdst = rows[row_count];                                         \ 
            if( ker_height == 1 )                                           \ 
            {                                                               \ 
                tdst = dst;                                                 \ 
                dst += dststep;                                             \ 
            }                                                               \ 
                                                                            \ 
            if( src_height-- <= 0 )                                         \ 
                break;                                                      \ 
                                                                            \ 
            if( ker_width_n == channels )                                   \ 
            {                                                               \ 
                if( ker_height == 1 )                                       \ 
                {                                                           \ 
                    CV_COPY( tdst, src, width_n, x );                       \ 
                }                                                           \ 
                else                                                        \ 
                {                                                           \ 
                    for( x = 0; x < width_n; x++ )                          \ 
                        t = src[x], tdst[x] = CV_TOGGLE_FLT(t);             \ 
                }                                                           \ 
                continue;                                                   \ 
            }                                                               \ 
                                                                            \ 
            for( x = 0; x < width_n; x++ )                                  \ 
            {                                                               \ 
                t = src[x];                                                 \ 
                tbuf[ker_x_n + x] = CV_TOGGLE_FLT(t);                       \ 
            }                                                               \ 
                                                                            \ 
            /* make replication borders */                                  \ 
            for( i = ker_x_n - 1; i >= 0; i-- )                             \ 
                tbuf[i] = tbuf[i + channels];                               \ 
            for( i = width_n + ker_x_n; i < width_n + ker_width_n; i++ )    \ 
                tbuf[i] = tbuf[i - channels];                               \ 
                                                                            \ 
            /* row processing */                                            \ 
            if( channels == 1 )                                             \ 
            {                                                               \ 
                for( x = 0; x <= width_n - 2; x += 2 )                      \ 
                {                                                           \ 
                    tsrc = tbuf + x;                                        \ 
                    val0 = tsrc[1];                                         \ 
                                                                            \ 
                    for( i = 2; i < ker_width_n; i++ )                      \ 
                    {                                                       \ 
                        t = tsrc[i]; update_extr_macro( val0, t );          \ 
                    }                                                       \ 
                    t = tsrc[0]; update_extr_macro( t, val0 ); tdst[x] = t; \ 
                    t = tsrc[i]; update_extr_macro( t, val0 ); tdst[x+1]= t;\ 
                }                                                           \ 
            }                                                               \ 
            else if( channels == 3 )                                        \ 
            {                                                               \ 
                for( x = 0; x <= width_n - 6; x += 6 )                      \ 
                {                                                           \ 
                    tsrc = tbuf + x;                                        \ 
                    val0 = tsrc[3]; val1 = tsrc[4]; val2 = tsrc[5];         \ 
                                                                            \ 
                    for( i = 6; i < ker_width_n; i += 3 )                   \ 
                    {                                                       \ 
                        t = tsrc[i]; update_extr_macro( val0, t );          \ 
                        t = tsrc[i+1]; update_extr_macro( val1, t );        \ 
                        t = tsrc[i+2]; update_extr_macro( val2, t );        \ 
                    }                                                       \ 
                    t = tsrc[0]; update_extr_macro( t, val0 ); tdst[x] = t; \ 
                    t = tsrc[i]; update_extr_macro( t, val0 ); tdst[x+3] = t;\ 
                                                                            \ 
                    t = tsrc[1]; update_extr_macro( t, val1 ); tdst[x+1] = t;\ 
                    t = tsrc[i+1]; update_extr_macro( t, val1 ); tdst[x+4] = t;\ 
                                                                            \ 
                    t = tsrc[2]; update_extr_macro( t, val2 ); tdst[x+2] = t;\ 
                    t = tsrc[i+2]; update_extr_macro( t, val2 ); tdst[x+5] = t;\ 
                }                                                           \ 
            }                                                               \ 
            else                                                            \ 
            {                                                               \ 
                assert( channels == 4 );                                    \ 
                for( x = 0; x <= width_n - 8; x += 8 )                      \ 
                {                                                           \ 
                    tsrc = tbuf + x;                                        \ 
                    val0 = tsrc[4]; val1 = tsrc[5];                         \ 
                    val2 = tsrc[6]; val3 = tsrc[7];                         \ 
                                                                            \ 
                    for( i = 8; i < ker_width_n; i += 4 )                   \ 
                    {                                                       \ 
                        t = tsrc[i]; update_extr_macro( val0, t );          \ 
                        t = tsrc[i+1]; update_extr_macro( val1, t );        \ 
                        t = tsrc[i+2]; update_extr_macro( val2, t );        \ 
                        t = tsrc[i+3]; update_extr_macro( val3, t );        \ 
                    }                                                       \ 
                    t = tsrc[0]; update_extr_macro( t, val0 ); tdst[x] = t; \ 
                    t = tsrc[i]; update_extr_macro( t, val0 ); tdst[x+4] = t;\ 
                                                                            \ 
                    t = tsrc[1]; update_extr_macro( t, val1 ); tdst[x+1] = t;\ 
                    t = tsrc[i+1]; update_extr_macro( t, val1 ); tdst[x+5] = t;\ 
                                                                            \ 
                    t = tsrc[2]; update_extr_macro( t, val2 ); tdst[x+2] = t;\ 
                    t = tsrc[i+2]; update_extr_macro( t, val2 ); tdst[x+6] = t;\ 
                                                                            \ 
                    t = tsrc[3]; update_extr_macro( t, val3 ); tdst[x+3] = t;\ 
                    t = tsrc[i+3]; update_extr_macro( t, val3 ); tdst[x+7] = t;\ 
                }                                                           \ 
            }                                                               \ 
                                                                            \ 
            for( ; x < width_n; x++ )                                       \ 
            {                                                               \ 
                val0 = tbuf[x];                                             \ 
                for( i = channels; i < ker_width_n; i += channels )         \ 
                {                                                           \ 
                    t = tbuf[x + i]; update_extr_macro( val0, t );          \ 
                }                                                           \ 
                tdst[x] = val0;                                             \ 
            }                                                               \ 
                                                                            \ 
            if( ker_height == 1 )                                           \ 
            {                                                               \ 
                for( x = 0; x < width_n; x++ )                              \ 
                    t = tdst[x], tdst[x] = CV_TOGGLE_FLT(t);                \ 
            }                                                               \ 
        }                                                                   \ 
                                                                            \ 
        /* apply vertical filter */                                         \ 
        if( ker_height == 1 )                                               \ 
        {                                                                   \ 
            row_count -= 2;                                                 \ 
            continue;                                                       \ 
        }                                                                   \ 
                                                                            \ 
        if( dy == 2 )                                                       \ 
        {                                                                   \ 
            int second_row = MIN((int)(y >= ker_y), row_count-1);           \ 
            int last_row = row_count - (src_height >= 0);                   \ 
                                                                            \ 
            for( x = 0; x <= width_n - 4; x += 4, dst += 4 )                \ 
            {                                                               \ 
                tsrc = rows[second_row] + x;                                \ 
                val0 = tsrc[0]; val1 = tsrc[1];                             \ 
                val2 = tsrc[2]; val3 = tsrc[3];                             \ 
                                                                            \ 
                for( i = second_row + 1; i < last_row; i++ )                \ 
                {                                                           \ 
                    tsrc = rows[i] + x;                                     \ 
                    t = tsrc[0]; update_extr_macro(val0, t);                \ 
                    t = tsrc[1]; update_extr_macro(val1, t);                \ 
                    t = tsrc[2]; update_extr_macro(val2, t);                \ 
                    t = tsrc[3]; update_extr_macro(val3, t);                \ 
                }                                                           \ 
                                                                            \ 
                tsrc = rows[0] + x;                                         \ 
                t = tsrc[0]; update_extr_macro(t, val0); dst[0] = CV_TOGGLE_FLT(t);\ 
                t = tsrc[1]; update_extr_macro(t, val1); dst[1] = CV_TOGGLE_FLT(t);\ 
                t = tsrc[2]; update_extr_macro(t, val2); dst[2] = CV_TOGGLE_FLT(t);\ 
                t = tsrc[3]; update_extr_macro(t, val3); dst[3] = CV_TOGGLE_FLT(t);\ 
                                                                            \ 
                tsrc = rows[row_count - 1] + x;                             \ 
                t = tsrc[0]; update_extr_macro(t, val0); dst[dststep] = CV_TOGGLE_FLT(t);\ 
                t = tsrc[1]; update_extr_macro(t, val1); dst[dststep+1] = CV_TOGGLE_FLT(t);\ 
                t = tsrc[2]; update_extr_macro(t, val2); dst[dststep+2] = CV_TOGGLE_FLT(t);\ 
                t = tsrc[3]; update_extr_macro(t, val3); dst[dststep+3] = CV_TOGGLE_FLT(t);\ 
            }                                                               \ 
                                                                            \ 
            for( ; x < width_n; x++, dst++ )                                \ 
            {                                                               \ 
                tsrc = rows[second_row] + x;                                \ 
                val0 = tsrc[0];                                             \ 
                                                                            \ 
                for( i = second_row + 1; i < last_row; i++ )                \ 
                {                                                           \ 
                    tsrc = rows[i] + x;                                     \ 
                    t = tsrc[0]; update_extr_macro(val0, t);                \ 
                }                                                           \ 
                                                                            \ 
                tsrc = rows[0] + x;                                         \ 
                t = tsrc[0]; update_extr_macro(t, val0); dst[0] = CV_TOGGLE_FLT(t);\ 
                tsrc = rows[row_count - 1] + x;                             \ 
                t = tsrc[0]; update_extr_macro(t, val0); dst[dststep] = CV_TOGGLE_FLT(t);\ 
            }                                                               \ 
            dst -= width_n;                                                 \ 
        }                                                                   \ 
        else                                                                \ 
        {                                                                   \ 
            for( x = 0; x < width_n; x++ )                                  \ 
            {                                                               \ 
                tsrc = rows[0] + x;                                         \ 
                val0 = tsrc[0];                                             \ 
                                                                            \ 
                for( i = 1; i < row_count; i++ )                            \ 
                {                                                           \ 
                    tsrc = rows[i] + x;                                     \ 
                    t = tsrc[0]; update_extr_macro(val0, t);                \ 
                }                                                           \ 
                                                                            \ 
                dst[x] = CV_TOGGLE_FLT(val0);                               \ 
            }                                                               \ 
        }                                                                   \ 
                                                                            \ 
        if( y+dy > ker_y && row_count > 1 )                                 \ 
        {                                                                   \ 
            /* rotate buffer */                                             \ 
            int shift = dy - (y < ker_y);                                   \ 
            int* row0 = rows[0];                                            \ 
            int* row1 = rows[1];                                            \ 
            if( row_count <= shift && src_height <= 0 )                     \ 
                shift = 1;                                                  \ 
                                                                            \ 
            CV_COPY( rows, rows + shift, ker_height + 1 - shift, i );       \ 
                                                                            \ 
            if( shift == 2 )                                                \ 
            {                                                               \ 
                rows[ker_height - 1] = row0;                                \ 
                rows[ker_height] = row1;                                    \ 
            }                                                               \ 
            else                                                            \ 
                rows[ker_height] = row0;                                    \ 
            row_count -= shift;                                             \ 
        }                                                                   \ 
                                                                            \ 
        rows_wanted = MIN(rows_wanted + 2, ker_height + 1);                 \ 
        dst += dststep*dy;                                                  \ 
    }                                                                       \ 
                                                                            \ 
    return CV_OK;                                                           \ 
} 
 
 
/****************************************************************************************\ 
*                 Erode/Dilate with arbitrary element and arbitrary type                 * 
\****************************************************************************************/ 
 
#define ICV_DEF_MORPH_ARB_FUNC( name, flavor, arrtype,                      \ 
                                update_extr_macro, toggle_macro )           \ 
static CvStatus CV_STDCALL                                                  \ 
icv##name##Any_##flavor( arrtype* src, int srcstep,                         \ 
                         arrtype* dst, int dststep,                         \ 
                         CvSize* roi, CvFilterState* state, int stage )      \ 
{                                                                           \ 
    int width = roi->width;                                                 \ 
    int src_height = roi->height;                                           \ 
    int dst_height = src_height;                                            \ 
    int x, y = 0, i;                                                        \ 
                                                                            \ 
    int ker_x = state->ker_x;                                               \ 
    int ker_y = state->ker_y;                                               \ 
    int ker_width = state->ker_width;                                       \ 
    int ker_height = state->ker_height;                                     \ 
    uchar *ker_data = state->ker0;                                          \ 
                                                                            \ 
    int crows = state->crows;                                               \ 
    arrtype **rows = (arrtype **) (state->rows);                            \ 
    arrtype *tbuf = (arrtype *) (state->tbuf);                              \ 
                                                                            \ 
    int channels = state->channels;                                         \ 
    int ker_x_n = ker_x * channels;                                         \ 
    int ker_width_n = ker_width * channels;                                 \ 
    int width_n = width * channels;                                         \ 
                                                                            \ 
    int starting_flag = 0;                                                  \ 
    int width_rest = width_n & (CV_MORPH_ALIGN - 1);                        \ 
    arrtype **ker_ptr, **ker = (arrtype**)cvStackAlloc(                     \ 
        ker_width*ker_height*sizeof(ker[0]) );                              \ 
                                                                            \ 
    srcstep /= sizeof(src[0]);                                              \ 
    dststep /= sizeof(dst[0]);                                              \ 
                                                                            \ 
    if( stage == CV_START + CV_END )                                        \ 
        stage = CV_WHOLE;                                                   \ 
                                                                            \ 
    /* initialize cyclic buffer when starting */                            \ 
    if( stage == CV_WHOLE || stage == CV_START )                            \ 
    {                                                                       \ 
        for( i = 0; i < ker_height; i++ )                                   \ 
            rows[i] = (arrtype *) (state->buffer + state->buffer_step * i); \ 
        crows = ker_y;                                                      \ 
        if( stage != CV_WHOLE )                                             \ 
            dst_height -= ker_height - ker_y - 1;                           \ 
        starting_flag = 1;                                                  \ 
    }                                                                       \ 
                                                                            \ 
    if( stage == CV_END )                                                   \ 
        dst_height += ker_height - ker_y - 1;                               \ 
                                                                            \ 
    do                                                                      \ 
    {                                                                       \ 
        arrtype *tsrc, *tdst;                                               \ 
        int need_copy = 0;                                                  \ 
                                                                            \ 
        /* fill cyclic buffer - horizontal filtering */                     \ 
        for( ; crows < ker_height; crows++ )                                \ 
        {                                                                   \ 
            tsrc = src;                                                     \ 
            tdst = rows[crows];                                             \ 
                                                                            \ 
            if( src_height-- <= 0 )                                         \ 
            {                                                               \ 
                if( stage != CV_WHOLE && stage != CV_END )                  \ 
                    break;                                                  \ 
                /* duplicate last row */                                    \ 
                tsrc = rows[crows - 1];                                     \ 
                CV_COPY( tdst, tsrc, width_n + ker_width_n, x );            \ 
                continue;                                                   \ 
            }                                                               \ 
                                                                            \ 
            src += srcstep;                                                 \ 
            for( x = 0; x < width_n; x++ )                                  \ 
            {                                                               \ 
                arrtype t = tsrc[x];                                        \ 
                tdst[ker_x_n + x] = toggle_macro(t);                        \ 
            }                                                               \ 
                                                                            \ 
            /* make replication borders */                                  \ 
            for( i = ker_x_n - 1; i >= 0; i-- )                             \ 
                tdst[i] = tdst[i + channels];                               \ 
            for( i = width_n + ker_x_n; i < width_n + ker_width_n; i++ )    \ 
                tdst[i] = tdst[i - channels];                               \ 
        }                                                                   \ 
                                                                            \ 
        if( starting_flag )                                                 \ 
        {                                                                   \ 
            starting_flag = 0;                                              \ 
            tsrc = rows[ker_y];                                             \ 
                                                                            \ 
            for( i = 0; i < ker_y; i++ )                                    \ 
            {                                                               \ 
                tdst = rows[i];                                             \ 
                CV_COPY( tdst, tsrc, width_n + ker_width_n, x );            \ 
            }                                                               \ 
        }                                                                   \ 
                                                                            \ 
        if( crows < ker_height )                                            \ 
            break;                                                          \ 
                                                                            \ 
        tdst = dst;                                                         \ 
        if( width_rest )                                                    \ 
        {                                                                   \ 
            need_copy = width_n < CV_MORPH_ALIGN || y == dst_height - 1;    \ 
                                                                            \ 
            if( need_copy )                                                 \ 
                tdst = tbuf;                                                \ 
            else                                                            \ 
                CV_COPY( tbuf + width_n, dst + width_n, CV_MORPH_ALIGN, x );\ 
        }                                                                   \ 
                                                                            \ 
        ker_ptr = ker;                                                      \ 
        for( i = 0; i < ker_height; i++ )                                   \ 
            for( x = 0; x < ker_width; x++ )                                \ 
            {                                                               \ 
                if( ker_data[i*ker_width + x] )                             \ 
                    *ker_ptr++ = rows[i] + x*channels;                      \ 
            }                                                               \ 
        if( ker_ptr == ker )                                                \ 
            *ker_ptr++ = rows[ker_y] + ker_x_n;                             \ 
                                                                            \ 
        if( channels == 3 )                                                 \ 
            for( x = 0; x < width_n; x += 3 )                               \ 
            {                                                               \ 
                arrtype** kp = ker;                                         \ 
                arrtype* tp = *kp++;                                        \ 
                int t, val0 = tp[x], val1 = tp[x+1], val2 = tp[x+2];        \ 
                                                                            \ 
                while( kp != ker_ptr )                                      \ 
                {                                                           \ 
                    tp = *kp++;                                             \ 
                    t = tp[x]; update_extr_macro( val0, t );                \ 
                    t = tp[x + 1]; update_extr_macro( val1, t );            \ 
                    t = tp[x + 2]; update_extr_macro( val2, t );            \ 
                }                                                           \ 
                tdst[x] = (arrtype)toggle_macro(val0);                      \ 
                tdst[x + 1] = (arrtype)toggle_macro(val1);                  \ 
                tdst[x + 2] = (arrtype)toggle_macro(val2);                  \ 
            }                                                               \ 
        else                                                                \ 
            /* channels == 1 or channels == 4 */                            \ 
            for( x = 0; x < width_n; x += 4 )                               \ 
            {                                                               \ 
                arrtype** kp = ker;                                         \ 
                arrtype* tp = *kp++;                                        \ 
                int t, val0 = tp[x], val1 = tp[x+1],                        \ 
                       val2 = tp[x+2], val3 = tp[x+3];                      \ 
                                                                            \ 
                while( kp != ker_ptr )                                      \ 
                {                                                           \ 
                    tp = *kp++;                                             \ 
                    t = tp[x]; update_extr_macro( val0, t );                \ 
                    t = tp[x + 1]; update_extr_macro( val1, t );            \ 
                    t = tp[x + 2]; update_extr_macro( val2, t );            \ 
                    t = tp[x + 3]; update_extr_macro( val3, t );            \ 
                }                                                           \ 
                                                                            \ 
                tdst[x] = (arrtype)toggle_macro(val0);                      \ 
                tdst[x + 1] = (arrtype)toggle_macro(val1);                  \ 
                tdst[x + 2] = (arrtype)toggle_macro(val2);                  \ 
                tdst[x + 3] = (arrtype)toggle_macro(val3);                  \ 
            }                                                               \ 
                                                                            \ 
        if( width_rest )                                                    \ 
        {                                                                   \ 
            if( need_copy )                                                 \ 
                CV_COPY( dst, tbuf, width_n, x );                           \ 
            else                                                            \ 
                CV_COPY( dst + width_n, tbuf + width_n, CV_MORPH_ALIGN, x );\ 
        }                                                                   \ 
                                                                            \ 
        /* rotate buffer */                                                 \ 
        {                                                                   \ 
            arrtype *t = rows[0];                                           \ 
                                                                            \ 
            CV_COPY( rows, rows + 1, ker_height - 1, i );                   \ 
            rows[i] = t;                                                    \ 
            crows--;                                                        \ 
            dst += dststep;                                                 \ 
        }                                                                   \ 
    }                                                                       \ 
    while( ++y < dst_height );                                              \ 
                                                                            \ 
    roi->height = y;                                                        \ 
    state->crows = crows;                                                   \ 
                                                                            \ 
    return CV_OK;                                                           \ 
} 
 
 
ICV_DEF_MORPH_RECT_INT_FUNC( Erode, 8u, uchar, CV_CALC_MIN_8U ) 
ICV_DEF_MORPH_RECT_INT_FUNC( Dilate, 8u, uchar, CV_CALC_MAX_8U ) 
ICV_DEF_MORPH_RECT_FLT_FUNC( Erode, CV_CALC_MIN ) 
ICV_DEF_MORPH_RECT_FLT_FUNC( Dilate, CV_CALC_MAX ) 
 
ICV_DEF_MORPH_ARB_FUNC( Erode, 8u, uchar, CV_CALC_MIN, CV_NOP ) 
ICV_DEF_MORPH_ARB_FUNC( Dilate, 8u, uchar, CV_CALC_MAX, CV_NOP ) 
ICV_DEF_MORPH_ARB_FUNC( Erode, 32f, int, CV_CALC_MIN, CV_TOGGLE_FLT ) 
ICV_DEF_MORPH_ARB_FUNC( Dilate, 32f, int, CV_CALC_MAX, CV_TOGGLE_FLT ) 
 
 
/////////////////////////////////// External Interface ///////////////////////////////////// 
 
 
CV_IMPL IplConvKernel * 
cvCreateStructuringElementEx( int cols, int rows, 
                              int anchorX, int anchorY, 
                              int shape, int *values ) 
{ 
    IplConvKernel *element = 0; 
    int i, size = rows * cols; 
    int *vals; 
    int element_size = sizeof( *element ) + size * sizeof( element->values[0] ); 
 
    CV_FUNCNAME( "cvCreateStructuringElementEx" ); 
 
    __BEGIN__; 
 
    if( !values && shape == CV_SHAPE_CUSTOM ) 
        CV_ERROR_FROM_STATUS( CV_NULLPTR_ERR ); 
 
    if( cols <= 0 || rows <= 0 || 
        (unsigned) anchorX >= (unsigned) cols || (unsigned) anchorY >= (unsigned) rows ) 
        CV_ERROR_FROM_STATUS( CV_BADSIZE_ERR ); 
 
    element_size = cvAlign(element_size,32); 
    element = (IplConvKernel *)cvAlloc( element_size ); 
    if( !element ) 
        CV_ERROR_FROM_STATUS( CV_OUTOFMEM_ERR ); 
 
    element->nCols = cols; 
    element->nRows = rows; 
    element->anchorX = anchorX; 
    element->anchorY = anchorY; 
    element->nShiftR = shape < CV_SHAPE_ELLIPSE ? shape : CV_SHAPE_CUSTOM; 
    element->values = vals = (int *) (element + 1); 
 
    switch (shape) 
    { 
    case CV_SHAPE_RECT: 
        memset( vals, -1, sizeof( vals[0] ) * cols * rows ); 
        break; 
    case CV_SHAPE_CROSS: 
        memset( vals, 0, sizeof( vals[0] ) * cols * rows ); 
        for( i = 0; i < cols; i++ ) 
        { 
            vals[i + anchorY * cols] = -1; 
        } 
 
        for( i = 0; i < rows; i++ ) 
        { 
            vals[anchorX + i * cols] = -1; 
        } 
        break; 
    case CV_SHAPE_ELLIPSE: 
        { 
            int r = (rows + 1) / 2; 
            int c = cols / 2; 
            double inv_r2 = 1. / (((double) (r)) * (r)); 
 
            memset( vals, 0, sizeof( vals[0] ) * cols * rows ); 
 
            for( i = 0; i < r; i++ ) 
            { 
                int y = r - i; 
                int dx = cvRound( c * sqrt( ((double)r * r - y * y) * inv_r2 )); 
                int x1 = c - dx; 
                int x2 = c + dx; 
 
                if( x1 < 0 ) 
                    x1 = 0; 
                if( x2 >= cols ) 
                    x2 = cols; 
                x2 -= x1 - 1; 
                memset( vals + i * cols + x1, -1, x2 * sizeof( int )); 
                memset( vals + (rows - i - 1) * cols + x1, -1, x2 * sizeof( int )); 
            } 
        } 
        break; 
    case CV_SHAPE_CUSTOM: 
        for( i = 0; i < size; i++ ) 
        { 
            vals[i] = !values || values[i] ? -1 : 0; 
        } 
        break; 
    default: 
        cvFree( (void**)&element ); 
        CV_ERROR_FROM_STATUS( CV_BADFLAG_ERR ); 
    } 
 
    __END__; 
 
    return element; 
} 
 
 
CV_IMPL void 
cvReleaseStructuringElement( IplConvKernel ** element ) 
{ 
    CV_FUNCNAME( "cvReleaseStructuringElement" ); 
 
    __BEGIN__; 
 
    if( !element ) 
        CV_ERROR_FROM_STATUS( CV_NULLPTR_ERR ); 
    cvFree( (void**)element ); 
 
    __END__; 
} 
 
 
static void icvInitMorphologyTab( CvFuncTable* rect_erode, CvFuncTable* rect_dilate, 
                                  CvFuncTable* any_erode, CvFuncTable* any_dilate ) 
{ 
    rect_erode->fn_2d[CV_8U] = (void*)icvErodeRect_8u; 
    rect_erode->fn_2d[CV_32F] = (void*)icvErodeRect_32f; 
    any_erode->fn_2d[CV_8U] = (void*)icvErodeAny_8u; 
    any_erode->fn_2d[CV_32F] = (void*)icvErodeAny_32f; 
 
    rect_dilate->fn_2d[CV_8U] = (void*)icvDilateRect_8u; 
    rect_dilate->fn_2d[CV_32F] = (void*)icvDilateRect_32f; 
    any_dilate->fn_2d[CV_8U] = (void*)icvDilateAny_8u; 
    any_dilate->fn_2d[CV_32F] = (void*)icvDilateAny_32f; 
} 
 
 
typedef CvStatus (CV_STDCALL * CvMorphRectFunc_IPP) 
    ( const void* src, int srcstep, void* dst, int dststep, 
      CvSize roi, CvSize elSize, CvPoint elAnchor ); 
 
typedef CvStatus (CV_STDCALL * CvMorphAnyFunc_IPP) 
    ( const void* src, int srcstep, void* dst, int dststep, 
      CvSize roi, const uchar* element, CvSize elSize, CvPoint elAnchor ); 
 
static void 
icvMorphOp( const void* srcarr, void* dstarr, IplConvKernel* element, 
            int iterations, int mop ) 
{ 
    static CvFuncTable morph_tab[4]; 
    static int inittab = 0; 
    CvFilterState *state = 0; 
    CvMat* temp = 0; 
 
    CV_FUNCNAME( "icvMorphOp" ); 
 
    __BEGIN__; 
 
    CvMorphFunc func = 0; 
    int i, coi1 = 0, coi2 = 0; 
    CvMat srcstub, *src = (CvMat*)srcarr; 
    CvMat dststub, *dst = (CvMat*)dstarr; 
    CvSize size, el_size; 
    CvPoint el_anchor; 
    int el_shape; 
    int type, depth; 
 
    if( !inittab ) 
    { 
        icvInitMorphologyTab( morph_tab+0, morph_tab+1, morph_tab+2, morph_tab+3 ); 
        inittab = 1; 
    } 
 
    CV_CALL( src = cvGetMat( src, &srcstub, &coi1 )); 
     
    if( src != &srcstub ) 
    { 
        srcstub = *src; 
        src = &srcstub; 
    } 
 
    if( dstarr == srcarr ) 
        dst = src; 
    else 
    { 
        CV_CALL( dst = cvGetMat( dst, &dststub, &coi2 )); 
 
        if( !CV_ARE_TYPES_EQ( src, dst )) 
            CV_ERROR( CV_StsUnmatchedFormats, "" ); 
 
        if( !CV_ARE_SIZES_EQ( src, dst )) 
            CV_ERROR( CV_StsUnmatchedSizes, "" ); 
    } 
 
    if( dst != &dststub ) 
    { 
        dststub = *dst; 
        dst = &dststub; 
    } 
 
    if( coi1 != 0 || coi2 != 0 ) 
        CV_ERROR( CV_BadCOI, "" ); 
 
    type = CV_MAT_TYPE( src->type ); 
    depth = CV_MAT_DEPTH( type ); 
 
    if( iterations == 0 || (element && element->nCols == 1 && element->nRows == 1)) 
    { 
        if( src->data.ptr != dst->data.ptr ) 
            cvCopy( src, dst ); 
        EXIT; 
    } 
 
    if( element ) 
    { 
        el_size = cvSize( element->nCols, element->nRows ); 
        el_anchor = cvPoint( element->anchorX, element->anchorY ); 
        el_shape = (int)(element->nShiftR); 
        el_shape = el_shape < CV_SHAPE_CUSTOM ? el_shape : CV_SHAPE_CUSTOM; 
    } 
    else 
    { 
        el_size = cvSize( 1+iterations*2, 1+iterations*2 ); 
        el_anchor = cvPoint( iterations, iterations ); 
        el_shape = CV_SHAPE_RECT; 
        iterations = 1; 
    } 
 
    if( icvErodeRect_8u_C1R_p ) 
    { 
        CvMorphRectFunc_IPP rect_func = 0; 
        CvMorphAnyFunc_IPP any_func = 0; 
 
        if( el_shape == CV_SHAPE_RECT && mop == 0 ) 
        { 
            rect_func = type == CV_8UC1 ? icvErodeRect_8u_C1R_p : 
                        type == CV_8UC3 ? icvErodeRect_8u_C3R_p : 
                        type == CV_8UC4 ? icvErodeRect_8u_C4R_p : 
                        type == CV_32FC1 ? icvErodeRect_32f_C1R_p : 
                        type == CV_32FC3 ? icvErodeRect_32f_C3R_p : 
                        type == CV_32FC4 ? icvErodeRect_32f_C4R_p : 0; 
        } 
        else if( el_shape == CV_SHAPE_RECT && mop == 1 ) 
        { 
            rect_func = type == CV_8UC1 ? icvDilateRect_8u_C1R_p : 
                        type == CV_8UC3 ? icvDilateRect_8u_C3R_p : 
                        type == CV_8UC4 ? icvDilateRect_8u_C4R_p : 
                        type == CV_32FC1 ? icvDilateRect_32f_C1R_p : 
                        type == CV_32FC3 ? icvDilateRect_32f_C3R_p : 
                        type == CV_32FC4 ? icvDilateRect_32f_C4R_p : 0; 
        } 
        else if( mop == 0 ) 
        { 
            any_func =  type == CV_8UC1 ? icvErodeAny_8u_C1R_p : 
                        type == CV_8UC3 ? icvErodeAny_8u_C3R_p : 
                        type == CV_8UC4 ? icvErodeAny_8u_C4R_p : 
                        type == CV_32FC1 ? icvErodeAny_32f_C1R_p : 
                        type == CV_32FC3 ? icvErodeAny_32f_C3R_p : 
                        type == CV_32FC4 ? icvErodeAny_32f_C4R_p : 0; 
        } 
        else 
        { 
            any_func =  type == CV_8UC1 ? icvDilateAny_8u_C1R_p : 
                        type == CV_8UC3 ? icvDilateAny_8u_C3R_p : 
                        type == CV_8UC4 ? icvDilateAny_8u_C4R_p : 
                        type == CV_32FC1 ? icvDilateAny_32f_C1R_p : 
                        type == CV_32FC3 ? icvDilateAny_32f_C3R_p : 
                        type == CV_32FC4 ? icvDilateAny_32f_C4R_p : 0; 
        } 
 
         
        if( rect_func || any_func ) 
        { 
            int y, dy = 0; 
            int el_len = el_size.width*el_size.height; 
            int temp_step; 
            uchar* el_mask = 0; 
            const uchar* shifted_ptr; 
            int stripe_size = 1 << 15; // the optimal value may depend on CPU cache, 
                                       // overhead of current IPP code etc. 
            if( any_func ) 
            { 
                el_mask = (uchar*)cvStackAlloc( el_len ); 
                for( i = 0; i < el_len; i++ ) 
                    el_mask[i] = (uchar)(element->values[i] != 0); 
            } 
 
            CV_CALL( temp = icvIPPFilterInit( src, stripe_size, el_size )); 
             
            shifted_ptr = temp->data.ptr + 
                el_anchor.y*temp->step + el_anchor.x*CV_ELEM_SIZE(type); 
            temp_step = temp->step ? temp->step : CV_STUB_STEP; 
 
            for( i = 0; i < iterations; i++ ) 
            { 
                int dst_step = dst->step ? dst->step : CV_STUB_STEP; 
 
                for( y = 0; y < src->rows; y += dy ) 
                { 
                    dy = icvIPPFilterNextStripe( src, temp, y, el_size, el_anchor ); 
                    if( rect_func ) 
                    { 
                        IPPI_CALL( rect_func( shifted_ptr, temp_step, 
                            dst->data.ptr + y*dst_step, dst_step, cvSize(src->cols, dy), 
                            el_size, el_anchor )); 
                    } 
                    else 
                    { 
                        IPPI_CALL( any_func( shifted_ptr, temp_step, 
                            dst->data.ptr + y*dst_step, dst_step, cvSize(src->cols, dy), 
                            el_mask, el_size, el_anchor )); 
                    } 
                } 
                src = dst; 
            } 
            EXIT; 
        } 
    } 
 
    CV_CALL( state = icvMorphologyInitAlloc( src->width, 
        depth == CV_8U ? cv8u : cv32f, CV_MAT_CN(type), 
        el_size, el_anchor, el_shape, element ? element->values : 0 )); 
 
    func = (CvMorphFunc)(morph_tab[(el_shape != CV_SHAPE_RECT)*2 + mop].fn_2d[depth]); 
    if( !func ) 
        CV_ERROR( CV_StsUnsupportedFormat, "" ); 
 
    size = cvGetMatSize( src ); 
    for( i = 0; i < iterations; i++ ) 
    { 
        IPPI_CALL( func( src->data.ptr, src->step, dst->data.ptr, 
                         dst->step, &size, state, 0 )); 
        src = dst; 
    } 
 
    __END__; 
 
    cvReleaseMat( &temp ); 
    icvMorphologyFree( &state ); 
} 
 
 
 
CV_IMPL void 
cvErode( const void* src, void* dst, IplConvKernel* element, int iterations ) 
{ 
    icvMorphOp( src, dst, element, iterations, 0 ); 
} 
 
 
CV_IMPL void 
cvDilate( const void* src, void* dst, IplConvKernel* element, int iterations ) 
{ 
    icvMorphOp( src, dst, element, iterations, 1 ); 
} 
 
 
CV_IMPL void 
cvMorphologyEx( const void* src, void* dst, 
                void* temp, IplConvKernel* element, int op, int iterations ) 
{ 
    CV_FUNCNAME( "cvMorhologyEx" ); 
 
    __BEGIN__; 
 
    if( (op == CV_MOP_GRADIENT || 
        (op == CV_MOP_TOPHAT || op == CV_MOP_BLACKHAT) && src == dst) && temp == 0 ) 
        CV_ERROR( CV_HeaderIsNull, "temp image required" ); 
 
    if( temp == src || temp == dst ) 
        CV_ERROR( CV_HeaderIsNull, "temp image is equal to src or dst" ); 
 
    switch (op) 
    { 
    case CV_MOP_OPEN: 
        CV_CALL( cvErode( src, dst, element, iterations )); 
        CV_CALL( cvDilate( dst, dst, element, iterations )); 
        break; 
    case CV_MOP_CLOSE: 
        CV_CALL( cvDilate( src, dst, element, iterations )); 
        CV_CALL( cvErode( dst, dst, element, iterations )); 
        break; 
    case CV_MOP_GRADIENT: 
        CV_CALL( cvErode( src, temp, element, iterations )); 
        CV_CALL( cvDilate( src, dst, element, iterations )); 
        CV_CALL( cvSub( dst, temp, dst )); 
        break; 
    case CV_MOP_TOPHAT: 
        if( src != dst ) 
            temp = dst; 
        CV_CALL( cvErode( src, temp, element, iterations )); 
        CV_CALL( cvDilate( temp, temp, element, iterations )); 
        CV_CALL( cvSub( src, temp, dst )); 
        break; 
    case CV_MOP_BLACKHAT: 
        if( src != dst ) 
            temp = dst; 
        CV_CALL( cvDilate( src, temp, element, iterations )); 
        CV_CALL( cvErode( temp, temp, element, iterations )); 
        CV_CALL( cvSub( temp, src, dst )); 
        break; 
    default: 
        CV_ERROR( CV_StsBadArg, "unknown morphological operation" ); 
    } 
 
    __END__; 
} 
 
/* End of file. */