16acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*M///////////////////////////////////////////////////////////////////////////////////////
26acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
36acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
46acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
56acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  By downloading, copying, installing or using the software you agree to this license.
66acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  If you do not agree to this license, do not download, install,
76acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  copy or use the software.
86acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
96acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//                        Intel License Agreement
116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//                For Open Source Computer Vision Library
126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Copyright (C) 2000, Intel Corporation, all rights reserved.
146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Third party copyrights are property of their respective owners.
156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Redistribution and use in source and binary forms, with or without modification,
176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// are permitted provided that the following conditions are met:
186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * Redistribution's of source code must retain the above copyright notice,
206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     this list of conditions and the following disclaimer.
216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * Redistribution's in binary form must reproduce the above copyright notice,
236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     this list of conditions and the following disclaimer in the documentation
246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     and/or other materials provided with the distribution.
256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * The name of Intel Corporation may not be used to endorse or promote products
276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     derived from this software without specific prior written permission.
286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// This software is provided by the copyright holders and contributors "as is" and
306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// any express or implied warranties, including, but not limited to, the implied
316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// warranties of merchantability and fitness for a particular purpose are disclaimed.
326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// In no event shall the Intel Corporation or contributors be liable for any direct,
336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// indirect, incidental, special, exemplary, or consequential damages
346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// (including, but not limited to, procurement of substitute goods or services;
356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// loss of use, data, or profits; or business interruption) however caused
366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// and on any theory of liability, whether in contract, strict liability,
376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// or tort (including negligence or otherwise) arising in any way out of
386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// the use of this software, even if advised of the possibility of such damage.
396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//M*/
416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "_cv.h"
436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\
466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    Base Image Filter
476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/
486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void default_x_filter_func( const uchar*, uchar*, void* )
506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void default_y_filter_func( uchar**, uchar*, int, int, void* )
546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvBaseImageFilter::CvBaseImageFilter()
586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    min_depth = CV_8U;
606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    buffer = 0;
616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    rows = 0;
626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    max_width = 0;
636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    x_func = default_x_filter_func;
646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    y_func = default_y_filter_func;
656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvBaseImageFilter::CvBaseImageFilter( int _max_width, int _src_type, int _dst_type,
696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                      bool _is_separable, CvSize _ksize, CvPoint _anchor,
706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                      int _border_mode, CvScalar _border_value )
716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    min_depth = CV_8U;
736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    buffer = 0;
746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    rows = 0;
756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    max_width = 0;
766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    x_func = default_x_filter_func;
776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    y_func = default_y_filter_func;
786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    init( _max_width, _src_type, _dst_type, _is_separable,
806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          _ksize, _anchor, _border_mode, _border_value );
816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvBaseImageFilter::clear()
856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvFree( &buffer );
876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    rows = 0;
886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvBaseImageFilter::~CvBaseImageFilter()
926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    clear();
946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvBaseImageFilter::get_work_params()
986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int min_rows = max_ky*2 + 3, rows = MAX(min_rows,10), row_sz;
1006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int width = max_width, trow_sz = 0;
1016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( is_separable )
1036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
1046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int max_depth = MAX(CV_MAT_DEPTH(src_type), CV_MAT_DEPTH(dst_type));
1056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int max_cn = MAX(CV_MAT_CN(src_type), CV_MAT_CN(dst_type));
1066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        max_depth = MAX( max_depth, min_depth );
1076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        work_type = CV_MAKETYPE( max_depth, max_cn );
1086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        trow_sz = cvAlign( (max_width + ksize.width - 1)*CV_ELEM_SIZE(src_type), ALIGN );
1096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
1116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
1126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        work_type = src_type;
1136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        width += ksize.width - 1;
1146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    row_sz = cvAlign( width*CV_ELEM_SIZE(work_type), ALIGN );
1166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    buf_size = rows*row_sz;
1176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    buf_size = MIN( buf_size, 1 << 16 );
1186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    buf_size = MAX( buf_size, min_rows*row_sz );
1196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    max_rows = (buf_size/row_sz)*3 + max_ky*2 + 8;
1206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    buf_size += trow_sz;
1216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvBaseImageFilter::init( int _max_width, int _src_type, int _dst_type,
1256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              bool _is_separable, CvSize _ksize, CvPoint _anchor,
1266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              int _border_mode, CvScalar _border_value )
1276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "CvBaseImageFilter::init" );
1296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
1316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int total_buf_sz, src_pix_sz, row_tab_sz, bsz;
1336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uchar* ptr;
1346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !(buffer && _max_width <= max_width && _src_type == src_type &&
1366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        _dst_type == dst_type && _is_separable == is_separable &&
1376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        _ksize.width == ksize.width && _ksize.height == ksize.height &&
1386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        _anchor.x == anchor.x && _anchor.y == anchor.y) )
1396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        clear();
1406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    is_separable = _is_separable != 0;
1426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    max_width = _max_width; //MAX(_max_width,_ksize.width);
1436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    src_type = CV_MAT_TYPE(_src_type);
1446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dst_type = CV_MAT_TYPE(_dst_type);
1456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ksize = _ksize;
1466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    anchor = _anchor;
1476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( anchor.x == -1 )
1496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        anchor.x = ksize.width / 2;
1506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( anchor.y == -1 )
1516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        anchor.y = ksize.height / 2;
1526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    max_ky = MAX( anchor.y, ksize.height - anchor.y - 1 );
1546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    border_mode = _border_mode;
1556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    border_value = _border_value;
1566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( ksize.width <= 0 || ksize.height <= 0 ||
1586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        (unsigned)anchor.x >= (unsigned)ksize.width ||
1596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        (unsigned)anchor.y >= (unsigned)ksize.height )
1606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange, "invalid kernel size and/or anchor position" );
1616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( border_mode != IPL_BORDER_CONSTANT && border_mode != IPL_BORDER_REPLICATE &&
1636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        border_mode != IPL_BORDER_REFLECT && border_mode != IPL_BORDER_REFLECT_101 )
1646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "Invalid/unsupported border mode" );
1656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    get_work_params();
1676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    prev_width = 0;
1696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    prev_x_range = cvSlice(0,0);
1706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    buf_size = cvAlign( buf_size, ALIGN );
1726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    src_pix_sz = CV_ELEM_SIZE(src_type);
1746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    border_tab_sz1 = anchor.x*src_pix_sz;
1756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    border_tab_sz = (ksize.width-1)*src_pix_sz;
1766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bsz = cvAlign( border_tab_sz*sizeof(int), ALIGN );
1776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( max_rows > max_ky*2 );
1796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    row_tab_sz = cvAlign( max_rows*sizeof(uchar*), ALIGN );
1806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    total_buf_sz = buf_size + row_tab_sz + bsz;
1816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( ptr = buffer = (uchar*)cvAlloc( total_buf_sz ));
1836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    rows = (uchar**)ptr;
1856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ptr += row_tab_sz;
1866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    border_tab = (int*)ptr;
1876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ptr += bsz;
1886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    buf_start = ptr;
1906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const_row = 0;
1916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( border_mode == IPL_BORDER_CONSTANT )
1936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvScalarToRawData( &border_value, border_tab, src_type, 0 );
1946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
1966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvBaseImageFilter::start_process( CvSlice x_range, int width )
2006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int mode = border_mode;
2026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int pix_sz = CV_ELEM_SIZE(src_type), work_pix_sz = CV_ELEM_SIZE(work_type);
2036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int bsz = buf_size, bw = x_range.end_index - x_range.start_index, bw1 = bw + ksize.width - 1;
2046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int tr_step = cvAlign(bw1*pix_sz, ALIGN );
2056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, j, k, ofs;
2066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( x_range.start_index == prev_x_range.start_index &&
2086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x_range.end_index == prev_x_range.end_index &&
2096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        width == prev_width )
2106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return;
2116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    prev_x_range = x_range;
2136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    prev_width = width;
2146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !is_separable )
2166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        bw = bw1;
2176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
2186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        bsz -= tr_step;
2196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    buf_step = cvAlign(bw*work_pix_sz, ALIGN);
2216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( mode == IPL_BORDER_CONSTANT )
2236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        bsz -= buf_step;
2246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    buf_max_count = bsz/buf_step;
2256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    buf_max_count = MIN( buf_max_count, max_rows - max_ky*2 );
2266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    buf_end = buf_start + buf_max_count*buf_step;
2276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( mode == IPL_BORDER_CONSTANT )
2296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int i, tab_len = ksize.width*pix_sz;
2316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        uchar* bt = (uchar*)border_tab;
2326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        uchar* trow = buf_end;
2336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const_row = buf_end + (is_separable ? 1 : 0)*tr_step;
2346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = pix_sz; i < tab_len; i++ )
2366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            bt[i] = bt[i - pix_sz];
2376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < pix_sz; i++ )
2386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            trow[i] = bt[i];
2396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = pix_sz; i < tr_step; i++ )
2406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            trow[i] = trow[i - pix_sz];
2416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( is_separable )
2426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            x_func( trow, const_row, this );
2436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return;
2446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
2456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( x_range.end_index - x_range.start_index <= 1 )
2476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        mode = IPL_BORDER_REPLICATE;
2486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    width = (width - 1)*pix_sz;
2506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ofs = (anchor.x-x_range.start_index)*pix_sz;
2516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( k = 0; k < 2; k++ )
2536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int idx, delta;
2556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int i1, i2, di;
2566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( k == 0 )
2586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
2596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            idx = (x_range.start_index - 1)*pix_sz;
2606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            delta = di = -pix_sz;
2616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            i1 = border_tab_sz1 - pix_sz;
2626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            i2 = -pix_sz;
2636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
2646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
2656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
2666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            idx = x_range.end_index*pix_sz;
2676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            delta = di = pix_sz;
2686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            i1 = border_tab_sz1;
2696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            i2 = border_tab_sz;
2706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
2716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( (unsigned)idx > (unsigned)width )
2736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
2746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int shift = mode == IPL_BORDER_REFLECT_101 ? pix_sz : 0;
2756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            idx = k == 0 ? shift : width - shift;
2766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            delta = -delta;
2776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
2786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = i1; i != i2; i += di )
2806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
2816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( j = 0; j < pix_sz; j++ )
2826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                border_tab[i + j] = idx + ofs + j;
2836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( mode != IPL_BORDER_REPLICATE )
2846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
2856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( (delta > 0 && idx == width) ||
2866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    (delta < 0 && idx == 0) )
2876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
2886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( mode == IPL_BORDER_REFLECT_101 )
2896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        idx -= delta*2;
2906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    delta = -delta;
2916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
2926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else
2936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    idx += delta;
2946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
2956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
2966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
2976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvBaseImageFilter::make_y_border( int row_count, int top_rows, int bottom_rows )
3016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
3026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i;
3036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( border_mode == IPL_BORDER_CONSTANT ||
3056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        border_mode == IPL_BORDER_REPLICATE )
3066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        uchar* row1 = border_mode == IPL_BORDER_CONSTANT ? const_row : rows[max_ky];
3086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < top_rows && rows[i] == 0; i++ )
3106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            rows[i] = row1;
3116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        row1 = border_mode == IPL_BORDER_CONSTANT ? const_row : rows[row_count-1];
3136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < bottom_rows; i++ )
3146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            rows[i + row_count] = row1;
3156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
3176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int j, dj = 1, shift = border_mode == IPL_BORDER_REFLECT_101;
3196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = top_rows-1, j = top_rows+shift; i >= 0; i-- )
3216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
3226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( rows[i] == 0 )
3236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                rows[i] = rows[j];
3246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            j += dj;
3256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( dj > 0 && j >= row_count )
3266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
3276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( !bottom_rows )
3286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
3296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                j -= 1 + shift;
3306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dj = -dj;
3316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
3326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
3336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0, j = row_count-1-shift; i < bottom_rows; i++, j-- )
3356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            rows[i + row_count] = rows[j];
3366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
3386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennint CvBaseImageFilter::fill_cyclic_buffer( const uchar* src, int src_step,
3416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                           int y0, int y1, int y2 )
3426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
3436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, y = y0, bsz1 = border_tab_sz1, bsz = border_tab_sz;
3446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int pix_size = CV_ELEM_SIZE(src_type);
3456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int width = prev_x_range.end_index - prev_x_range.start_index, width_n = width*pix_size;
3466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool can_use_src_as_trow = false; //is_separable && width >= ksize.width;
3476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // fill the cyclic buffer
3496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( ; buf_count < buf_max_count && y < y2; buf_count++, y++, src += src_step )
3506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        uchar* trow = is_separable ? buf_end : buf_tail;
3526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        uchar* bptr = can_use_src_as_trow && y1 < y && y+1 < y2 ? (uchar*)(src - bsz1) : trow;
3536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( bptr != trow )
3556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
3566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i < bsz1; i++ )
3576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                trow[i] = bptr[i];
3586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; i < bsz; i++ )
3596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                trow[i] = bptr[i + width_n];
3606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
3616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else if( !(((size_t)(bptr + bsz1)|(size_t)src|width_n) & (sizeof(int)-1)) )
3626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i < width_n; i += sizeof(int) )
3636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                *(int*)(bptr + i + bsz1) = *(int*)(src + i);
3646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
3656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i < width_n; i++ )
3666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                bptr[i + bsz1] = src[i];
3676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( border_mode != IPL_BORDER_CONSTANT )
3696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
3706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i < bsz1; i++ )
3716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
3726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int j = border_tab[i];
3736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                bptr[i] = bptr[j];
3746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
3756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; i < bsz; i++ )
3766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
3776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int j = border_tab[i];
3786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                bptr[i + width_n] = bptr[j];
3796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
3806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
3816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
3826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
3836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const uchar *bt = (uchar*)border_tab;
3846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i < bsz1; i++ )
3856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                bptr[i] = bt[i];
3866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; i < bsz; i++ )
3886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                bptr[i + width_n] = bt[i];
3896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
3906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( is_separable )
3926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
3936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            x_func( bptr, buf_tail, this );
3946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( bptr != trow )
3956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
3966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( i = 0; i < bsz1; i++ )
3976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    bptr[i] = trow[i];
3986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( ; i < bsz; i++ )
3996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    bptr[i + width_n] = trow[i];
4006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
4016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
4026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        buf_tail += buf_step;
4046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( buf_tail >= buf_end )
4056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            buf_tail = buf_start;
4066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
4076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return y - y0;
4096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
4106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennint CvBaseImageFilter::process( const CvMat* src, CvMat* dst,
4126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                CvRect src_roi, CvPoint dst_origin, int flags )
4136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
4146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int rows_processed = 0;
4156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /*
4176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        check_parameters
4186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        initialize_horizontal_border_reloc_tab_if_not_initialized_yet
4196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for_each_source_row: src starts from src_roi.y, buf starts with the first available row
4216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            1) if separable,
4226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                   1a.1) copy source row to temporary buffer, form a border using border reloc tab.
4236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                   1a.2) apply row-wise filter (symmetric, asymmetric or generic)
4246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               else
4256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                   1b.1) copy source row to the buffer, form a border
4266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            2) if the buffer is full, or it is the last source row:
4276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                 2.1) if stage != middle, form the pointers to other "virtual" rows.
4286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                 if separable
4296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    2a.2) apply column-wise filter, store the results.
4306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                 else
4316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    2b.2) form a sparse (offset,weight) tab
4326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    2b.3) apply generic non-separable filter, store the results
4336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            3) update row pointers etc.
4346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    */
4356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "CvBaseImageFilter::process" );
4376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
4396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, width, _src_y1, _src_y2;
4416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int src_x, src_y, src_y1, src_y2, dst_y;
4426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int pix_size = CV_ELEM_SIZE(src_type);
4436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uchar *sptr = 0, *dptr;
4446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int phase = flags & (CV_START|CV_END|CV_MIDDLE);
4456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool isolated_roi = (flags & CV_ISOLATED_ROI) != 0;
4466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_IS_MAT(src) )
4486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "" );
4496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( CV_MAT_TYPE(src->type) != src_type )
4516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsUnmatchedFormats, "" );
4526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    width = src->cols;
4546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( src_roi.width == -1 && src_roi.x == 0 )
4566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        src_roi.width = width;
4576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( src_roi.height == -1 && src_roi.y == 0 )
4596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
4606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        src_roi.y = 0;
4616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        src_roi.height = src->rows;
4626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
4636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( src_roi.width > max_width ||
4656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        src_roi.x < 0 || src_roi.width < 0 ||
4666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        src_roi.y < 0 || src_roi.height < 0 ||
4676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        src_roi.x + src_roi.width > width ||
4686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        src_roi.y + src_roi.height > src->rows )
4696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange, "Too large source image or its ROI" );
4706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    src_x = src_roi.x;
4726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _src_y1 = 0;
4736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _src_y2 = src->rows;
4746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( isolated_roi )
4766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
4776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        src_roi.x = 0;
4786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        width = src_roi.width;
4796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        _src_y1 = src_roi.y;
4806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        _src_y2 = src_roi.y + src_roi.height;
4816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
4826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_IS_MAT(dst) )
4846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "" );
4856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( CV_MAT_TYPE(dst->type) != dst_type )
4876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsUnmatchedFormats, "" );
4886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( dst_origin.x < 0 || dst_origin.y < 0 )
4906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange, "Incorrect destination ROI origin" );
4916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( phase == CV_WHOLE )
4936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        phase = CV_START | CV_END;
4946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    phase &= CV_START | CV_END | CV_MIDDLE;
4956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // initialize horizontal border relocation tab if it is not initialized yet
4976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( phase & CV_START )
4986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        start_process( cvSlice(src_roi.x, src_roi.x + src_roi.width), width );
4996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( prev_width != width || prev_x_range.start_index != src_roi.x ||
5006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        prev_x_range.end_index != src_roi.x + src_roi.width )
5016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg,
5026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            "In a middle or at the end the horizontal placement of the stripe can not be changed" );
5036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dst_y = dst_origin.y;
5056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    src_y1 = src_roi.y;
5066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    src_y2 = src_roi.y + src_roi.height;
5076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( phase & CV_START )
5096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i <= max_ky*2; i++ )
5116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            rows[i] = 0;
5126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        src_y1 -= max_ky;
5146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        top_rows = bottom_rows = 0;
5156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( src_y1 < _src_y1 )
5176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
5186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            top_rows = _src_y1 - src_y1;
5196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            src_y1 = _src_y1;
5206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
5216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        buf_head = buf_tail = buf_start;
5236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        buf_count = 0;
5246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( phase & CV_END )
5276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        src_y2 += max_ky;
5296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( src_y2 > _src_y2 )
5316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
5326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            bottom_rows = src_y2 - _src_y2;
5336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            src_y2 = _src_y2;
5346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
5356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dptr = dst->data.ptr + dst_origin.y*dst->step + dst_origin.x*CV_ELEM_SIZE(dst_type);
5386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sptr = src->data.ptr + src_y1*src->step + src_x*pix_size;
5396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( src_y = src_y1; src_y < src_y2; )
5416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        uchar* bptr;
5436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int row_count, delta;
5446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        delta = fill_cyclic_buffer( sptr, src->step, src_y, src_y1, src_y2 );
5466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        src_y += delta;
5486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        sptr += src->step*delta;
5496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // initialize the cyclic buffer row pointers
5516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        bptr = buf_head;
5526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < buf_count; i++ )
5536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
5546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            rows[i+top_rows] = bptr;
5556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            bptr += buf_step;
5566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( bptr >= buf_end )
5576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                bptr = buf_start;
5586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
5596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        row_count = top_rows + buf_count;
5616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !rows[0] || ((phase & CV_END) && src_y == src_y2) )
5636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
5646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int br = (phase & CV_END) && src_y == src_y2 ? bottom_rows : 0;
5656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            make_y_border( row_count, top_rows, br );
5666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            row_count += br;
5676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
5686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( rows[0] && row_count > max_ky*2 )
5706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
5716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int count = row_count - max_ky*2;
5726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( dst_y + count > dst->rows )
5736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_ERROR( CV_StsOutOfRange, "The destination image can not fit the result" );
5746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            assert( count >= 0 );
5766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            y_func( rows + max_ky - anchor.y, dptr, dst->step, count, this );
5776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            row_count -= count;
5786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst_y += count;
5796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dptr += dst->step*count;
5806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( bptr = row_count > 0 ?rows[count] : 0; buf_head != bptr && buf_count > 0; buf_count-- )
5816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
5826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                buf_head += buf_step;
5836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( buf_head >= buf_end )
5846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    buf_head = buf_start;
5856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
5866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            rows_processed += count;
5876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            top_rows = MAX(top_rows - count, 0);
5886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
5896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
5926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return rows_processed;
5946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\
5986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    Separable Linear Filter
5996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/
6006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvFilterRowSymm_8u32s( const uchar* src, int* dst, void* params );
6026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvFilterColSymm_32s8u( const int** src, uchar* dst, int dst_step,
6036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    int count, void* params );
6046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvFilterColSymm_32s16s( const int** src, short* dst, int dst_step,
6056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                     int count, void* params );
6066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvFilterRowSymm_8u32f( const uchar* src, float* dst, void* params );
6076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvFilterRow_8u32f( const uchar* src, float* dst, void* params );
6086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvFilterRowSymm_16s32f( const short* src, float* dst, void* params );
6096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvFilterRow_16s32f( const short* src, float* dst, void* params );
6106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvFilterRowSymm_16u32f( const ushort* src, float* dst, void* params );
6116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvFilterRow_16u32f( const ushort* src, float* dst, void* params );
6126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvFilterRowSymm_32f( const float* src, float* dst, void* params );
6136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvFilterRow_32f( const float* src, float* dst, void* params );
6146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvFilterColSymm_32f8u( const float** src, uchar* dst, int dst_step,
6166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    int count, void* params );
6176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvFilterCol_32f8u( const float** src, uchar* dst, int dst_step,
6186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                int count, void* params );
6196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvFilterColSymm_32f16s( const float** src, short* dst, int dst_step,
6206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                     int count, void* params );
6216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvFilterCol_32f16s( const float** src, short* dst, int dst_step,
6226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 int count, void* params );
6236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvFilterColSymm_32f16u( const float** src, ushort* dst, int dst_step,
6246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                     int count, void* params );
6256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvFilterCol_32f16u( const float** src, ushort* dst, int dst_step,
6266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 int count, void* params );
6276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvFilterColSymm_32f( const float** src, float* dst, int dst_step,
6286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                  int count, void* params );
6296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvFilterCol_32f( const float** src, float* dst, int dst_step,
6306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              int count, void* params );
6316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvSepFilter::CvSepFilter()
6336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
6346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    min_depth = CV_32F;
6356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    kx = ky = 0;
6366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    kx_flags = ky_flags = 0;
6376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
6386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvSepFilter::CvSepFilter( int _max_width, int _src_type, int _dst_type,
6416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          const CvMat* _kx, const CvMat* _ky,
6426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          CvPoint _anchor, int _border_mode,
6436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          CvScalar _border_value )
6446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
6456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    min_depth = CV_32F;
6466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    kx = ky = 0;
6476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    init( _max_width, _src_type, _dst_type, _kx, _ky, _anchor, _border_mode, _border_value );
6486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
6496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvSepFilter::clear()
6526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
6536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat( &kx );
6546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat( &ky );
6556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvBaseImageFilter::clear();
6566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
6576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvSepFilter::~CvSepFilter()
6606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
6616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    clear();
6626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
6636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#undef FILTER_BITS
6666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define FILTER_BITS 8
6676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvSepFilter::init( int _max_width, int _src_type, int _dst_type,
6696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        const CvMat* _kx, const CvMat* _ky,
6706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CvPoint _anchor, int _border_mode,
6716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CvScalar _border_value )
6726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
6736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "CvSepFilter::init" );
6746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
6766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSize _ksize;
6786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int filter_type;
6796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, xsz, ysz;
6806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int convert_filters = 0;
6816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double xsum = 0, ysum = 0;
6826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const float eps = FLT_EPSILON*100.f;
6836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_IS_MAT(_kx) || !CV_IS_MAT(_ky) ||
6856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        (_kx->cols != 1 && _kx->rows != 1) ||
6866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        (_ky->cols != 1 && _ky->rows != 1) ||
6876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_MAT_CN(_kx->type) != 1 || CV_MAT_CN(_ky->type) != 1 ||
6886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        !CV_ARE_TYPES_EQ(_kx,_ky) )
6896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg,
6906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        "Both kernels must be valid 1d single-channel vectors of the same types" );
6916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( CV_MAT_CN(_src_type) != CV_MAT_CN(_dst_type) )
6936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsUnmatchedFormats, "Input and output must have the same number of channels" );
6946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    filter_type = MAX( CV_32F, CV_MAT_DEPTH(_kx->type) );
6966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _ksize.width = _kx->rows + _kx->cols - 1;
6986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _ksize.height = _ky->rows + _ky->cols - 1;
6996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( CvBaseImageFilter::init( _max_width, _src_type, _dst_type, 1, _ksize,
7016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                      _anchor, _border_mode, _border_value ));
7026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !(kx && CV_ARE_SIZES_EQ(kx,_kx)) )
7046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
7056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvReleaseMat( &kx );
7066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( kx = cvCreateMat( _kx->rows, _kx->cols, filter_type ));
7076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
7086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !(ky && CV_ARE_SIZES_EQ(ky,_ky)) )
7106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
7116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvReleaseMat( &ky );
7126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( ky = cvCreateMat( _ky->rows, _ky->cols, filter_type ));
7136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
7146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvConvert( _kx, kx ));
7166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvConvert( _ky, ky ));
7176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    xsz = kx->rows + kx->cols - 1;
7196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ysz = ky->rows + ky->cols - 1;
7206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    kx_flags = ky_flags = ASYMMETRICAL + SYMMETRICAL + POSITIVE + SUM_TO_1 + INTEGER;
7216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !(xsz & 1) )
7236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        kx_flags &= ~(ASYMMETRICAL + SYMMETRICAL);
7246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !(ysz & 1) )
7256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ky_flags &= ~(ASYMMETRICAL + SYMMETRICAL);
7266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < xsz; i++ )
7286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
7296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        float v = kx->data.fl[i];
7306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        xsum += v;
7316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( v < 0 )
7326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            kx_flags &= ~POSITIVE;
7336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( fabs(v - cvRound(v)) > eps )
7346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            kx_flags &= ~INTEGER;
7356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( fabs(v - kx->data.fl[xsz - i - 1]) > eps )
7366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            kx_flags &= ~SYMMETRICAL;
7376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( fabs(v + kx->data.fl[xsz - i - 1]) > eps )
7386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            kx_flags &= ~ASYMMETRICAL;
7396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
7406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( fabs(xsum - 1.) > eps )
7426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        kx_flags &= ~SUM_TO_1;
7436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < ysz; i++ )
7456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
7466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        float v = ky->data.fl[i];
7476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ysum += v;
7486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( v < 0 )
7496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ky_flags &= ~POSITIVE;
7506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( fabs(v - cvRound(v)) > eps )
7516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ky_flags &= ~INTEGER;
7526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( fabs(v - ky->data.fl[ysz - i - 1]) > eps )
7536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ky_flags &= ~SYMMETRICAL;
7546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( fabs(v + ky->data.fl[ysz - i - 1]) > eps )
7556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ky_flags &= ~ASYMMETRICAL;
7566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
7576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( fabs(ysum - 1.) > eps )
7596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ky_flags &= ~SUM_TO_1;
7606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    x_func = 0;
7626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    y_func = 0;
7636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( CV_MAT_DEPTH(src_type) == CV_8U )
7656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
7666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( CV_MAT_DEPTH(dst_type) == CV_8U &&
7676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ((kx_flags&ky_flags) & (SYMMETRICAL + POSITIVE + SUM_TO_1)) == SYMMETRICAL + POSITIVE + SUM_TO_1 )
7686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
7696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            x_func = (CvRowFilterFunc)icvFilterRowSymm_8u32s;
7706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            y_func = (CvColumnFilterFunc)icvFilterColSymm_32s8u;
7716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            kx_flags &= ~INTEGER;
7726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ky_flags &= ~INTEGER;
7736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            convert_filters = 1;
7746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
7756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else if( CV_MAT_DEPTH(dst_type) == CV_16S &&
7766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            (kx_flags & (SYMMETRICAL + ASYMMETRICAL)) && (kx_flags & INTEGER) &&
7776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            (ky_flags & (SYMMETRICAL + ASYMMETRICAL)) && (ky_flags & INTEGER) )
7786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
7796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            x_func = (CvRowFilterFunc)icvFilterRowSymm_8u32s;
7806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            y_func = (CvColumnFilterFunc)icvFilterColSymm_32s16s;
7816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            convert_filters = 1;
7826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
7836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
7846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
7856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( CV_MAT_DEPTH(dst_type) > CV_32F )
7866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_ERROR( CV_StsUnsupportedFormat, "8u->64f separable filtering is not supported" );
7876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( kx_flags & (SYMMETRICAL + ASYMMETRICAL) )
7896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                x_func = (CvRowFilterFunc)icvFilterRowSymm_8u32f;
7906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
7916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                x_func = (CvRowFilterFunc)icvFilterRow_8u32f;
7926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
7936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
7946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( CV_MAT_DEPTH(src_type) == CV_16U )
7956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
7966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( CV_MAT_DEPTH(dst_type) > CV_32F )
7976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsUnsupportedFormat, "16u->64f separable filtering is not supported" );
7986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( kx_flags & (SYMMETRICAL + ASYMMETRICAL) )
8006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            x_func = (CvRowFilterFunc)icvFilterRowSymm_16u32f;
8016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
8026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            x_func = (CvRowFilterFunc)icvFilterRow_16u32f;
8036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
8046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( CV_MAT_DEPTH(src_type) == CV_16S )
8056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
8066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( CV_MAT_DEPTH(dst_type) > CV_32F )
8076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsUnsupportedFormat, "16s->64f separable filtering is not supported" );
8086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( kx_flags & (SYMMETRICAL + ASYMMETRICAL) )
8106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            x_func = (CvRowFilterFunc)icvFilterRowSymm_16s32f;
8116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
8126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            x_func = (CvRowFilterFunc)icvFilterRow_16s32f;
8136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
8146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( CV_MAT_DEPTH(src_type) == CV_32F )
8156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
8166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( CV_MAT_DEPTH(dst_type) != CV_32F )
8176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsUnsupportedFormat, "When the input has 32f data type, the output must also have 32f type" );
8186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( kx_flags & (SYMMETRICAL + ASYMMETRICAL) )
8206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            x_func = (CvRowFilterFunc)icvFilterRowSymm_32f;
8216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
8226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            x_func = (CvRowFilterFunc)icvFilterRow_32f;
8236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
8246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
8256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsUnsupportedFormat, "Unknown or unsupported input data type" );
8266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !y_func )
8286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
8296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( CV_MAT_DEPTH(dst_type) == CV_8U )
8306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
8316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( ky_flags & (SYMMETRICAL + ASYMMETRICAL) )
8326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                y_func = (CvColumnFilterFunc)icvFilterColSymm_32f8u;
8336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
8346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                y_func = (CvColumnFilterFunc)icvFilterCol_32f8u;
8356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
8366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else if( CV_MAT_DEPTH(dst_type) == CV_16U )
8376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
8386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( ky_flags & (SYMMETRICAL + ASYMMETRICAL) )
8396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                y_func = (CvColumnFilterFunc)icvFilterColSymm_32f16u;
8406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
8416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                y_func = (CvColumnFilterFunc)icvFilterCol_32f16u;
8426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
8436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else if( CV_MAT_DEPTH(dst_type) == CV_16S )
8446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
8456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( ky_flags & (SYMMETRICAL + ASYMMETRICAL) )
8466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                y_func = (CvColumnFilterFunc)icvFilterColSymm_32f16s;
8476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
8486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                y_func = (CvColumnFilterFunc)icvFilterCol_32f16s;
8496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
8506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else if( CV_MAT_DEPTH(dst_type) == CV_32F )
8516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
8526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( ky_flags & (SYMMETRICAL + ASYMMETRICAL) )
8536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                y_func = (CvColumnFilterFunc)icvFilterColSymm_32f;
8546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
8556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                y_func = (CvColumnFilterFunc)icvFilterCol_32f;
8566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
8576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
8586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsUnsupportedFormat, "Unknown or unsupported input data type" );
8596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
8606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( convert_filters )
8626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
8636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int scale = kx_flags & ky_flags & INTEGER ? 1 : (1 << FILTER_BITS);
8646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int sum;
8656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = sum = 0; i < xsz; i++ )
8676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
8686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int t = cvRound(kx->data.fl[i]*scale);
8696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            kx->data.i[i] = t;
8706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            sum += t;
8716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
8726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( scale > 1 )
8736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            kx->data.i[xsz/2] += scale - sum;
8746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = sum = 0; i < ysz; i++ )
8766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
8776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int t = cvRound(ky->data.fl[i]*scale);
8786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ky->data.i[i] = t;
8796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            sum += t;
8806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
8816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( scale > 1 )
8826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ky->data.i[ysz/2] += scale - sum;
8836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        kx->type = (kx->type & ~CV_MAT_DEPTH_MASK) | CV_32S;
8846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ky->type = (ky->type & ~CV_MAT_DEPTH_MASK) | CV_32S;
8856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
8866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
8886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
8896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvSepFilter::init( int _max_width, int _src_type, int _dst_type,
8926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        bool _is_separable, CvSize _ksize,
8936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CvPoint _anchor, int _border_mode,
8946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CvScalar _border_value )
8956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
8966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvBaseImageFilter::init( _max_width, _src_type, _dst_type, _is_separable,
8976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                             _ksize, _anchor, _border_mode, _border_value );
8986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
8996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
9026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterRowSymm_8u32s( const uchar* src, int* dst, void* params )
9036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
9046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvSepFilter* state = (const CvSepFilter*)params;
9056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvMat* _kx = state->get_x_kernel();
9066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const int* kx = _kx->data.i;
9076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int ksize = _kx->cols + _kx->rows - 1;
9086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i = 0, j, k, width = state->get_width();
9096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int cn = CV_MAT_CN(state->get_src_type());
9106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int ksize2 = ksize/2, ksize2n = ksize2*cn;
9116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int is_symm = state->get_x_kernel_flags() & CvSepFilter::SYMMETRICAL;
9126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const uchar* s = src + ksize2n;
9136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    kx += ksize2;
9156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    width *= cn;
9166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( is_symm )
9186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
9196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( ksize == 1 && kx[0] == 1 )
9206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
9216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i <= width - 2; i += 2 )
9226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
9236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int s0 = s[i], s1 = s[i+1];
9246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i] = s0; dst[i+1] = s1;
9256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
9266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            s += i;
9276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
9286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else if( ksize == 3 )
9296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
9306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( kx[0] == 2 && kx[1] == 1 )
9316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( ; i <= width - 2; i += 2, s += 2 )
9326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
9336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int s0 = s[-cn] + s[0]*2 + s[cn], s1 = s[1-cn] + s[1]*2 + s[1+cn];
9346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    dst[i] = s0; dst[i+1] = s1;
9356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
9366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if( kx[0] == 10 && kx[1] == 3 )
9376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( ; i <= width - 2; i += 2, s += 2 )
9386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
9396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int s0 = s[0]*10 + (s[-cn] + s[cn])*3, s1 = s[1]*10 + (s[1-cn] + s[1+cn])*3;
9406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    dst[i] = s0; dst[i+1] = s1;
9416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
9426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if( kx[0] == 2*64 && kx[1] == 1*64 )
9436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( ; i <= width - 2; i += 2, s += 2 )
9446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
9456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int s0 = (s[0]*2 + s[-cn] + s[cn]) << 6;
9466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int s1 = (s[1]*2 + s[1-cn] + s[1+cn]) << 6;
9476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    dst[i] = s0; dst[i+1] = s1;
9486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
9496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
9506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
9516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int k0 = kx[0], k1 = kx[1];
9526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( ; i <= width - 2; i += 2, s += 2 )
9536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
9546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int s0 = s[0]*k0 + (s[-cn] + s[cn])*k1, s1 = s[1]*k0 + (s[1-cn] + s[1+cn])*k1;
9556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    dst[i] = s0; dst[i+1] = s1;
9566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
9576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
9586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
9596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else if( ksize == 5 )
9606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
9616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int k0 = kx[0], k1 = kx[1], k2 = kx[2];
9626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( k0 == 6*16 && k1 == 4*16 && k2 == 1*16 )
9636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( ; i <= width - 2; i += 2, s += 2 )
9646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
9656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int s0 = (s[0]*6 + (s[-cn] + s[cn])*4 + (s[-cn*2] + s[cn*2])*1) << 4;
9666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int s1 = (s[1]*6 + (s[1-cn] + s[1+cn])*4 + (s[1-cn*2] + s[1+cn*2])*1) << 4;
9676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    dst[i] = s0; dst[i+1] = s1;
9686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
9696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
9706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( ; i <= width - 2; i += 2, s += 2 )
9716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
9726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int s0 = s[0]*k0 + (s[-cn] + s[cn])*k1 + (s[-cn*2] + s[cn*2])*k2;
9736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int s1 = s[1]*k0 + (s[1-cn] + s[1+cn])*k1 + (s[1-cn*2] + s[1+cn*2])*k2;
9746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    dst[i] = s0; dst[i+1] = s1;
9756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
9766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
9776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
9786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; i <= width - 4; i += 4, s += 4 )
9796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
9806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int f = kx[0];
9816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int s0 = f*s[0], s1 = f*s[1], s2 = f*s[2], s3 = f*s[3];
9826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k = 1, j = cn; k <= ksize2; k++, j += cn )
9836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
9846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    f = kx[k];
9856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s0 += f*(s[j] + s[-j]); s1 += f*(s[j+1] + s[-j+1]);
9866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s2 += f*(s[j+2] + s[-j+2]); s3 += f*(s[j+3] + s[-j+3]);
9876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
9886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i] = s0; dst[i+1] = s1;
9906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i+2] = s2; dst[i+3] = s3;
9916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
9926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ; i < width; i++, s++ )
9946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
9956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int s0 = kx[0]*s[0];
9966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( k = 1, j = cn; k <= ksize2; k++, j += cn )
9976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s0 += kx[k]*(s[j] + s[-j]);
9986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst[i] = s0;
9996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
10006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
10016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
10026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
10036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( ksize == 3 && kx[0] == 0 && kx[1] == 1 )
10046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; i <= width - 2; i += 2, s += 2 )
10056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
10066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int s0 = s[cn] - s[-cn], s1 = s[1+cn] - s[1-cn];
10076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i] = s0; dst[i+1] = s1;
10086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
10096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
10106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; i <= width - 4; i += 4, s += 4 )
10116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
10126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int s0 = 0, s1 = 0, s2 = 0, s3 = 0;
10136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k = 1, j = cn; k <= ksize2; k++, j += cn )
10146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
10156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int f = kx[k];
10166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s0 += f*(s[j] - s[-j]); s1 += f*(s[j+1] - s[-j+1]);
10176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s2 += f*(s[j+2] - s[-j+2]); s3 += f*(s[j+3] - s[-j+3]);
10186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
10196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i] = s0; dst[i+1] = s1;
10216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i+2] = s2; dst[i+3] = s3;
10226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
10236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ; i < width; i++, s++ )
10256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
10266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int s0 = kx[0]*s[0];
10276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( k = 1, j = cn; k <= ksize2; k++, j += cn )
10286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s0 += kx[k]*(s[j] - s[-j]);
10296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst[i] = s0;
10306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
10316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
10326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
10336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define ICV_FILTER_ROW( flavor, srctype, dsttype, load_macro )      \
10366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void                                                         \
10376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterRow_##flavor(const srctype* src, dsttype* dst, void*params)\
10386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{                                                                   \
10396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvSepFilter* state = (const CvSepFilter*)params;          \
10406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvMat* _kx = state->get_x_kernel();                       \
10416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const dsttype* kx = (const dsttype*)(_kx->data.ptr);            \
10426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int ksize = _kx->cols + _kx->rows - 1;                          \
10436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i = 0, k, width = state->get_width();                       \
10446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int cn = CV_MAT_CN(state->get_src_type());                      \
10456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const srctype* s;                                               \
10466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                    \
10476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    width *= cn;                                                    \
10486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                    \
10496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( ; i <= width - 4; i += 4 )                                 \
10506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {                                                               \
10516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        double f = kx[0];                                           \
10526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        double s0=f*load_macro(src[i]), s1=f*load_macro(src[i+1]),  \
10536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s2=f*load_macro(src[i+2]), s3=f*load_macro(src[i+3]);\
10546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( k = 1, s = src + i + cn; k < ksize; k++, s += cn )     \
10556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {                                                           \
10566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            f = kx[k];                                              \
10576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            s0 += f*load_macro(s[0]);                               \
10586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            s1 += f*load_macro(s[1]);                               \
10596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            s2 += f*load_macro(s[2]);                               \
10606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            s3 += f*load_macro(s[3]);                               \
10616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }                                                           \
10626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dst[i] = (dsttype)s0; dst[i+1] = (dsttype)s1;               \
10636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dst[i+2] = (dsttype)s2; dst[i+3] = (dsttype)s3;             \
10646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }                                                               \
10656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                    \
10666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( ; i < width; i++ )                                         \
10676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {                                                               \
10686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        double s0 = (double)kx[0]*load_macro(src[i]);               \
10696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( k = 1, s = src + i + cn; k < ksize; k++, s += cn )     \
10706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            s0 += (double)kx[k]*load_macro(s[0]);                   \
10716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dst[i] = (dsttype)s0;                                       \
10726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }                                                               \
10736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
10746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennICV_FILTER_ROW( 8u32f, uchar, float, CV_8TO32F )
10776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennICV_FILTER_ROW( 16s32f, short, float, CV_NOP )
10786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennICV_FILTER_ROW( 16u32f, ushort, float, CV_NOP )
10796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennICV_FILTER_ROW( 32f, float, float, CV_NOP )
10806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define ICV_FILTER_ROW_SYMM( flavor, srctype, dsttype, load_macro ) \
10836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void                                                         \
10846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterRowSymm_##flavor( const srctype* src,                      \
10856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           dsttype* dst, void* params )             \
10866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{                                                                   \
10876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvSepFilter* state = (const CvSepFilter*)params;          \
10886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvMat* _kx = state->get_x_kernel();                       \
10896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const dsttype* kx = (const dsttype*)(_kx->data.ptr);            \
10906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int ksize = _kx->cols + _kx->rows - 1;                          \
10916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i = 0, j, k, width = state->get_width();                    \
10926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int cn = CV_MAT_CN(state->get_src_type());                      \
10936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int is_symm=state->get_x_kernel_flags()&CvSepFilter::SYMMETRICAL;\
10946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int ksize2 = ksize/2, ksize2n = ksize2*cn;                      \
10956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const srctype* s = src + ksize2n;                               \
10966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                    \
10976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    kx += ksize2;                                                   \
10986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    width *= cn;                                                    \
10996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                    \
11006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( is_symm )                                                   \
11016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {                                                               \
11026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ; i <= width - 4; i += 4, s += 4 )                     \
11036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {                                                           \
11046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double f = kx[0];                                       \
11056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double s0=f*load_macro(s[0]), s1=f*load_macro(s[1]),    \
11066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                   s2=f*load_macro(s[2]), s3=f*load_macro(s[3]);    \
11076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( k = 1, j = cn; k <= ksize2; k++, j += cn )         \
11086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {                                                       \
11096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                f = kx[k];                                          \
11106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s0 += f*load_macro(s[j] + s[-j]);                   \
11116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s1 += f*load_macro(s[j+1] + s[-j+1]);               \
11126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s2 += f*load_macro(s[j+2] + s[-j+2]);               \
11136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s3 += f*load_macro(s[j+3] + s[-j+3]);               \
11146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }                                                       \
11156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                    \
11166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst[i] = (dsttype)s0; dst[i+1] = (dsttype)s1;           \
11176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst[i+2] = (dsttype)s2; dst[i+3] = (dsttype)s3;         \
11186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }                                                           \
11196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                    \
11206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ; i < width; i++, s++ )                                \
11216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {                                                           \
11226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double s0 = (double)kx[0]*load_macro(s[0]);             \
11236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( k = 1, j = cn; k <= ksize2; k++, j += cn )         \
11246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s0 += (double)kx[k]*load_macro(s[j] + s[-j]);       \
11256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst[i] = (dsttype)s0;                                   \
11266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }                                                           \
11276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }                                                               \
11286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else                                                            \
11296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {                                                               \
11306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ; i <= width - 4; i += 4, s += 4 )                     \
11316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {                                                           \
11326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double s0 = 0, s1 = 0, s2 = 0, s3 = 0;                  \
11336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( k = 1, j = cn; k <= ksize2; k++, j += cn )         \
11346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {                                                       \
11356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                double f = kx[k];                                   \
11366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s0 += f*load_macro(s[j] - s[-j]);                   \
11376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s1 += f*load_macro(s[j+1] - s[-j+1]);               \
11386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s2 += f*load_macro(s[j+2] - s[-j+2]);               \
11396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s3 += f*load_macro(s[j+3] - s[-j+3]);               \
11406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }                                                       \
11416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                    \
11426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst[i] = (dsttype)s0; dst[i+1] = (dsttype)s1;           \
11436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst[i+2] = (dsttype)s2; dst[i+3] = (dsttype)s3;         \
11446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }                                                           \
11456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                    \
11466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ; i < width; i++, s++ )                                \
11476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {                                                           \
11486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double s0 = 0;                                          \
11496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( k = 1, j = cn; k <= ksize2; k++, j += cn )         \
11506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s0 += (double)kx[k]*load_macro(s[j] - s[-j]);       \
11516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst[i] = (dsttype)s0;                                   \
11526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }                                                           \
11536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }                                                               \
11546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
11556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennICV_FILTER_ROW_SYMM( 8u32f, uchar, float, CV_8TO32F )
11586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennICV_FILTER_ROW_SYMM( 16s32f, short, float, CV_NOP )
11596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennICV_FILTER_ROW_SYMM( 16u32f, ushort, float, CV_NOP )
11606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
11626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterRowSymm_32f( const float* src, float* dst, void* params )
11636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
11646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvSepFilter* state = (const CvSepFilter*)params;
11656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvMat* _kx = state->get_x_kernel();
11666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const float* kx = _kx->data.fl;
11676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int ksize = _kx->cols + _kx->rows - 1;
11686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i = 0, j, k, width = state->get_width();
11696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int cn = CV_MAT_CN(state->get_src_type());
11706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int ksize2 = ksize/2, ksize2n = ksize2*cn;
11716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int is_symm = state->get_x_kernel_flags() & CvSepFilter::SYMMETRICAL;
11726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const float* s = src + ksize2n;
11736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    kx += ksize2;
11756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    width *= cn;
11766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( is_symm )
11786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
11796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( ksize == 3 && fabs(kx[0]-2.) <= FLT_EPSILON && fabs(kx[1]-1.) <= FLT_EPSILON )
11806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; i <= width - 2; i += 2, s += 2 )
11816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
11826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                float s0 = s[-cn] + s[0]*2 + s[cn], s1 = s[1-cn] + s[1]*2 + s[1+cn];
11836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i] = s0; dst[i+1] = s1;
11846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
11856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else if( ksize == 3 && fabs(kx[0]-10.) <= FLT_EPSILON && fabs(kx[1]-3.) <= FLT_EPSILON )
11866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; i <= width - 2; i += 2, s += 2 )
11876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
11886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                float s0 = s[0]*10 + (s[-cn] + s[cn])*3, s1 = s[1]*10 + (s[1-cn] + s[1+cn])*3;
11896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i] = s0; dst[i+1] = s1;
11906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
11916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
11926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; i <= width - 4; i += 4, s += 4 )
11936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
11946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                double f = kx[0];
11956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                double s0 = f*s[0], s1 = f*s[1], s2 = f*s[2], s3 = f*s[3];
11966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k = 1, j = cn; k <= ksize2; k++, j += cn )
11976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
11986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    f = kx[k];
11996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s0 += f*(s[j] + s[-j]); s1 += f*(s[j+1] + s[-j+1]);
12006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s2 += f*(s[j+2] + s[-j+2]); s3 += f*(s[j+3] + s[-j+3]);
12016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
12026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i] = (float)s0; dst[i+1] = (float)s1;
12046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i+2] = (float)s2; dst[i+3] = (float)s3;
12056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
12066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ; i < width; i++, s++ )
12086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
12096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double s0 = (double)kx[0]*s[0];
12106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( k = 1, j = cn; k <= ksize2; k++, j += cn )
12116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s0 += (double)kx[k]*(s[j] + s[-j]);
12126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst[i] = (float)s0;
12136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
12146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
12156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
12166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
12176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( ksize == 3 && fabs(kx[0]) <= FLT_EPSILON && fabs(kx[1]-1.) <= FLT_EPSILON )
12186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; i <= width - 2; i += 2, s += 2 )
12196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
12206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                float s0 = s[cn] - s[-cn], s1 = s[1+cn] - s[1-cn];
12216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i] = s0; dst[i+1] = s1;
12226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
12236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
12246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; i <= width - 4; i += 4, s += 4 )
12256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
12266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                double s0 = 0, s1 = 0, s2 = 0, s3 = 0;
12276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k = 1, j = cn; k <= ksize2; k++, j += cn )
12286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
12296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    double f = kx[k];
12306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s0 += f*(s[j] - s[-j]); s1 += f*(s[j+1] - s[-j+1]);
12316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s2 += f*(s[j+2] - s[-j+2]); s3 += f*(s[j+3] - s[-j+3]);
12326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
12336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i] = (float)s0; dst[i+1] = (float)s1;
12356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i+2] = (float)s2; dst[i+3] = (float)s3;
12366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
12376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ; i < width; i++, s++ )
12396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
12406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double s0 = (double)kx[0]*s[0];
12416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( k = 1, j = cn; k <= ksize2; k++, j += cn )
12426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s0 += (double)kx[k]*(s[j] - s[-j]);
12436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst[i] = (float)s0;
12446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
12456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
12466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
12476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
12506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterColSymm_32s8u( const int** src, uchar* dst, int dst_step, int count, void* params )
12516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
12526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvSepFilter* state = (const CvSepFilter*)params;
12536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvMat* _ky = state->get_y_kernel();
12546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const int* ky = _ky->data.i;
12556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int ksize = _ky->cols + _ky->rows - 1, ksize2 = ksize/2;
12566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, k, width = state->get_width();
12576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int cn = CV_MAT_CN(state->get_src_type());
12586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    width *= cn;
12606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    src += ksize2;
12616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ky += ksize2;
12626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( ; count--; dst += dst_step, src++ )
12646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
12656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( ksize == 3 )
12666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
12676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const int* sptr0 = src[-1], *sptr1 = src[0], *sptr2 = src[1];
12686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int k0 = ky[0], k1 = ky[1];
12696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i <= width - 2; i += 2 )
12706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
12716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int s0 = sptr1[i]*k0 + (sptr0[i] + sptr2[i])*k1;
12726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int s1 = sptr1[i+1]*k0 + (sptr0[i+1] + sptr2[i+1])*k1;
12736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s0 = CV_DESCALE(s0, FILTER_BITS*2);
12746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s1 = CV_DESCALE(s1, FILTER_BITS*2);
12756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i] = (uchar)s0; dst[i+1] = (uchar)s1;
12766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
12776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
12786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else if( ksize == 5 )
12796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
12806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const int* sptr0 = src[-2], *sptr1 = src[-1],
12816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                *sptr2 = src[0], *sptr3 = src[1], *sptr4 = src[2];
12826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int k0 = ky[0], k1 = ky[1], k2 = ky[2];
12836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i <= width - 2; i += 2 )
12846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
12856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int s0 = sptr2[i]*k0 + (sptr1[i] + sptr3[i])*k1 + (sptr0[i] + sptr4[i])*k2;
12866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int s1 = sptr2[i+1]*k0 + (sptr1[i+1] + sptr3[i+1])*k1 + (sptr0[i+1] + sptr4[i+1])*k2;
12876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s0 = CV_DESCALE(s0, FILTER_BITS*2);
12886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s1 = CV_DESCALE(s1, FILTER_BITS*2);
12896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i] = (uchar)s0; dst[i+1] = (uchar)s1;
12906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
12916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
12926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
12936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i <= width - 4; i += 4 )
12946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
12956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int f = ky[0];
12966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                const int* sptr = src[0] + i, *sptr2;
12976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int s0 = f*sptr[0], s1 = f*sptr[1], s2 = f*sptr[2], s3 = f*sptr[3];
12986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k = 1; k <= ksize2; k++ )
12996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
13006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    sptr = src[k] + i;
13016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    sptr2 = src[-k] + i;
13026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    f = ky[k];
13036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s0 += f*(sptr[0] + sptr2[0]);
13046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s1 += f*(sptr[1] + sptr2[1]);
13056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s2 += f*(sptr[2] + sptr2[2]);
13066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s3 += f*(sptr[3] + sptr2[3]);
13076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
13086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s0 = CV_DESCALE(s0, FILTER_BITS*2);
13106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s1 = CV_DESCALE(s1, FILTER_BITS*2);
13116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i] = (uchar)s0; dst[i+1] = (uchar)s1;
13126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s2 = CV_DESCALE(s2, FILTER_BITS*2);
13136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s3 = CV_DESCALE(s3, FILTER_BITS*2);
13146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i+2] = (uchar)s2; dst[i+3] = (uchar)s3;
13156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
13166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ; i < width; i++ )
13186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
13196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int s0 = ky[0]*src[0][i];
13206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( k = 1; k <= ksize2; k++ )
13216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s0 += ky[k]*(src[k][i] + src[-k][i]);
13226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            s0 = CV_DESCALE(s0, FILTER_BITS*2);
13246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst[i] = (uchar)s0;
13256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
13266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
13276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
13286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
13316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterColSymm_32s16s( const int** src, short* dst,
13326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                         int dst_step, int count, void* params )
13336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
13346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvSepFilter* state = (const CvSepFilter*)params;
13356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvMat* _ky = state->get_y_kernel();
13366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const int* ky = (const int*)_ky->data.ptr;
13376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int ksize = _ky->cols + _ky->rows - 1, ksize2 = ksize/2;
13386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i = 0, k, width = state->get_width();
13396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int cn = CV_MAT_CN(state->get_src_type());
13406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int is_symm = state->get_y_kernel_flags() & CvSepFilter::SYMMETRICAL;
13416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int is_1_2_1 = is_symm && ksize == 3 && ky[1] == 2 && ky[2] == 1;
13426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int is_3_10_3 = is_symm && ksize == 3 && ky[1] == 10 && ky[2] == 3;
13436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int is_m1_0_1 = !is_symm && ksize == 3 && ky[1] == 0 &&
13446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ky[2]*ky[2] == 1 ? (ky[2] > 0 ? 1 : -1) : 0;
13456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    width *= cn;
13476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    src += ksize2;
13486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ky += ksize2;
13496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dst_step /= sizeof(dst[0]);
13506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( is_symm )
13526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
13536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ; count--; dst += dst_step, src++ )
13546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
13556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( is_1_2_1 )
13566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
13576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                const int *src0 = src[-1], *src1 = src[0], *src2 = src[1];
13586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( i = 0; i <= width - 2; i += 2 )
13606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
13616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int s0 = src0[i] + src1[i]*2 + src2[i],
13626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        s1 = src0[i+1] + src1[i+1]*2 + src2[i+1];
13636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    dst[i] = (short)s0; dst[i+1] = (short)s1;
13656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
13666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
13676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if( is_3_10_3 )
13686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
13696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                const int *src0 = src[-1], *src1 = src[0], *src2 = src[1];
13706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( i = 0; i <= width - 2; i += 2 )
13726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
13736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int s0 = src1[i]*10 + (src0[i] + src2[i])*3,
13746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        s1 = src1[i+1]*10 + (src0[i+1] + src2[i+1])*3;
13756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    dst[i] = (short)s0; dst[i+1] = (short)s1;
13776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
13786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
13796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
13806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( i = 0; i <= width - 4; i += 4 )
13816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
13826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int f = ky[0];
13836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    const int* sptr = src[0] + i, *sptr2;
13846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int s0 = f*sptr[0], s1 = f*sptr[1],
13856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        s2 = f*sptr[2], s3 = f*sptr[3];
13866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    for( k = 1; k <= ksize2; k++ )
13876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
13886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        sptr = src[k] + i; sptr2 = src[-k] + i; f = ky[k];
13896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        s0 += f*(sptr[0] + sptr2[0]); s1 += f*(sptr[1] + sptr2[1]);
13906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        s2 += f*(sptr[2] + sptr2[2]); s3 += f*(sptr[3] + sptr2[3]);
13916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
13926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    dst[i] = CV_CAST_16S(s0); dst[i+1] = CV_CAST_16S(s1);
13946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    dst[i+2] = CV_CAST_16S(s2); dst[i+3] = CV_CAST_16S(s3);
13956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
13966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; i < width; i++ )
13986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
13996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int s0 = ky[0]*src[0][i];
14006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k = 1; k <= ksize2; k++ )
14016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s0 += ky[k]*(src[k][i] + src[-k][i]);
14026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i] = CV_CAST_16S(s0);
14036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
14046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
14056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
14066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
14076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
14086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ; count--; dst += dst_step, src++ )
14096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
14106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( is_m1_0_1 )
14116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
14126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                const int *src0 = src[-is_m1_0_1], *src2 = src[is_m1_0_1];
14136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( i = 0; i <= width - 2; i += 2 )
14156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
14166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int s0 = src2[i] - src0[i], s1 = src2[i+1] - src0[i+1];
14176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    dst[i] = (short)s0; dst[i+1] = (short)s1;
14186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
14196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
14206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
14216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( i = 0; i <= width - 4; i += 4 )
14226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
14236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int f = ky[0];
14246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    const int* sptr = src[0] + i, *sptr2;
14256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int s0 = 0, s1 = 0, s2 = 0, s3 = 0;
14266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    for( k = 1; k <= ksize2; k++ )
14276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
14286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        sptr = src[k] + i; sptr2 = src[-k] + i; f = ky[k];
14296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        s0 += f*(sptr[0] - sptr2[0]); s1 += f*(sptr[1] - sptr2[1]);
14306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        s2 += f*(sptr[2] - sptr2[2]); s3 += f*(sptr[3] - sptr2[3]);
14316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
14326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    dst[i] = CV_CAST_16S(s0); dst[i+1] = CV_CAST_16S(s1);
14346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    dst[i+2] = CV_CAST_16S(s2); dst[i+3] = CV_CAST_16S(s3);
14356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
14366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; i < width; i++ )
14386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
14396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int s0 = ky[0]*src[0][i];
14406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k = 1; k <= ksize2; k++ )
14416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s0 += ky[k]*(src[k][i] - src[-k][i]);
14426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i] = CV_CAST_16S(s0);
14436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
14446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
14456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
14466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
14476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define ICV_FILTER_COL( flavor, srctype, dsttype, worktype,     \
14506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        cast_macro1, cast_macro2 )              \
14516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void                                                     \
14526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterCol_##flavor( const srctype** src, dsttype* dst,       \
14536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                       int dst_step, int count, void* params )  \
14546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{                                                               \
14556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvSepFilter* state = (const CvSepFilter*)params;      \
14566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvMat* _ky = state->get_y_kernel();                   \
14576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const srctype* ky = (const srctype*)_ky->data.ptr;          \
14586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int ksize = _ky->cols + _ky->rows - 1;                      \
14596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, k, width = state->get_width();                       \
14606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int cn = CV_MAT_CN(state->get_src_type());                  \
14616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                \
14626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    width *= cn;                                                \
14636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dst_step /= sizeof(dst[0]);                                 \
14646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                \
14656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( ; count--; dst += dst_step, src++ )                    \
14666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {                                                           \
14676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i <= width - 4; i += 4 )                    \
14686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {                                                       \
14696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double f = ky[0];                                   \
14706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const srctype* sptr = src[0] + i;                   \
14716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double s0 = f*sptr[0], s1 = f*sptr[1],              \
14726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                   s2 = f*sptr[2], s3 = f*sptr[3];              \
14736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            worktype t0, t1;                                    \
14746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( k = 1; k < ksize; k++ )                        \
14756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {                                                   \
14766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                sptr = src[k] + i; f = ky[k];                   \
14776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s0 += f*sptr[0]; s1 += f*sptr[1];               \
14786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s2 += f*sptr[2]; s3 += f*sptr[3];               \
14796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }                                                   \
14806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                \
14816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            t0 = cast_macro1(s0); t1 = cast_macro1(s1);         \
14826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst[i]=cast_macro2(t0); dst[i+1]=cast_macro2(t1);   \
14836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            t0 = cast_macro1(s2); t1 = cast_macro1(s3);         \
14846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst[i+2]=cast_macro2(t0); dst[i+3]=cast_macro2(t1); \
14856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }                                                       \
14866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                \
14876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ; i < width; i++ )                                 \
14886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {                                                       \
14896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double s0 = (double)ky[0]*src[0][i];                \
14906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            worktype t0;                                        \
14916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( k = 1; k < ksize; k++ )                        \
14926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s0 += (double)ky[k]*src[k][i];                  \
14936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            t0 = cast_macro1(s0);                               \
14946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst[i] = cast_macro2(t0);                           \
14956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }                                                       \
14966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }                                                           \
14976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
14986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennICV_FILTER_COL( 32f8u, float, uchar, int, cvRound, CV_CAST_8U )
15016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennICV_FILTER_COL( 32f16s, float, short, int, cvRound, CV_CAST_16S )
15026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennICV_FILTER_COL( 32f16u, float, ushort, int, cvRound, CV_CAST_16U )
15036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define ICV_FILTER_COL_SYMM( flavor, srctype, dsttype, worktype,    \
15056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                             cast_macro1, cast_macro2 )             \
15066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void                                                         \
15076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterColSymm_##flavor( const srctype** src, dsttype* dst,       \
15086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           int dst_step, int count, void* params )  \
15096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{                                                                   \
15106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvSepFilter* state = (const CvSepFilter*)params;          \
15116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvMat* _ky = state->get_y_kernel();                       \
15126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const srctype* ky = (const srctype*)_ky->data.ptr;              \
15136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int ksize = _ky->cols + _ky->rows - 1, ksize2 = ksize/2;        \
15146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, k, width = state->get_width();                           \
15156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int cn = CV_MAT_CN(state->get_src_type());                      \
15166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int is_symm = state->get_y_kernel_flags() & CvSepFilter::SYMMETRICAL;\
15176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                    \
15186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    width *= cn;                                                    \
15196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    src += ksize2;                                                  \
15206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ky += ksize2;                                                   \
15216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dst_step /= sizeof(dst[0]);                                     \
15226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                    \
15236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( is_symm )                                                   \
15246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {                                                               \
15256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ; count--; dst += dst_step, src++ )                    \
15266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {                                                           \
15276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i <= width - 4; i += 4 )                    \
15286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {                                                       \
15296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                double f = ky[0];                                   \
15306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                const srctype* sptr = src[0] + i, *sptr2;           \
15316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                double s0 = f*sptr[0], s1 = f*sptr[1],              \
15326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                       s2 = f*sptr[2], s3 = f*sptr[3];              \
15336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                worktype t0, t1;                                    \
15346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k = 1; k <= ksize2; k++ )                      \
15356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {                                                   \
15366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    sptr = src[k] + i;                              \
15376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    sptr2 = src[-k] + i;                            \
15386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    f = ky[k];                                      \
15396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s0 += f*(sptr[0] + sptr2[0]);                   \
15406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s1 += f*(sptr[1] + sptr2[1]);                   \
15416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s2 += f*(sptr[2] + sptr2[2]);                   \
15426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s3 += f*(sptr[3] + sptr2[3]);                   \
15436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }                                                   \
15446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                    \
15456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                t0 = cast_macro1(s0); t1 = cast_macro1(s1);         \
15466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i]=cast_macro2(t0); dst[i+1]=cast_macro2(t1);   \
15476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                t0 = cast_macro1(s2); t1 = cast_macro1(s3);         \
15486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i+2]=cast_macro2(t0); dst[i+3]=cast_macro2(t1); \
15496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }                                                       \
15506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                    \
15516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; i < width; i++ )                                 \
15526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {                                                       \
15536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                double s0 = (double)ky[0]*src[0][i];                \
15546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                worktype t0;                                        \
15556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k = 1; k <= ksize2; k++ )                      \
15566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s0 += (double)ky[k]*(src[k][i] + src[-k][i]);   \
15576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                t0 = cast_macro1(s0);                               \
15586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i] = cast_macro2(t0);                           \
15596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }                                                       \
15606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }                                                           \
15616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }                                                               \
15626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else                                                            \
15636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {                                                               \
15646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ; count--; dst += dst_step, src++ )                    \
15656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {                                                           \
15666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i <= width - 4; i += 4 )                    \
15676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {                                                       \
15686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                double f = ky[0];                                   \
15696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                const srctype* sptr = src[0] + i, *sptr2;           \
15706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                double s0 = 0, s1 = 0, s2 = 0, s3 = 0;              \
15716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                worktype t0, t1;                                    \
15726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k = 1; k <= ksize2; k++ )                      \
15736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {                                                   \
15746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    sptr = src[k] + i;                              \
15756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    sptr2 = src[-k] + i;                            \
15766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    f = ky[k];                                      \
15776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s0 += f*(sptr[0] - sptr2[0]);                   \
15786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s1 += f*(sptr[1] - sptr2[1]);                   \
15796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s2 += f*(sptr[2] - sptr2[2]);                   \
15806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s3 += f*(sptr[3] - sptr2[3]);                   \
15816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }                                                   \
15826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                    \
15836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                t0 = cast_macro1(s0); t1 = cast_macro1(s1);         \
15846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i]=cast_macro2(t0); dst[i+1]=cast_macro2(t1);   \
15856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                t0 = cast_macro1(s2); t1 = cast_macro1(s3);         \
15866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i+2]=cast_macro2(t0); dst[i+3]=cast_macro2(t1); \
15876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }                                                       \
15886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                    \
15896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; i < width; i++ )                                 \
15906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {                                                       \
15916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                double s0 = (double)ky[0]*src[0][i];                \
15926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                worktype t0;                                        \
15936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k = 1; k <= ksize2; k++ )                      \
15946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s0 += (double)ky[k]*(src[k][i] - src[-k][i]);   \
15956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                t0 = cast_macro1(s0);                               \
15966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i] = cast_macro2(t0);                           \
15976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }                                                       \
15986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }                                                           \
15996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }                                                               \
16006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
16016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennICV_FILTER_COL_SYMM( 32f8u, float, uchar, int, cvRound, CV_CAST_8U )
16046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennICV_FILTER_COL_SYMM( 32f16s, float, short, int, cvRound, CV_CAST_16S )
16056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennICV_FILTER_COL_SYMM( 32f16u, float, ushort, int, cvRound, CV_CAST_16U )
16066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
16096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterCol_32f( const float** src, float* dst,
16106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  int dst_step, int count, void* params )
16116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
16126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvSepFilter* state = (const CvSepFilter*)params;
16136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvMat* _ky = state->get_y_kernel();
16146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const float* ky = (const float*)_ky->data.ptr;
16156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int ksize = _ky->cols + _ky->rows - 1;
16166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, k, width = state->get_width();
16176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int cn = CV_MAT_CN(state->get_src_type());
16186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    width *= cn;
16206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dst_step /= sizeof(dst[0]);
16216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( ; count--; dst += dst_step, src++ )
16236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
16246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i <= width - 4; i += 4 )
16256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
16266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double f = ky[0];
16276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const float* sptr = src[0] + i;
16286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double s0 = f*sptr[0], s1 = f*sptr[1],
16296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                   s2 = f*sptr[2], s3 = f*sptr[3];
16306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( k = 1; k < ksize; k++ )
16316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
16326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                sptr = src[k] + i; f = ky[k];
16336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s0 += f*sptr[0]; s1 += f*sptr[1];
16346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s2 += f*sptr[2]; s3 += f*sptr[3];
16356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
16366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst[i] = (float)s0; dst[i+1] = (float)s1;
16386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst[i+2] = (float)s2; dst[i+3] = (float)s3;
16396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
16406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ; i < width; i++ )
16426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
16436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double s0 = (double)ky[0]*src[0][i];
16446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( k = 1; k < ksize; k++ )
16456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s0 += (double)ky[k]*src[k][i];
16466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst[i] = (float)s0;
16476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
16486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
16496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
16506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
16536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterColSymm_32f( const float** src, float* dst,
16546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                      int dst_step, int count, void* params )
16556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
16566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvSepFilter* state = (const CvSepFilter*)params;
16576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvMat* _ky = state->get_y_kernel();
16586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const float* ky = (const float*)_ky->data.ptr;
16596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int ksize = _ky->cols + _ky->rows - 1, ksize2 = ksize/2;
16606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i = 0, k, width = state->get_width();
16616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int cn = CV_MAT_CN(state->get_src_type());
16626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int is_symm = state->get_y_kernel_flags() & CvSepFilter::SYMMETRICAL;
16636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int is_1_2_1 = is_symm && ksize == 3 &&
16646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fabs(ky[1] - 2.) <= FLT_EPSILON && fabs(ky[2] - 1.) <= FLT_EPSILON;
16656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int is_3_10_3 = is_symm && ksize == 3 &&
16666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fabs(ky[1] - 10.) <= FLT_EPSILON && fabs(ky[2] - 3.) <= FLT_EPSILON;
16676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int is_m1_0_1 = !is_symm && ksize == 3 &&
16686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fabs(ky[1]) <= FLT_EPSILON && fabs(ky[2]*ky[2] - 1.) <= FLT_EPSILON ?
16696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            (ky[2] > 0 ? 1 : -1) : 0;
16706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    width *= cn;
16726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    src += ksize2;
16736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ky += ksize2;
16746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dst_step /= sizeof(dst[0]);
16756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( is_symm )
16776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
16786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ; count--; dst += dst_step, src++ )
16796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
16806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( is_1_2_1 )
16816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
16826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                const float *src0 = src[-1], *src1 = src[0], *src2 = src[1];
16836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( i = 0; i <= width - 4; i += 4 )
16856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
16866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    float s0 = src0[i] + src1[i]*2 + src2[i],
16876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          s1 = src0[i+1] + src1[i+1]*2 + src2[i+1],
16886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          s2 = src0[i+2] + src1[i+2]*2 + src2[i+2],
16896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          s3 = src0[i+3] + src1[i+3]*2 + src2[i+3];
16906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    dst[i] = s0; dst[i+1] = s1;
16926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    dst[i+2] = s2; dst[i+3] = s3;
16936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
16946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
16956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if( is_3_10_3 )
16966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
16976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                const float *src0 = src[-1], *src1 = src[0], *src2 = src[1];
16986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( i = 0; i <= width - 4; i += 4 )
17006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
17016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    float s0 = src1[i]*10 + (src0[i] + src2[i])*3,
17026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          s1 = src1[i+1]*10 + (src0[i+1] + src2[i+1])*3,
17036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          s2 = src1[i+2]*10 + (src0[i+2] + src2[i+2])*3,
17046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          s3 = src1[i+3]*10 + (src0[i+3] + src2[i+3])*3;
17056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    dst[i] = s0; dst[i+1] = s1;
17076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    dst[i+2] = s2; dst[i+3] = s3;
17086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
17096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
17106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
17116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( i = 0; i <= width - 4; i += 4 )
17126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
17136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    double f = ky[0];
17146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    const float* sptr = src[0] + i, *sptr2;
17156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    double s0 = f*sptr[0], s1 = f*sptr[1],
17166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           s2 = f*sptr[2], s3 = f*sptr[3];
17176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    for( k = 1; k <= ksize2; k++ )
17186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
17196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        sptr = src[k] + i; sptr2 = src[-k] + i; f = ky[k];
17206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        s0 += f*(sptr[0] + sptr2[0]); s1 += f*(sptr[1] + sptr2[1]);
17216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        s2 += f*(sptr[2] + sptr2[2]); s3 += f*(sptr[3] + sptr2[3]);
17226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
17236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    dst[i] = (float)s0; dst[i+1] = (float)s1;
17256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    dst[i+2] = (float)s2; dst[i+3] = (float)s3;
17266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
17276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; i < width; i++ )
17296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
17306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                double s0 = (double)ky[0]*src[0][i];
17316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k = 1; k <= ksize2; k++ )
17326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s0 += (double)ky[k]*(src[k][i] + src[-k][i]);
17336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i] = (float)s0;
17346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
17356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
17366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
17376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
17386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
17396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ; count--; dst += dst_step, src++ )
17406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
17416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( is_m1_0_1 )
17426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
17436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                const float *src0 = src[-is_m1_0_1], *src2 = src[is_m1_0_1];
17446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( i = 0; i <= width - 4; i += 4 )
17466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
17476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    float s0 = src2[i] - src0[i], s1 = src2[i+1] - src0[i+1],
17486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          s2 = src2[i+2] - src0[i+2], s3 = src2[i+3] - src0[i+3];
17496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    dst[i] = s0; dst[i+1] = s1;
17506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    dst[i+2] = s2; dst[i+3] = s3;
17516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
17526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
17536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
17546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( i = 0; i <= width - 4; i += 4 )
17556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
17566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    double f = ky[0];
17576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    const float* sptr = src[0] + i, *sptr2;
17586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    double s0 = 0, s1 = 0, s2 = 0, s3 = 0;
17596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    for( k = 1; k <= ksize2; k++ )
17606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
17616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        sptr = src[k] + i; sptr2 = src[-k] + i; f = ky[k];
17626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        s0 += f*(sptr[0] - sptr2[0]); s1 += f*(sptr[1] - sptr2[1]);
17636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        s2 += f*(sptr[2] - sptr2[2]); s3 += f*(sptr[3] - sptr2[3]);
17646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
17656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    dst[i] = (float)s0; dst[i+1] = (float)s1;
17676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    dst[i+2] = (float)s2; dst[i+3] = (float)s3;
17686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
17696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; i < width; i++ )
17716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
17726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                double s0 = (double)ky[0]*src[0][i];
17736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k = 1; k <= ksize2; k++ )
17746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s0 += (double)ky[k]*(src[k][i] - src[-k][i]);
17756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i] = (float)s0;
17766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
17776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
17786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
17796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
17806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define SMALL_GAUSSIAN_SIZE  7
17836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvSepFilter::init_gaussian_kernel( CvMat* kernel, double sigma )
17856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
17866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    static const float small_gaussian_tab[][SMALL_GAUSSIAN_SIZE/2+1] =
17876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
17886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {1.f},
17896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {0.5f, 0.25f},
17906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {0.375f, 0.25f, 0.0625f},
17916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {0.28125f, 0.21875f, 0.109375f, 0.03125f}
17926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    };
17936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "CvSepFilter::init_gaussian_kernel" );
17956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
17976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int type, i, n, step;
17996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const float* fixed_kernel = 0;
18006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double sigmaX, scale2X, sum;
18016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    float* cf;
18026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double* cd;
18036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_IS_MAT(kernel) )
18056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "kernel is not a valid matrix" );
18066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    type = CV_MAT_TYPE(kernel->type);
18086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( (kernel->cols != 1 && kernel->rows != 1) ||
18106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        (kernel->cols + kernel->rows - 1) % 2 == 0 ||
18116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        (type != CV_32FC1 && type != CV_64FC1) )
18126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadSize, "kernel should be 1D floating-point vector of odd (2*k+1) size" );
18136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    n = kernel->cols + kernel->rows - 1;
18156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( n <= SMALL_GAUSSIAN_SIZE && sigma <= 0 )
18176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fixed_kernel = small_gaussian_tab[n>>1];
18186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sigmaX = sigma > 0 ? sigma : (n/2 - 1)*0.3 + 0.8;
18206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scale2X = -0.5/(sigmaX*sigmaX);
18216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    step = kernel->rows == 1 ? 1 : kernel->step/CV_ELEM_SIZE1(type);
18226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cf = kernel->data.fl;
18236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cd = kernel->data.db;
18246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sum = fixed_kernel ? -fixed_kernel[0] : -1.;
18266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i <= n/2; i++ )
18286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
18296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        double t = fixed_kernel ? (double)fixed_kernel[i] : exp(scale2X*i*i);
18306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( type == CV_32FC1 )
18316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
18326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cf[(n/2+i)*step] = (float)t;
18336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            sum += cf[(n/2+i)*step]*2;
18346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
18356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
18366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
18376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cd[(n/2+i)*step] = t;
18386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            sum += cd[(n/2+i)*step]*2;
18396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
18406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
18416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sum = 1./sum;
18436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i <= n/2; i++ )
18446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
18456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( type == CV_32FC1 )
18466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cf[(n/2+i)*step] = cf[(n/2-i)*step] = (float)(cf[(n/2+i)*step]*sum);
18476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
18486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cd[(n/2+i)*step] = cd[(n/2-i)*step] = cd[(n/2+i)*step]*sum;
18496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
18506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
18526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
18536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvSepFilter::init_sobel_kernel( CvMat* _kx, CvMat* _ky, int dx, int dy, int flags )
18566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
18576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "CvSepFilter::init_sobel_kernel" );
18586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
18606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, j, k, msz;
18626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int* kerI;
18636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool normalize = (flags & NORMALIZE_KERNEL) != 0;
18646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool flip = (flags & FLIP_KERNEL) != 0;
18656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_IS_MAT(_kx) || !CV_IS_MAT(_ky) )
18676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "One of the kernel matrices is not valid" );
18686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    msz = MAX( _kx->cols + _kx->rows, _ky->cols + _ky->rows );
18706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( msz > 32 )
18716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange, "Too large kernel size" );
18726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    kerI = (int*)cvStackAlloc( msz*sizeof(kerI[0]) );
18746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( dx < 0 || dy < 0 || dx+dy <= 0 )
18766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange,
18776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            "Both derivative orders (dx and dy) must be non-negative "
18786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            "and at least one of them must be positive." );
18796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( k = 0; k < 2; k++ )
18816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
18826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvMat* kernel = k == 0 ? _kx : _ky;
18836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int order = k == 0 ? dx : dy;
18846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int n = kernel->cols + kernel->rows - 1, step;
18856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int type = CV_MAT_TYPE(kernel->type);
18866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        double scale = !normalize ? 1. : 1./(1 << (n-order-1));
18876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int iscale = 1;
18886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( (kernel->cols != 1 && kernel->rows != 1) ||
18906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            (kernel->cols + kernel->rows - 1) % 2 == 0 ||
18916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            (type != CV_32FC1 && type != CV_64FC1 && type != CV_32SC1) )
18926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsOutOfRange,
18936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            "Both kernels must be 1D floating-point or integer vectors of odd (2*k+1) size." );
18946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( normalize && n > 1 && type == CV_32SC1 )
18966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsBadArg, "Integer kernel can not be normalized" );
18976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( n <= order )
18996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsOutOfRange,
19006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            "Derivative order must be smaller than the corresponding kernel size" );
19016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( n == 1 )
19036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            kerI[0] = 1;
19046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else if( n == 3 )
19056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
19066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( order == 0 )
19076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                kerI[0] = 1, kerI[1] = 2, kerI[2] = 1;
19086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if( order == 1 )
19096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                kerI[0] = -1, kerI[1] = 0, kerI[2] = 1;
19106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
19116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                kerI[0] = 1, kerI[1] = -2, kerI[2] = 1;
19126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
19136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
19146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
19156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int oldval, newval;
19166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            kerI[0] = 1;
19176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i < n; i++ )
19186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                kerI[i+1] = 0;
19196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i < n - order - 1; i++ )
19216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
19226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                oldval = kerI[0];
19236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( j = 1; j <= n; j++ )
19246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
19256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    newval = kerI[j]+kerI[j-1];
19266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    kerI[j-1] = oldval;
19276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    oldval = newval;
19286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
19296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
19306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i < order; i++ )
19326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
19336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                oldval = -kerI[0];
19346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( j = 1; j <= n; j++ )
19356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
19366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    newval = kerI[j-1] - kerI[j];
19376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    kerI[j-1] = oldval;
19386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    oldval = newval;
19396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
19406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
19416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
19426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        step = kernel->rows == 1 ? 1 : kernel->step/CV_ELEM_SIZE1(type);
19446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( flip && (order & 1) && k )
19456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            iscale = -iscale, scale = -scale;
19466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < n; i++ )
19486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
19496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( type == CV_32SC1 )
19506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                kernel->data.i[i*step] = kerI[i]*iscale;
19516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if( type == CV_32FC1 )
19526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                kernel->data.fl[i*step] = (float)(kerI[i]*scale);
19536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
19546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                kernel->data.db[i*step] = kerI[i]*scale;
19556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
19566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
19576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
19596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
19606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvSepFilter::init_scharr_kernel( CvMat* _kx, CvMat* _ky, int dx, int dy, int flags )
19636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
19646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "CvSepFilter::init_scharr_kernel" );
19656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
19676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, k;
19696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int kerI[3];
19706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool normalize = (flags & NORMALIZE_KERNEL) != 0;
19716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool flip = (flags & FLIP_KERNEL) != 0;
19726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_IS_MAT(_kx) || !CV_IS_MAT(_ky) )
19746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "One of the kernel matrices is not valid" );
19756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( ((dx|dy)&~1) || dx+dy != 1 )
19776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange,
19786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            "Scharr kernel can only be used for 1st order derivatives" );
19796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( k = 0; k < 2; k++ )
19816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
19826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvMat* kernel = k == 0 ? _kx : _ky;
19836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int order = k == 0 ? dx : dy;
19846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int n = kernel->cols + kernel->rows - 1, step;
19856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int type = CV_MAT_TYPE(kernel->type);
19866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        double scale = !normalize ? 1. : order == 0 ? 1./16 : 1./2;
19876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int iscale = 1;
19886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( (kernel->cols != 1 && kernel->rows != 1) ||
19906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            kernel->cols + kernel->rows - 1 != 3 ||
19916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            (type != CV_32FC1 && type != CV_64FC1 && type != CV_32SC1) )
19926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsOutOfRange,
19936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            "Both kernels must be 1D floating-point or integer vectors containing 3 elements each." );
19946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( normalize && type == CV_32SC1 )
19966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsBadArg, "Integer kernel can not be normalized" );
19976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( order == 0 )
19996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            kerI[0] = 3, kerI[1] = 10, kerI[2] = 3;
20006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
20016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            kerI[0] = -1, kerI[1] = 0, kerI[2] = 1;
20026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        step = kernel->rows == 1 ? 1 : kernel->step/CV_ELEM_SIZE1(type);
20046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( flip && (order & 1) && k )
20056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            iscale = -iscale, scale = -scale;
20066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < n; i++ )
20086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
20096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( type == CV_32SC1 )
20106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                kernel->data.i[i*step] = kerI[i]*iscale;
20116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if( type == CV_32FC1 )
20126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                kernel->data.fl[i*step] = (float)(kerI[i]*scale);
20136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
20146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                kernel->data.db[i*step] = kerI[i]*scale;
20156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
20166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
20176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
20196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
20206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvSepFilter::init_deriv( int _max_width, int _src_type, int _dst_type,
20236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              int dx, int dy, int aperture_size, int flags )
20246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
20256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "CvSepFilter::init_deriv" );
20266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
20286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int kx_size = aperture_size == CV_SCHARR ? 3 : aperture_size, ky_size = kx_size;
20306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    float kx_data[CV_MAX_SOBEL_KSIZE], ky_data[CV_MAX_SOBEL_KSIZE];
20316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat _kx, _ky;
20326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( kx_size <= 0 || ky_size > CV_MAX_SOBEL_KSIZE )
20346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange, "Incorrect aperture_size" );
20356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( kx_size == 1 && dx )
20376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        kx_size = 3;
20386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( ky_size == 1 && dy )
20396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ky_size = 3;
20406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _kx = cvMat( 1, kx_size, CV_32FC1, kx_data );
20426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _ky = cvMat( 1, ky_size, CV_32FC1, ky_data );
20436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( aperture_size == CV_SCHARR )
20456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
20466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( init_scharr_kernel( &_kx, &_ky, dx, dy, flags ));
20476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
20486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
20496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
20506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( init_sobel_kernel( &_kx, &_ky, dx, dy, flags ));
20516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
20526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( init( _max_width, _src_type, _dst_type, &_kx, &_ky ));
20546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
20566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
20576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvSepFilter::init_gaussian( int _max_width, int _src_type, int _dst_type,
20606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 int gaussian_size, double sigma )
20616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
20626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    float* kdata = 0;
20636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "CvSepFilter::init_gaussian" );
20656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
20676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat _kernel;
20696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( gaussian_size <= 0 || gaussian_size > 1024 )
20716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadSize, "Incorrect size of gaussian kernel" );
20726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    kdata = (float*)cvStackAlloc(gaussian_size*sizeof(kdata[0]));
20746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _kernel = cvMat( 1, gaussian_size, CV_32F, kdata );
20756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( init_gaussian_kernel( &_kernel, sigma ));
20776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( init( _max_width, _src_type, _dst_type, &_kernel, &_kernel ));
20786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
20806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
20816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\
20846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              Non-separable Linear Filter
20856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/
20866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvLinearFilter_8u( const uchar** src, uchar* dst, int dst_step,
20886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                int count, void* params );
20896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvLinearFilter_16s( const short** src, short* dst, int dst_step,
20906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 int count, void* params );
20916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvLinearFilter_16u( const ushort** src, ushort* dst, int dst_step,
20926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 int count, void* params );
20936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvLinearFilter_32f( const float** src, float* dst, int dst_step,
20946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 int count, void* params );
20956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvLinearFilter::CvLinearFilter()
20976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
20986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    kernel = 0;
20996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    k_sparse = 0;
21006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
21016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvLinearFilter::CvLinearFilter( int _max_width, int _src_type, int _dst_type,
21036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                const CvMat* _kernel, CvPoint _anchor,
21046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                int _border_mode, CvScalar _border_value )
21056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
21066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    kernel = 0;
21076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    k_sparse = 0;
21086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    init( _max_width, _src_type, _dst_type, _kernel,
21096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          _anchor, _border_mode, _border_value );
21106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
21116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvLinearFilter::clear()
21146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
21156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat( &kernel );
21166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvFree( &k_sparse );
21176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvBaseImageFilter::clear();
21186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
21196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvLinearFilter::~CvLinearFilter()
21226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
21236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    clear();
21246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
21256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvLinearFilter::init( int _max_width, int _src_type, int _dst_type,
21286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           const CvMat* _kernel, CvPoint _anchor,
21296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           int _border_mode, CvScalar _border_value )
21306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
21316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "CvLinearFilter::init" );
21326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
21346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int depth = CV_MAT_DEPTH(_src_type);
21366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int cn = CV_MAT_CN(_src_type);
21376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvPoint* nz_loc;
21386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    float* coeffs;
21396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, j, k = 0;
21406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_IS_MAT(_kernel) )
21426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "kernel is not valid matrix" );
21436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _src_type = CV_MAT_TYPE(_src_type);
21456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _dst_type = CV_MAT_TYPE(_dst_type);
21466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( _src_type != _dst_type )
21486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsUnmatchedFormats,
21496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        "The source and destination image types must be the same" );
21506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( CvBaseImageFilter::init( _max_width, _src_type, _dst_type,
21526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        false, cvGetMatSize(_kernel), _anchor, _border_mode, _border_value ));
21536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !(kernel && k_sparse && ksize.width == kernel->cols && ksize.height == kernel->rows ))
21556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
21566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvReleaseMat( &kernel );
21576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvFree( &k_sparse );
21586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( kernel = cvCreateMat( ksize.height, ksize.width, CV_32FC1 ));
21596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( k_sparse = (uchar*)cvAlloc(
21606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ksize.width*ksize.height*(2*sizeof(int) + sizeof(uchar*) + sizeof(float))));
21616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
21626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvConvert( _kernel, kernel ));
21646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    nz_loc = (CvPoint*)k_sparse;
21666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < ksize.height; i++ )
21676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
21686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( j = 0; j < ksize.width; j++ )
21696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( fabs(((float*)(kernel->data.ptr + i*kernel->step))[j])>FLT_EPSILON )
21706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                nz_loc[k++] = cvPoint(j,i);
21716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
21726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( k == 0 )
21736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        nz_loc[k++] = anchor;
21746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    k_sparse_count = k;
21756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    coeffs = (float*)((uchar**)(nz_loc + k_sparse_count) + k_sparse_count);
21766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( k = 0; k < k_sparse_count; k++ )
21786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
21796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        coeffs[k] = CV_MAT_ELEM( *kernel, float, nz_loc[k].y, nz_loc[k].x );
21806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        nz_loc[k].x *= cn;
21816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
21826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    x_func = 0;
21846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( depth == CV_8U )
21856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        y_func = (CvColumnFilterFunc)icvLinearFilter_8u;
21866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( depth == CV_16S )
21876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        y_func = (CvColumnFilterFunc)icvLinearFilter_16s;
21886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( depth == CV_16U )
21896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        y_func = (CvColumnFilterFunc)icvLinearFilter_16u;
21906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( depth == CV_32F )
21916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        y_func = (CvColumnFilterFunc)icvLinearFilter_32f;
21926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
21936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsUnsupportedFormat, "Unsupported image type" );
21946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
21966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
21976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvLinearFilter::init( int _max_width, int _src_type, int _dst_type,
22006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           bool _is_separable, CvSize _ksize,
22016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           CvPoint _anchor, int _border_mode,
22026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           CvScalar _border_value )
22036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
22046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvBaseImageFilter::init( _max_width, _src_type, _dst_type, _is_separable,
22056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                             _ksize, _anchor, _border_mode, _border_value );
22066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
22076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define ICV_FILTER( flavor, arrtype, worktype, load_macro,          \
22106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    cast_macro1, cast_macro2 )                      \
22116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void                                                         \
22126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvLinearFilter_##flavor( const arrtype** src, arrtype* dst,        \
22136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int dst_step, int count, void* params )         \
22146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{                                                                   \
22156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvLinearFilter* state = (CvLinearFilter*)params;                \
22166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int width = state->get_width();                                 \
22176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int cn = CV_MAT_CN(state->get_src_type());                      \
22186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, k;                                                       \
22196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvPoint* k_sparse = (CvPoint*)state->get_kernel_sparse_buf();   \
22206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int k_count = state->get_kernel_sparse_count();                 \
22216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const arrtype** k_ptr = (const arrtype**)(k_sparse + k_count);  \
22226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const arrtype** k_end = k_ptr + k_count;                        \
22236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const float* k_coeffs = (const float*)(k_ptr + k_count);        \
22246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                    \
22256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    width *= cn;                                                    \
22266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dst_step /= sizeof(dst[0]);                                     \
22276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                    \
22286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( ; count > 0; count--, dst += dst_step, src++ )             \
22296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {                                                               \
22306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( k = 0; k < k_count; k++ )                              \
22316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            k_ptr[k] = src[k_sparse[k].y] + k_sparse[k].x;          \
22326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                    \
22336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i <= width - 4; i += 4 )                        \
22346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {                                                           \
22356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const arrtype** kp = k_ptr;                             \
22366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const float* kc = k_coeffs;                             \
22376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double s0 = 0, s1 = 0, s2 = 0, s3 = 0;                  \
22386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            worktype t0, t1;                                        \
22396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                    \
22406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            while( kp != k_end )                                    \
22416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {                                                       \
22426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                const arrtype* sptr = (*kp++) + i;                  \
22436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                float f = *kc++;                                    \
22446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s0 += f*load_macro(sptr[0]);                        \
22456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s1 += f*load_macro(sptr[1]);                        \
22466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s2 += f*load_macro(sptr[2]);                        \
22476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s3 += f*load_macro(sptr[3]);                        \
22486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }                                                       \
22496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                    \
22506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            t0 = cast_macro1(s0); t1 = cast_macro1(s1);             \
22516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst[i] = cast_macro2(t0);                               \
22526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst[i+1] = cast_macro2(t1);                             \
22536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            t0 = cast_macro1(s2); t1 = cast_macro1(s3);             \
22546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst[i+2] = cast_macro2(t0);                             \
22556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst[i+3] = cast_macro2(t1);                             \
22566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }                                                           \
22576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                    \
22586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ; i < width; i++ )                                     \
22596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {                                                           \
22606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const arrtype** kp = k_ptr;                             \
22616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const float* kc = k_coeffs;                             \
22626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double s0 = 0;                                          \
22636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            worktype t0;                                            \
22646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                    \
22656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            while( kp != k_end )                                    \
22666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {                                                       \
22676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                const arrtype* sptr = *kp++;                        \
22686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                float f = *kc++;                                    \
22696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s0 += f*load_macro(sptr[i]);                        \
22706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }                                                       \
22716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                    \
22726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            t0 = cast_macro1(s0);                                   \
22736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst[i] = cast_macro2(t0);                               \
22746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }                                                           \
22756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }                                                               \
22766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
22776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennICV_FILTER( 8u, uchar, int, CV_8TO32F, cvRound, CV_CAST_8U )
22806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennICV_FILTER( 16u, ushort, int, CV_NOP, cvRound, CV_CAST_16U )
22816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennICV_FILTER( 16s, short, int, CV_NOP, cvRound, CV_CAST_16S )
22826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennICV_FILTER( 32f, float, float, CV_NOP, CV_CAST_32F, CV_NOP )
22836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/////////////////////// common functions for working with IPP filters ////////////////////
22866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvMat* icvIPPFilterInit( const CvMat* src, int stripe_size, CvSize ksize )
22886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
22896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSize temp_size;
22906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int pix_size = CV_ELEM_SIZE(src->type);
22916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    temp_size.width = cvAlign(src->cols + ksize.width - 1,8/CV_ELEM_SIZE(src->type & CV_MAT_DEPTH_MASK));
22926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    //temp_size.width = src->cols + ksize.width - 1;
22936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    temp_size.height = (stripe_size*2 + temp_size.width*pix_size) / (temp_size.width*pix_size*2);
22946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    temp_size.height = MAX( temp_size.height, ksize.height );
22956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    temp_size.height = MIN( temp_size.height, src->rows + ksize.height - 1 );
22966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return cvCreateMat( temp_size.height, temp_size.width, src->type );
22986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
22996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennint icvIPPFilterNextStripe( const CvMat* src, CvMat* temp, int y,
23026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            CvSize ksize, CvPoint anchor )
23036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
23046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int pix_size = CV_ELEM_SIZE(src->type);
23056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int src_step = src->step ? src->step : CV_STUB_STEP;
23066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int temp_step = temp->step ? temp->step : CV_STUB_STEP;
23076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, dy, src_y1 = 0, src_y2;
23086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int temp_rows;
23096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uchar* temp_ptr = temp->data.ptr;
23106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSize stripe_size, temp_size;
23116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dy = MIN( temp->rows - ksize.height + 1, src->rows - y );
23136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( y > 0 )
23146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
23156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int temp_ready = ksize.height - 1;
23166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < temp_ready; i++ )
23186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            memcpy( temp_ptr + temp_step*i, temp_ptr +
23196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    temp_step*(temp->rows - temp_ready + i), temp_step );
23206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        temp_ptr += temp_ready*temp_step;
23226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        temp_rows = dy;
23236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        src_y1 = y + temp_ready - anchor.y;
23246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        src_y2 = src_y1 + dy;
23256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( src_y1 >= src->rows )
23266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
23276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            src_y1 = src->rows - 1;
23286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            src_y2 = src->rows;
23296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
23306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
23316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
23326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
23336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        temp_rows = dy + ksize.height - 1;
23346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        src_y2 = temp_rows - anchor.y;
23356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
23366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    src_y2 = MIN( src_y2, src->rows );
23386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    stripe_size = cvSize(src->cols, src_y2 - src_y1);
23406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    temp_size = cvSize(temp->cols, temp_rows);
23416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    icvCopyReplicateBorder_8u( src->data.ptr + src_y1*src_step, src_step,
23426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                      stripe_size, temp_ptr, temp_step, temp_size,
23436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                      (y == 0 ? anchor.y : 0), anchor.x, pix_size );
23446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return dy;
23456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
23466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/////////////////////////////// IPP separable filter functions ///////////////////////////
23496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterRow_8u_C1R_t icvFilterRow_8u_C1R_p = 0;
23516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterRow_8u_C3R_t icvFilterRow_8u_C3R_p = 0;
23526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterRow_8u_C4R_t icvFilterRow_8u_C4R_p = 0;
23536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterRow_16s_C1R_t icvFilterRow_16s_C1R_p = 0;
23546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterRow_16s_C3R_t icvFilterRow_16s_C3R_p = 0;
23556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterRow_16s_C4R_t icvFilterRow_16s_C4R_p = 0;
23566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterRow_32f_C1R_t icvFilterRow_32f_C1R_p = 0;
23576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterRow_32f_C3R_t icvFilterRow_32f_C3R_p = 0;
23586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterRow_32f_C4R_t icvFilterRow_32f_C4R_p = 0;
23596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterColumn_8u_C1R_t icvFilterColumn_8u_C1R_p = 0;
23616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterColumn_8u_C3R_t icvFilterColumn_8u_C3R_p = 0;
23626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterColumn_8u_C4R_t icvFilterColumn_8u_C4R_p = 0;
23636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterColumn_16s_C1R_t icvFilterColumn_16s_C1R_p = 0;
23646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterColumn_16s_C3R_t icvFilterColumn_16s_C3R_p = 0;
23656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterColumn_16s_C4R_t icvFilterColumn_16s_C4R_p = 0;
23666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterColumn_32f_C1R_t icvFilterColumn_32f_C1R_p = 0;
23676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterColumn_32f_C3R_t icvFilterColumn_32f_C3R_p = 0;
23686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterColumn_32f_C4R_t icvFilterColumn_32f_C4R_p = 0;
23696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//////////////////////////////////////////////////////////////////////////////////////////
23716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef CvStatus (CV_STDCALL * CvIPPSepFilterFunc)
23736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ( const void* src, int srcstep, void* dst, int dststep,
23746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      CvSize size, const float* kernel, int ksize, int anchor );
23756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennint icvIPPSepFilter( const CvMat* src, CvMat* dst, const CvMat* kernelX,
23776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     const CvMat* kernelY, CvPoint anchor )
23786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
23796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int result = 0;
23806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat* top_bottom = 0;
23826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat* vout_hin = 0;
23836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat* dst_buf = 0;
23846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvIPPSepFilter" );
23866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
23886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSize ksize;
23906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvPoint el_anchor;
23916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSize size;
23926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int type, depth, pix_size;
23936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, x, y, dy = 0, prev_dy = 0, max_dy;
23946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat vout;
23956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvIPPSepFilterFunc x_func = 0, y_func = 0;
23966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int src_step, top_bottom_step;
23976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    float *kx, *ky;
23986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int align, stripe_size;
23996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !icvFilterRow_8u_C1R_p )
24016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        EXIT;
24026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_ARE_TYPES_EQ( src, dst ) || !CV_ARE_SIZES_EQ( src, dst ) ||
24046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        !CV_IS_MAT_CONT(kernelX->type & kernelY->type) ||
24056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_MAT_TYPE(kernelX->type) != CV_32FC1 ||
24066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_MAT_TYPE(kernelY->type) != CV_32FC1 ||
24076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        (kernelX->cols != 1 && kernelX->rows != 1) ||
24086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        (kernelY->cols != 1 && kernelY->rows != 1) ||
24096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        (unsigned)anchor.x >= (unsigned)(kernelX->cols + kernelX->rows - 1) ||
24106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        (unsigned)anchor.y >= (unsigned)(kernelY->cols + kernelY->rows - 1) )
24116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsError, "Internal Error: incorrect parameters" );
24126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ksize.width = kernelX->cols + kernelX->rows - 1;
24146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ksize.height = kernelY->cols + kernelY->rows - 1;
24156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /*if( ksize.width <= 5 && ksize.height <= 5 )
24176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
24186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        float* ker = (float*)cvStackAlloc( ksize.width*ksize.height*sizeof(ker[0]));
24196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvMat kernel = cvMat( ksize.height, ksize.width, CV_32F, ker );
24206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( y = 0, i = 0; y < ksize.height; y++ )
24216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( x = 0; x < ksize.width; x++, i++ )
24226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ker[i] = kernelY->data.fl[y]*kernelX->data.fl[x];
24236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( cvFilter2D( src, dst, &kernel, anchor ));
24256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        EXIT;
24266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }*/
24276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    type = CV_MAT_TYPE(src->type);
24296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    depth = CV_MAT_DEPTH(type);
24306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    pix_size = CV_ELEM_SIZE(type);
24316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( type == CV_8UC1 )
24336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x_func = icvFilterRow_8u_C1R_p, y_func = icvFilterColumn_8u_C1R_p;
24346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( type == CV_8UC3 )
24356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x_func = icvFilterRow_8u_C3R_p, y_func = icvFilterColumn_8u_C3R_p;
24366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( type == CV_8UC4 )
24376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x_func = icvFilterRow_8u_C4R_p, y_func = icvFilterColumn_8u_C4R_p;
24386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( type == CV_16SC1 )
24396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x_func = icvFilterRow_16s_C1R_p, y_func = icvFilterColumn_16s_C1R_p;
24406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( type == CV_16SC3 )
24416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x_func = icvFilterRow_16s_C3R_p, y_func = icvFilterColumn_16s_C3R_p;
24426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( type == CV_16SC4 )
24436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x_func = icvFilterRow_16s_C4R_p, y_func = icvFilterColumn_16s_C4R_p;
24446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( type == CV_32FC1 )
24456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x_func = icvFilterRow_32f_C1R_p, y_func = icvFilterColumn_32f_C1R_p;
24466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( type == CV_32FC3 )
24476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x_func = icvFilterRow_32f_C3R_p, y_func = icvFilterColumn_32f_C3R_p;
24486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( type == CV_32FC4 )
24496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x_func = icvFilterRow_32f_C4R_p, y_func = icvFilterColumn_32f_C4R_p;
24506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
24516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        EXIT;
24526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    size = cvGetMatSize(src);
24546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    stripe_size = src->data.ptr == dst->data.ptr ? 1 << 15 : 1 << 16;
24556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    max_dy = MAX( ksize.height - 1, stripe_size/(size.width + ksize.width - 1));
24566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    max_dy = MIN( max_dy, size.height + ksize.height - 1 );
24576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    align = 8/CV_ELEM_SIZE(depth);
24596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( top_bottom = cvCreateMat( ksize.height*2, cvAlign(size.width,align), type ));
24616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( vout_hin = cvCreateMat( max_dy + ksize.height,
24636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvAlign(size.width + ksize.width - 1, align), type ));
24646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( src->data.ptr == dst->data.ptr && size.height )
24666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( dst_buf = cvCreateMat( max_dy + ksize.height,
24676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvAlign(size.width, align), type ));
24686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    kx = (float*)cvStackAlloc( ksize.width*sizeof(kx[0]) );
24706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ky = (float*)cvStackAlloc( ksize.height*sizeof(ky[0]) );
24716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // mirror the kernels
24736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < ksize.width; i++ )
24746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        kx[i] = kernelX->data.fl[ksize.width - i - 1];
24756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < ksize.height; i++ )
24776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ky[i] = kernelY->data.fl[ksize.height - i - 1];
24786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    el_anchor = cvPoint( ksize.width - anchor.x - 1, ksize.height - anchor.y - 1 );
24806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvGetCols( vout_hin, &vout, anchor.x, anchor.x + size.width );
24826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    src_step = src->step ? src->step : CV_STUB_STEP;
24846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    top_bottom_step = top_bottom->step ? top_bottom->step : CV_STUB_STEP;
24856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    vout.step = vout.step ? vout.step : CV_STUB_STEP;
24866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( y = 0; y < size.height; y += dy )
24886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
24896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const CvMat *vin = src, *hout = dst;
24906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int src_y = y, dst_y = y;
24916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dy = MIN( max_dy, size.height - (ksize.height - anchor.y - 1) - y );
24926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( y < anchor.y || dy < anchor.y )
24946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
24956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int ay = anchor.y;
24966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvSize src_stripe_size = size;
24976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( y < anchor.y )
24996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
25006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                src_y = 0;
25016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dy = MIN( anchor.y, size.height );
25026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                src_stripe_size.height = MIN( dy + ksize.height - anchor.y - 1, size.height );
25036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
25046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
25056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
25066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                src_y = MAX( y - anchor.y, 0 );
25076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dy = size.height - y;
25086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                src_stripe_size.height = MIN( dy + anchor.y, size.height );
25096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ay = MAX( anchor.y - y, 0 );
25106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
25116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            icvCopyReplicateBorder_8u( src->data.ptr + src_y*src_step, src_step,
25136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                src_stripe_size, top_bottom->data.ptr, top_bottom_step,
25146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                cvSize(size.width, dy + ksize.height - 1), ay, 0, pix_size );
25156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            vin = top_bottom;
25166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            src_y = anchor.y;
25176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
25186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // do vertical convolution
25206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        IPPI_CALL( y_func( vin->data.ptr + src_y*vin->step, vin->step ? vin->step : CV_STUB_STEP,
25216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           vout.data.ptr, vout.step, cvSize(size.width, dy),
25226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           ky, ksize.height, el_anchor.y ));
25236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // now it's time to copy the previously processed stripe to the input/output image
25256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( src->data.ptr == dst->data.ptr )
25266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
25276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i < prev_dy; i++ )
25286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                memcpy( dst->data.ptr + (y - prev_dy + i)*dst->step,
25296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        dst_buf->data.ptr + i*dst_buf->step, size.width*pix_size );
25306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( y + dy < size.height )
25316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
25326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                hout = dst_buf;
25336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst_y = 0;
25346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
25356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
25366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // create a border for every line by replicating the left-most/right-most elements
25386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < dy; i++ )
25396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
25406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            uchar* ptr = vout.data.ptr + i*vout.step;
25416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( x = -1; x >= -anchor.x*pix_size; x-- )
25426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ptr[x] = ptr[x + pix_size];
25436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( x = size.width*pix_size; x < (size.width+ksize.width-anchor.x-1)*pix_size; x++ )
25446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ptr[x] = ptr[x - pix_size];
25456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
25466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // do horizontal convolution
25486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        IPPI_CALL( x_func( vout.data.ptr, vout.step, hout->data.ptr + dst_y*hout->step,
25496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           hout->step ? hout->step : CV_STUB_STEP,
25506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           cvSize(size.width, dy), kx, ksize.width, el_anchor.x ));
25516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        prev_dy = dy;
25526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
25536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    result = 1;
25556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
25576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat( &vout_hin );
25596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat( &dst_buf );
25606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat( &top_bottom );
25616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return result;
25636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
25646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//////////////////////////////////////////////////////////////////////////////////////////
25666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//////////////////////////////// IPP generic filter functions ////////////////////////////
25686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilter_8u_C1R_t icvFilter_8u_C1R_p = 0;
25706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilter_8u_C3R_t icvFilter_8u_C3R_p = 0;
25716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilter_8u_C4R_t icvFilter_8u_C4R_p = 0;
25726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilter_16s_C1R_t icvFilter_16s_C1R_p = 0;
25736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilter_16s_C3R_t icvFilter_16s_C3R_p = 0;
25746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilter_16s_C4R_t icvFilter_16s_C4R_p = 0;
25756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilter_32f_C1R_t icvFilter_32f_C1R_p = 0;
25766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilter_32f_C3R_t icvFilter_32f_C3R_p = 0;
25776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilter_32f_C4R_t icvFilter_32f_C4R_p = 0;
25786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef CvStatus (CV_STDCALL * CvFilterIPPFunc)
25816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn( const void* src, int srcstep, void* dst, int dststep, CvSize size,
25826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  const float* kernel, CvSize ksize, CvPoint anchor );
25836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
25856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvFilter2D( const CvArr* _src, CvArr* _dst, const CvMat* kernel, CvPoint anchor )
25866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
25876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const int dft_filter_size = 100;
25886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvLinearFilter filter;
25906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat* ipp_kernel = 0;
25916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // below that approximate size OpenCV is faster
25936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const int ipp_lower_limit = 20;
25946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat* temp = 0;
25956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvFilter2D" );
25976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
25996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int coi1 = 0, coi2 = 0;
26016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat srcstub, *src = (CvMat*)_src;
26026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat dststub, *dst = (CvMat*)_dst;
26036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int type;
26046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( src = cvGetMat( src, &srcstub, &coi1 ));
26066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( dst = cvGetMat( dst, &dststub, &coi2 ));
26076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( coi1 != 0 || coi2 != 0 )
26096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_BadCOI, "" );
26106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    type = CV_MAT_TYPE( src->type );
26126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_ARE_SIZES_EQ( src, dst ))
26146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsUnmatchedSizes, "" );
26156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_ARE_TYPES_EQ( src, dst ))
26176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsUnmatchedFormats, "" );
26186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( anchor.x == -1 && anchor.y == -1 )
26206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        anchor = cvPoint(kernel->cols/2,kernel->rows/2);
26216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( kernel->cols*kernel->rows >= dft_filter_size &&
26236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        kernel->cols <= src->cols && kernel->rows <= src->rows )
26246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
26256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( src->data.ptr == dst->data.ptr )
26266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
26276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            temp = cvCloneMat( src );
26286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            src = temp;
26296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
26306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        icvCrossCorr( src, kernel, dst, anchor );
26316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        EXIT;
26326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
26336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( icvFilter_8u_C1R_p && (src->rows >= ipp_lower_limit || src->cols >= ipp_lower_limit) )
26356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
26366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvFilterIPPFunc ipp_func =
26376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                type == CV_8UC1 ? (CvFilterIPPFunc)icvFilter_8u_C1R_p :
26386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                type == CV_8UC3 ? (CvFilterIPPFunc)icvFilter_8u_C3R_p :
26396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                type == CV_8UC4 ? (CvFilterIPPFunc)icvFilter_8u_C4R_p :
26406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                type == CV_16SC1 ? (CvFilterIPPFunc)icvFilter_16s_C1R_p :
26416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                type == CV_16SC3 ? (CvFilterIPPFunc)icvFilter_16s_C3R_p :
26426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                type == CV_16SC4 ? (CvFilterIPPFunc)icvFilter_16s_C4R_p :
26436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                type == CV_32FC1 ? (CvFilterIPPFunc)icvFilter_32f_C1R_p :
26446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                type == CV_32FC3 ? (CvFilterIPPFunc)icvFilter_32f_C3R_p :
26456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                type == CV_32FC4 ? (CvFilterIPPFunc)icvFilter_32f_C4R_p : 0;
26466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( ipp_func )
26486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
26496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvSize el_size = { kernel->cols, kernel->rows };
26506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvPoint el_anchor;
26516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int stripe_size = 1 << 16; // the optimal value may depend on CPU cache,
26526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                       // overhead of current IPP code etc.
26536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const uchar* shifted_ptr;
26546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int i, j, y, dy = 0;
26556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int temp_step, dst_step = dst->step ? dst->step : CV_STUB_STEP;
26566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( (unsigned)anchor.x >= (unsigned)kernel->cols ||
26586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                (unsigned)anchor.y >= (unsigned)kernel->rows )
26596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_ERROR( CV_StsOutOfRange, "anchor point is out of kernel" );
26606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            el_anchor = cvPoint( el_size.width - anchor.x - 1, el_size.height - anchor.y - 1 );
26626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( ipp_kernel = cvCreateMat( kernel->rows, kernel->cols, CV_32FC1 ));
26646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( cvConvert( kernel, ipp_kernel ));
26656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            // mirror the kernel around the center
26676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i < (el_size.height+1)/2; i++ )
26686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
26696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                float* top_row = ipp_kernel->data.fl + el_size.width*i;
26706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                float* bottom_row = ipp_kernel->data.fl + el_size.width*(el_size.height - i - 1);
26716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( j = 0; j < (el_size.width+1)/2; j++ )
26736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
26746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    float a = top_row[j], b = top_row[el_size.width - j - 1];
26756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    float c = bottom_row[j], d = bottom_row[el_size.width - j - 1];
26766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    top_row[j] = d;
26776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    top_row[el_size.width - j - 1] = c;
26786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    bottom_row[j] = b;
26796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    bottom_row[el_size.width - j - 1] = a;
26806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
26816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
26826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( temp = icvIPPFilterInit( src, stripe_size, el_size ));
26846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            shifted_ptr = temp->data.ptr +
26866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                anchor.y*temp->step + anchor.x*CV_ELEM_SIZE(type);
26876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            temp_step = temp->step ? temp->step : CV_STUB_STEP;
26886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( y = 0; y < src->rows; y += dy )
26906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
26916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dy = icvIPPFilterNextStripe( src, temp, y, el_size, anchor );
26926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                IPPI_CALL( ipp_func( shifted_ptr, temp_step,
26936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    dst->data.ptr + y*dst_step, dst_step, cvSize(src->cols, dy),
26946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    ipp_kernel->data.fl, el_size, el_anchor ));
26956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
26966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            EXIT;
26976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
26986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
26996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( filter.init( src->cols, type, type, kernel, anchor ));
27016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( filter.process( src, dst ));
27026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
27046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat( &temp );
27066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat( &ipp_kernel );
27076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
27086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* End of file. */
2711