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 * This file includes the code, contributed by Simon Perreault
466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * (the function icvMedianBlur_8u_CnR_O1)
476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *
486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Constant-time median filtering -- http://nomis80.org/ctmf.html
496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Copyright (C) 2006 Simon Perreault
506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *
516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Contact:
526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *  Laboratoire de vision et systemes numeriques
536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *  Pavillon Adrien-Pouliot
546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *  Universite Laval
556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *  Sainte-Foy, Quebec, Canada
566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *  G1K 7P4
576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *
586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *  perreaul@gel.ulaval.ca
596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */
606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// uncomment the line below to force SSE2 mode
626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//#define CV_SSE2 1
636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\
656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                         Box Filter
666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/
676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvSumRow_8u32s( const uchar* src0, int* dst, void* params );
696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvSumRow_32f64f( const float* src0, double* dst, void* params );
706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvSumCol_32s8u( const int** src, uchar* dst, int dst_step,
716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                             int count, void* params );
726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvSumCol_32s16s( const int** src, short* dst, int dst_step,
736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                             int count, void* params );
746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvSumCol_32s32s( const int** src, int* dst, int dst_step,
756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                             int count, void* params );
766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvSumCol_64f32f( const double** src, float* dst, int dst_step,
776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              int count, void* params );
786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvBoxFilter::CvBoxFilter()
806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    min_depth = CV_32S;
826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sum = 0;
836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sum_count = 0;
846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    normalized = false;
856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvBoxFilter::CvBoxFilter( int _max_width, int _src_type, int _dst_type,
896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          bool _normalized, CvSize _ksize,
906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          CvPoint _anchor, int _border_mode,
916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          CvScalar _border_value )
926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    min_depth = CV_32S;
946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sum = 0;
956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sum_count = 0;
966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    normalized = false;
976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    init( _max_width, _src_type, _dst_type, _normalized,
986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          _ksize, _anchor, _border_mode, _border_value );
996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvBoxFilter::~CvBoxFilter()
1036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    clear();
1056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvBoxFilter::init( int _max_width, int _src_type, int _dst_type,
1096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        bool _normalized, CvSize _ksize,
1106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CvPoint _anchor, int _border_mode,
1116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CvScalar _border_value )
1126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "CvBoxFilter::init" );
1146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
1166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sum = 0;
1186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    normalized = _normalized;
1196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( (normalized && CV_MAT_TYPE(_src_type) != CV_MAT_TYPE(_dst_type)) ||
1216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        (!normalized && CV_MAT_CN(_src_type) != CV_MAT_CN(_dst_type)))
1226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsUnmatchedFormats,
1236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        "In case of normalized box filter input and output must have the same type.\n"
1246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        "In case of unnormalized box filter the number of input and output channels must be the same" );
1256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    min_depth = CV_MAT_DEPTH(_src_type) == CV_8U ? CV_32S : CV_64F;
1276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvBaseImageFilter::init( _max_width, _src_type, _dst_type, 1, _ksize,
1296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                             _anchor, _border_mode, _border_value );
1306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scale = normalized ? 1./(ksize.width*ksize.height) : 1;
1326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( CV_MAT_DEPTH(src_type) == CV_8U )
1346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x_func = (CvRowFilterFunc)icvSumRow_8u32s;
1356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( CV_MAT_DEPTH(src_type) == CV_32F )
1366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x_func = (CvRowFilterFunc)icvSumRow_32f64f;
1376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
1386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsUnsupportedFormat, "Unknown/unsupported input image format" );
1396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( CV_MAT_DEPTH(dst_type) == CV_8U )
1416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
1426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !normalized )
1436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsBadArg, "Only normalized box filter can be used for 8u->8u transformation" );
1446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        y_func = (CvColumnFilterFunc)icvSumCol_32s8u;
1456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( CV_MAT_DEPTH(dst_type) == CV_16S )
1476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
1486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( normalized || CV_MAT_DEPTH(src_type) != CV_8U )
1496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsBadArg, "Only 8u->16s unnormalized box filter is supported in case of 16s output" );
1506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        y_func = (CvColumnFilterFunc)icvSumCol_32s16s;
1516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	else if( CV_MAT_DEPTH(dst_type) == CV_32S )
1536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	{
1546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		if( normalized || CV_MAT_DEPTH(src_type) != CV_8U )
1556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn			CV_ERROR( CV_StsBadArg, "Only 8u->32s unnormalized box filter is supported in case of 32s output");
1566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		y_func = (CvColumnFilterFunc)icvSumCol_32s32s;
1586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	}
1596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( CV_MAT_DEPTH(dst_type) == CV_32F )
1606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
1616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( CV_MAT_DEPTH(src_type) != CV_32F )
1626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsBadArg, "Only 32f->32f box filter (normalized or not) is supported in case of 32f output" );
1636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        y_func = (CvColumnFilterFunc)icvSumCol_64f32f;
1646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	else{
1666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		CV_ERROR( CV_StsBadArg, "Unknown/unsupported destination image format" );
1676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	}
1686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
1706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvBoxFilter::start_process( CvSlice x_range, int width )
1746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvBaseImageFilter::start_process( x_range, width );
1766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, psz = CV_ELEM_SIZE(work_type);
1776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uchar* s;
1786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    buf_end -= buf_step;
1796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    buf_max_count--;
1806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( buf_max_count >= max_ky*2 + 1 );
1816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    s = sum = buf_end + cvAlign((width + ksize.width - 1)*CV_ELEM_SIZE(src_type), ALIGN);
1826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sum_count = 0;
1836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    width *= psz;
1856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < width; i++ )
1866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        s[i] = (uchar)0;
1876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
1916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvSumRow_8u32s( const uchar* src, int* dst, void* params )
1926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvBoxFilter* state = (const CvBoxFilter*)params;
1946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int ksize = state->get_kernel_size().width;
1956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int width = state->get_width();
1966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int cn = CV_MAT_CN(state->get_src_type());
1976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, k;
1986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    width = (width - 1)*cn; ksize *= cn;
2006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( k = 0; k < cn; k++, src++, dst++ )
2026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int s = 0;
2046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < ksize; i += cn )
2056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            s += src[i];
2066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dst[0] = s;
2076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < width; i += cn )
2086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
2096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            s += src[i+ksize] - src[i];
2106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst[i+cn] = s;
2116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
2126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
2136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
2176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvSumRow_32f64f( const float* src, double* dst, void* params )
2186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvBoxFilter* state = (const CvBoxFilter*)params;
2206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int ksize = state->get_kernel_size().width;
2216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int width = state->get_width();
2226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int cn = CV_MAT_CN(state->get_src_type());
2236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, k;
2246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    width = (width - 1)*cn; ksize *= cn;
2266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( k = 0; k < cn; k++, src++, dst++ )
2286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        double s = 0;
2306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < ksize; i += cn )
2316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            s += src[i];
2326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dst[0] = s;
2336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < width; i += cn )
2346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
2356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            s += (double)src[i+ksize] - src[i];
2366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst[i+cn] = s;
2376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
2386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
2396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
2436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvSumCol_32s8u( const int** src, uchar* dst,
2446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                 int dst_step, int count, void* params )
2456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define BLUR_SHIFT 24
2476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvBoxFilter* state = (CvBoxFilter*)params;
2486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int ksize = state->get_kernel_size().height;
2496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, width = state->get_width();
2506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int cn = CV_MAT_CN(state->get_src_type());
2516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double scale = state->get_scale();
2526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int iscale = cvFloor(scale*(1 << BLUR_SHIFT));
2536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int* sum = (int*)state->get_sum_buf();
2546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int* _sum_count = state->get_sum_count_ptr();
2556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int sum_count = *_sum_count;
2566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    width *= cn;
2586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    src += sum_count;
2596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    count += ksize - 1 - sum_count;
2606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( ; count--; src++ )
2626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const int* sp = src[0];
2646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( sum_count+1 < ksize )
2656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
2666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i <= width - 2; i += 2 )
2676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
2686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int s0 = sum[i] + sp[i], s1 = sum[i+1] + sp[i+1];
2696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                sum[i] = s0; sum[i+1] = s1;
2706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
2716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; i < width; i++ )
2736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                sum[i] += sp[i];
2746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            sum_count++;
2766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
2776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
2786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
2796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const int* sm = src[-ksize+1];
2806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i <= width - 2; i += 2 )
2816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
2826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int s0 = sum[i] + sp[i], s1 = sum[i+1] + sp[i+1];
2836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int t0 = CV_DESCALE(s0*iscale, BLUR_SHIFT), t1 = CV_DESCALE(s1*iscale, BLUR_SHIFT);
2846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s0 -= sm[i]; s1 -= sm[i+1];
2856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                sum[i] = s0; sum[i+1] = s1;
2866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i] = (uchar)t0; dst[i+1] = (uchar)t1;
2876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
2886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; i < width; i++ )
2906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
2916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int s0 = sum[i] + sp[i], t0 = CV_DESCALE(s0*iscale, BLUR_SHIFT);
2926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                sum[i] = s0 - sm[i]; dst[i] = (uchar)t0;
2936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
2946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst += dst_step;
2956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
2966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
2976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *_sum_count = sum_count;
2996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#undef BLUR_SHIFT
3006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
3016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
3046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvSumCol_32s16s( const int** src, short* dst,
3056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  int dst_step, int count, void* params )
3066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
3076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvBoxFilter* state = (CvBoxFilter*)params;
3086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int ksize = state->get_kernel_size().height;
3096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int ktotal = ksize*state->get_kernel_size().width;
3106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, width = state->get_width();
3116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int cn = CV_MAT_CN(state->get_src_type());
3126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int* sum = (int*)state->get_sum_buf();
3136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int* _sum_count = state->get_sum_count_ptr();
3146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int sum_count = *_sum_count;
3156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dst_step /= sizeof(dst[0]);
3176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    width *= cn;
3186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    src += sum_count;
3196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    count += ksize - 1 - sum_count;
3206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( ; count--; src++ )
3226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const int* sp = src[0];
3246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( sum_count+1 < ksize )
3256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
3266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i <= width - 2; i += 2 )
3276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
3286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int s0 = sum[i] + sp[i], s1 = sum[i+1] + sp[i+1];
3296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                sum[i] = s0; sum[i+1] = s1;
3306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
3316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; i < width; i++ )
3336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                sum[i] += sp[i];
3346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            sum_count++;
3366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
3376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else if( ktotal < 128 )
3386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
3396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const int* sm = src[-ksize+1];
3406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i <= width - 2; i += 2 )
3416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
3426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int s0 = sum[i] + sp[i], s1 = sum[i+1] + sp[i+1];
3436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i] = (short)s0; dst[i+1] = (short)s1;
3446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s0 -= sm[i]; s1 -= sm[i+1];
3456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                sum[i] = s0; sum[i+1] = s1;
3466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
3476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; i < width; i++ )
3496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
3506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int s0 = sum[i] + sp[i];
3516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i] = (short)s0;
3526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                sum[i] = s0 - sm[i];
3536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
3546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst += dst_step;
3556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
3566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
3576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
3586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const int* sm = src[-ksize+1];
3596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i <= width - 2; i += 2 )
3606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
3616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int s0 = sum[i] + sp[i], s1 = sum[i+1] + sp[i+1];
3626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i] = CV_CAST_16S(s0); dst[i+1] = CV_CAST_16S(s1);
3636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s0 -= sm[i]; s1 -= sm[i+1];
3646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                sum[i] = s0; sum[i+1] = s1;
3656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
3666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; i < width; i++ )
3686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
3696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int s0 = sum[i] + sp[i];
3706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i] = CV_CAST_16S(s0);
3716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                sum[i] = s0 - sm[i];
3726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
3736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst += dst_step;
3746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
3756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *_sum_count = sum_count;
3786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
3796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
3816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvSumCol_32s32s( const int** src, int * dst,
3826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  int dst_step, int count, void* params )
3836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
3846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvBoxFilter* state = (CvBoxFilter*)params;
3856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int ksize = state->get_kernel_size().height;
3866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, width = state->get_width();
3876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int cn = CV_MAT_CN(state->get_src_type());
3886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int* sum = (int*)state->get_sum_buf();
3896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int* _sum_count = state->get_sum_count_ptr();
3906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int sum_count = *_sum_count;
3916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dst_step /= sizeof(dst[0]);
3936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    width *= cn;
3946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    src += sum_count;
3956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    count += ksize - 1 - sum_count;
3966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( ; count--; src++ )
3986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const int* sp = src[0];
4006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( sum_count+1 < ksize )
4016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
4026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i <= width - 2; i += 2 )
4036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
4046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int s0 = sum[i] + sp[i], s1 = sum[i+1] + sp[i+1];
4056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                sum[i] = s0; sum[i+1] = s1;
4066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
4076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; i < width; i++ )
4096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                sum[i] += sp[i];
4106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            sum_count++;
4126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
4136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
4146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
4156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const int* sm = src[-ksize+1];
4166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i <= width - 2; i += 2 )
4176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
4186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int s0 = sum[i] + sp[i], s1 = sum[i+1] + sp[i+1];
4196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i] = s0; dst[i+1] = s1;
4206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                s0 -= sm[i]; s1 -= sm[i+1];
4216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                sum[i] = s0; sum[i+1] = s1;
4226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
4236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; i < width; i++ )
4256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
4266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int s0 = sum[i] + sp[i];
4276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[i] = s0;
4286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                sum[i] = s0 - sm[i];
4296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
4306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst += dst_step;
4316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
4326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
4336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *_sum_count = sum_count;
4356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
4366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
4396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvSumCol_64f32f( const double** src, float* dst,
4406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  int dst_step, int count, void* params )
4416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
4426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvBoxFilter* state = (CvBoxFilter*)params;
4436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int ksize = state->get_kernel_size().height;
4446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, width = state->get_width();
4456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int cn = CV_MAT_CN(state->get_src_type());
4466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double scale = state->get_scale();
4476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool normalized = state->is_normalized();
4486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double* sum = (double*)state->get_sum_buf();
4496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int* _sum_count = state->get_sum_count_ptr();
4506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int sum_count = *_sum_count;
4516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dst_step /= sizeof(dst[0]);
4536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    width *= cn;
4546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    src += sum_count;
4556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    count += ksize - 1 - sum_count;
4566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( ; count--; src++ )
4586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
4596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const double* sp = src[0];
4606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( sum_count+1 < ksize )
4616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
4626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i <= width - 2; i += 2 )
4636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
4646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                double s0 = sum[i] + sp[i], s1 = sum[i+1] + sp[i+1];
4656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                sum[i] = s0; sum[i+1] = s1;
4666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
4676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; i < width; i++ )
4696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                sum[i] += sp[i];
4706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            sum_count++;
4726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
4736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
4746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
4756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const double* sm = src[-ksize+1];
4766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( normalized )
4776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( i = 0; i <= width - 2; i += 2 )
4786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
4796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    double s0 = sum[i] + sp[i], s1 = sum[i+1] + sp[i+1];
4806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    double t0 = s0*scale, t1 = s1*scale;
4816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s0 -= sm[i]; s1 -= sm[i+1];
4826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    dst[i] = (float)t0; dst[i+1] = (float)t1;
4836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    sum[i] = s0; sum[i+1] = s1;
4846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
4856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
4866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( i = 0; i <= width - 2; i += 2 )
4876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
4886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    double s0 = sum[i] + sp[i], s1 = sum[i+1] + sp[i+1];
4896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    dst[i] = (float)s0; dst[i+1] = (float)s1;
4906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s0 -= sm[i]; s1 -= sm[i+1];
4916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    sum[i] = s0; sum[i+1] = s1;
4926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
4936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; i < width; i++ )
4956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
4966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                double s0 = sum[i] + sp[i], t0 = s0*scale;
4976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                sum[i] = s0 - sm[i]; dst[i] = (float)t0;
4986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
4996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst += dst_step;
5006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
5016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *_sum_count = sum_count;
5046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\
5086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                      Median Filter
5096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/
5106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_MINMAX_8U(a,b) \
5126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    (t = CV_FAST_CAST_8U((a) - (b)), (b) += t, a -= t)
5136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if CV_SSE2 && !defined __SSE2__
5156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define __SSE2__ 1
5166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "emmintrin.h"
5176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif
5186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if defined(__VEC__) || defined(__ALTIVEC__)
5206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <altivec.h>
5216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#undef bool
5226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif
5236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if defined(__GNUC__)
5256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define align(x) __attribute__ ((aligned (x)))
5266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#elif CV_SSE2 && (defined(__ICL) || (_MSC_VER >= 1300))
5276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define align(x) __declspec(align(x))
5286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#else
5296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define align(x)
5306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif
5316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if _MSC_VER >= 1200
5336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#pragma warning( disable: 4244 )
5346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif
5356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/**
5376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * This structure represents a two-tier histogram. The first tier (known as the
5386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * "coarse" level) is 4 bit wide and the second tier (known as the "fine" level)
5396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * is 8 bit wide. Pixels inserted in the fine level also get inserted into the
5406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * coarse bucket designated by the 4 MSBs of the fine bucket value.
5416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *
5426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * The structure is aligned on 16 bits, which is a prerequisite for SIMD
5436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * instructions. Each bucket is 16 bit wide, which means that extra care must be
5446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * taken to prevent overflow.
5456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */
5466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef struct align(16)
5476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ushort coarse[16];
5496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ushort fine[16][16];
5506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} Histogram;
5516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/**
5536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * HOP is short for Histogram OPeration. This macro makes an operation \a op on
5546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * histogram \a h for pixel value \a x. It takes care of handling both levels.
5556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */
5566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define HOP(h,x,op) \
5576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    h.coarse[x>>4] op; \
5586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *((ushort*) h.fine + x) op;
5596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define COP(c,j,x,op) \
5616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    h_coarse[ 16*(n*c+j) + (x>>4) ] op; \
5626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    h_fine[ 16 * (n*(16*c+(x>>4)) + j) + (x & 0xF) ] op;
5636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if defined __SSE2__ || defined __MMX__ || defined __ALTIVEC__
5656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define MEDIAN_HAVE_SIMD 1
5666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#else
5676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define MEDIAN_HAVE_SIMD 0
5686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif
5696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/**
5716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Adds histograms \a x and \a y and stores the result in \a y. Makes use of
5726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * SSE2, MMX or Altivec, if available.
5736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */
5746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if defined(__SSE2__)
5756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic inline void histogram_add( const ushort x[16], ushort y[16] )
5766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _mm_store_si128( (__m128i*) &y[0], _mm_add_epi16(
5786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        _mm_load_si128((__m128i*) &y[0]), _mm_load_si128((__m128i*) &x[0] )));
5796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _mm_store_si128( (__m128i*) &y[8], _mm_add_epi16(
5806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        _mm_load_si128((__m128i*) &y[8]), _mm_load_si128((__m128i*) &x[8] )));
5816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#elif defined(__MMX__)
5836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic inline void histogram_add( const ushort x[16], ushort y[16] )
5846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *(__m64*) &y[0]  = _mm_add_pi16( *(__m64*) &y[0],  *(__m64*) &x[0]  );
5866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *(__m64*) &y[4]  = _mm_add_pi16( *(__m64*) &y[4],  *(__m64*) &x[4]  );
5876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *(__m64*) &y[8]  = _mm_add_pi16( *(__m64*) &y[8],  *(__m64*) &x[8]  );
5886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *(__m64*) &y[12] = _mm_add_pi16( *(__m64*) &y[12], *(__m64*) &x[12] );
5896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#elif defined(__ALTIVEC__)
5916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic inline void histogram_add( const ushort x[16], ushort y[16] )
5926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *(vector ushort*) &y[0] = vec_add( *(vector ushort*) &y[0], *(vector ushort*) &x[0] );
5946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *(vector ushort*) &y[8] = vec_add( *(vector ushort*) &y[8], *(vector ushort*) &x[8] );
5956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#else
5976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic inline void histogram_add( const ushort x[16], ushort y[16] )
5986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i;
6006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < 16; ++i )
6016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        y[i] = (ushort)(y[i] + x[i]);
6026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
6036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif
6046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/**
6066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Subtracts histogram \a x from \a y and stores the result in \a y. Makes use
6076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * of SSE2, MMX or Altivec, if available.
6086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */
6096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if defined(__SSE2__)
6106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic inline void histogram_sub( const ushort x[16], ushort y[16] )
6116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
6126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _mm_store_si128( (__m128i*) &y[0], _mm_sub_epi16(
6136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        _mm_load_si128((__m128i*) &y[0]), _mm_load_si128((__m128i*) &x[0] )));
6146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _mm_store_si128( (__m128i*) &y[8], _mm_sub_epi16(
6156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        _mm_load_si128((__m128i*) &y[8]), _mm_load_si128((__m128i*) &x[8] )));
6166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
6176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#elif defined(__MMX__)
6186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic inline void histogram_sub( const ushort x[16], ushort y[16] )
6196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
6206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *(__m64*) &y[0]  = _mm_sub_pi16( *(__m64*) &y[0],  *(__m64*) &x[0]  );
6216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *(__m64*) &y[4]  = _mm_sub_pi16( *(__m64*) &y[4],  *(__m64*) &x[4]  );
6226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *(__m64*) &y[8]  = _mm_sub_pi16( *(__m64*) &y[8],  *(__m64*) &x[8]  );
6236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *(__m64*) &y[12] = _mm_sub_pi16( *(__m64*) &y[12], *(__m64*) &x[12] );
6246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
6256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#elif defined(__ALTIVEC__)
6266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic inline void histogram_sub( const ushort x[16], ushort y[16] )
6276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
6286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *(vector ushort*) &y[0] = vec_sub( *(vector ushort*) &y[0], *(vector ushort*) &x[0] );
6296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *(vector ushort*) &y[8] = vec_sub( *(vector ushort*) &y[8], *(vector ushort*) &x[8] );
6306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
6316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#else
6326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic inline void histogram_sub( const ushort x[16], ushort y[16] )
6336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
6346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i;
6356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < 16; ++i )
6366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        y[i] = (ushort)(y[i] - x[i]);
6376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
6386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif
6396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic inline void histogram_muladd( int a, const ushort x[16],
6416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ushort y[16] )
6426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
6436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i;
6446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for ( i = 0; i < 16; ++i )
6456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        y[i] = (ushort)(y[i] + a * x[i]);
6466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
6476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic CvStatus CV_STDCALL
6496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvMedianBlur_8u_CnR_O1( uchar* src, int src_step, uchar* dst, int dst_step,
6506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                         CvSize size, int kernel_size, int cn, int pad_left, int pad_right )
6516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
6526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int r = (kernel_size-1)/2;
6536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const int m = size.height, n = size.width;
6546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, j, k, c;
6556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const unsigned char *p, *q;
6566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    Histogram H[4];
6576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ushort *h_coarse, *h_fine, luc[4][16];
6586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( size.height < r || size.width < r )
6606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return CV_BADSIZE_ERR;
6616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( src );
6636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( dst );
6646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( r >= 0 );
6656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( size.width >= 2*r+1 );
6666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( size.height >= 2*r+1 );
6676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( src_step != 0 );
6686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( dst_step != 0 );
6696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    h_coarse = (ushort*) cvAlloc(  1 * 16 * n * cn * sizeof(ushort) );
6716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    h_fine   = (ushort*) cvAlloc( 16 * 16 * n * cn * sizeof(ushort) );
6726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memset( h_coarse, 0,  1 * 16 * n * cn * sizeof(ushort) );
6736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memset( h_fine,   0, 16 * 16 * n * cn * sizeof(ushort) );
6746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /* First row initialization */
6766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for ( j = 0; j < n; ++j ) {
6776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for ( c = 0; c < cn; ++c ) {
6786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            COP( c, j, src[cn*j+c], += r+1 );
6796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
6806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
6816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for ( i = 0; i < r; ++i ) {
6826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for ( j = 0; j < n; ++j ) {
6836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for ( c = 0; c < cn; ++c ) {
6846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                COP( c, j, src[src_step*i+cn*j+c], ++ );
6856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
6866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
6876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
6886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for ( i = 0; i < m; ++i ) {
6906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        /* Update column histograms for entire row. */
6926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        p = src + src_step * MAX( 0, i-r-1 );
6936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        q = p + cn * n;
6946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for ( j = 0; p != q; ++j ) {
6956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for ( c = 0; c < cn; ++c, ++p ) {
6966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                COP( c, j, *p, -- );
6976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
6986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
6996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        p = src + src_step * MIN( m-1, i+r );
7016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        q = p + cn * n;
7026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for ( j = 0; p != q; ++j ) {
7036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for ( c = 0; c < cn; ++c, ++p ) {
7046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                COP( c, j, *p, ++ );
7056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
7066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
7076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        /* First column initialization */
7096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        memset( H, 0, cn*sizeof(H[0]) );
7106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        memset( luc, 0, cn*sizeof(luc[0]) );
7116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if ( pad_left ) {
7126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for ( c = 0; c < cn; ++c ) {
7136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                histogram_muladd( r, &h_coarse[16*n*c], H[c].coarse );
7146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
7156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
7166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for ( j = 0; j < (pad_left ? r : 2*r); ++j ) {
7176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for ( c = 0; c < cn; ++c ) {
7186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                histogram_add( &h_coarse[16*(n*c+j)], H[c].coarse );
7196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
7206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
7216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for ( c = 0; c < cn; ++c ) {
7226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for ( k = 0; k < 16; ++k ) {
7236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                histogram_muladd( 2*r+1, &h_fine[16*n*(16*c+k)], &H[c].fine[k][0] );
7246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
7256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
7266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for ( j = pad_left ? 0 : r; j < (pad_right ? n : n-r); ++j ) {
7286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for ( c = 0; c < cn; ++c ) {
7296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int t = 2*r*r + 2*r, b, sum = 0;
7306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ushort* segment;
7316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                histogram_add( &h_coarse[16*(n*c + MIN(j+r,n-1))], H[c].coarse );
7336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                /* Find median at coarse level */
7356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for ( k = 0; k < 16 ; ++k ) {
7366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    sum += H[c].coarse[k];
7376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if ( sum > t ) {
7386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        sum -= H[c].coarse[k];
7396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        break;
7406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
7416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
7426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                assert( k < 16 );
7436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                /* Update corresponding histogram segment */
7456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if ( luc[c][k] <= j-r ) {
7466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    memset( &H[c].fine[k], 0, 16 * sizeof(ushort) );
7476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    for ( luc[c][k] = j-r; luc[c][k] < MIN(j+r+1,n); ++luc[c][k] ) {
7486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        histogram_add( &h_fine[16*(n*(16*c+k)+luc[c][k])], H[c].fine[k] );
7496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
7506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if ( luc[c][k] < j+r+1 ) {
7516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        histogram_muladd( j+r+1 - n, &h_fine[16*(n*(16*c+k)+(n-1))], &H[c].fine[k][0] );
7526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        luc[c][k] = (ushort)(j+r+1);
7536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
7546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
7556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else {
7566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    for ( ; luc[c][k] < j+r+1; ++luc[c][k] ) {
7576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        histogram_sub( &h_fine[16*(n*(16*c+k)+MAX(luc[c][k]-2*r-1,0))], H[c].fine[k] );
7586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        histogram_add( &h_fine[16*(n*(16*c+k)+MIN(luc[c][k],n-1))], H[c].fine[k] );
7596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
7606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
7616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                histogram_sub( &h_coarse[16*(n*c+MAX(j-r,0))], H[c].coarse );
7636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                /* Find median in segment */
7656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                segment = H[c].fine[k];
7666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for ( b = 0; b < 16 ; ++b ) {
7676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    sum += segment[b];
7686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if ( sum > t ) {
7696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        dst[dst_step*i+cn*j+c] = (uchar)(16*k + b);
7706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        break;
7716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
7726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
7736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                assert( b < 16 );
7746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
7756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
7766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
7776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if defined(__MMX__)
7796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _mm_empty();
7806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif
7816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvFree(&h_coarse);
7836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvFree(&h_fine);
7846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#undef HOP
7866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#undef COP
7876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return CV_OK;
7886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
7896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if _MSC_VER >= 1200
7926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#pragma warning( default: 4244 )
7936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif
7946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic CvStatus CV_STDCALL
7976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvMedianBlur_8u_CnR_Om( uchar* src, int src_step, uchar* dst, int dst_step,
7986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                         CvSize size, int m, int cn )
7996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
8006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    #define N  16
8016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int     zone0[4][N];
8026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int     zone1[4][N*N];
8036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int     x, y;
8046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int     n2 = m*m/2;
8056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int     nx = (m + 1)/2 - 1;
8066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uchar*  src_max = src + size.height*src_step;
8076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uchar*  src_right = src + size.width*cn;
8086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    #define UPDATE_ACC01( pix, cn, op ) \
8106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {                                   \
8116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int p = (pix);                  \
8126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        zone1[cn][p] op;                \
8136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        zone0[cn][p >> 4] op;           \
8146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
8156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( size.height < nx || size.width < nx )
8176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return CV_BADSIZE_ERR;
8186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( m == 3 )
8206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
8216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        size.width *= cn;
8226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( y = 0; y < size.height; y++, dst += dst_step )
8246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
8256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const uchar* src0 = src + src_step*(y-1);
8266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const uchar* src1 = src0 + src_step;
8276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const uchar* src2 = src1 + src_step;
8286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( y == 0 )
8296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                src0 = src1;
8306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if( y == size.height - 1 )
8316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                src2 = src1;
8326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( x = 0; x < 2*cn; x++ )
8346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
8356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int x0 = x < cn ? x : size.width - 3*cn + x;
8366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int x2 = x < cn ? x + cn : size.width - 2*cn + x;
8376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int x1 = x < cn ? x0 : x2, t;
8386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int p0 = src0[x0], p1 = src0[x1], p2 = src0[x2];
8406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int p3 = src1[x0], p4 = src1[x1], p5 = src1[x2];
8416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int p6 = src2[x0], p7 = src2[x1], p8 = src2[x2];
8426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_MINMAX_8U(p1, p2); CV_MINMAX_8U(p4, p5);
8446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_MINMAX_8U(p7, p8); CV_MINMAX_8U(p0, p1);
8456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_MINMAX_8U(p3, p4); CV_MINMAX_8U(p6, p7);
8466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_MINMAX_8U(p1, p2); CV_MINMAX_8U(p4, p5);
8476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_MINMAX_8U(p7, p8); CV_MINMAX_8U(p0, p3);
8486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_MINMAX_8U(p5, p8); CV_MINMAX_8U(p4, p7);
8496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_MINMAX_8U(p3, p6); CV_MINMAX_8U(p1, p4);
8506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_MINMAX_8U(p2, p5); CV_MINMAX_8U(p4, p7);
8516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_MINMAX_8U(p4, p2); CV_MINMAX_8U(p6, p4);
8526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_MINMAX_8U(p4, p2);
8536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[x1] = (uchar)p4;
8546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
8556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( x = cn; x < size.width - cn; x++ )
8576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
8586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int p0 = src0[x-cn], p1 = src0[x], p2 = src0[x+cn];
8596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int p3 = src1[x-cn], p4 = src1[x], p5 = src1[x+cn];
8606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int p6 = src2[x-cn], p7 = src2[x], p8 = src2[x+cn];
8616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int t;
8626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_MINMAX_8U(p1, p2); CV_MINMAX_8U(p4, p5);
8646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_MINMAX_8U(p7, p8); CV_MINMAX_8U(p0, p1);
8656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_MINMAX_8U(p3, p4); CV_MINMAX_8U(p6, p7);
8666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_MINMAX_8U(p1, p2); CV_MINMAX_8U(p4, p5);
8676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_MINMAX_8U(p7, p8); CV_MINMAX_8U(p0, p3);
8686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_MINMAX_8U(p5, p8); CV_MINMAX_8U(p4, p7);
8696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_MINMAX_8U(p3, p6); CV_MINMAX_8U(p1, p4);
8706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_MINMAX_8U(p2, p5); CV_MINMAX_8U(p4, p7);
8716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_MINMAX_8U(p4, p2); CV_MINMAX_8U(p6, p4);
8726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_MINMAX_8U(p4, p2);
8736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst[x] = (uchar)p4;
8756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
8766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
8776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return CV_OK;
8796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
8806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( x = 0; x < size.width; x++, dst += cn )
8826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
8836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        uchar* dst_cur = dst;
8846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        uchar* src_top = src;
8856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        uchar* src_bottom = src;
8866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int    k, c;
8876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int    x0 = -1;
8886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int    src_step1 = src_step, dst_step1 = dst_step;
8896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( x % 2 != 0 )
8916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
8926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            src_bottom = src_top += src_step*(size.height-1);
8936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst_cur += dst_step*(size.height-1);
8946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            src_step1 = -src_step1;
8956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst_step1 = -dst_step1;
8966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
8976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( x <= m/2 )
8996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            nx++;
9006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( nx < m )
9026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            x0 = x < m/2 ? 0 : (nx-1)*cn;
9036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // init accumulator
9056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        memset( zone0, 0, sizeof(zone0[0])*cn );
9066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        memset( zone1, 0, sizeof(zone1[0])*cn );
9076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( y = 0; y <= m/2; y++ )
9096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
9106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( c = 0; c < cn; c++ )
9116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
9126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( y > 0 )
9136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
9146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( x0 >= 0 )
9156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        UPDATE_ACC01( src_bottom[x0+c], c, += (m - nx) );
9166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    for( k = 0; k < nx*cn; k += cn )
9176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        UPDATE_ACC01( src_bottom[k+c], c, ++ );
9186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
9196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else
9206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
9216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( x0 >= 0 )
9226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        UPDATE_ACC01( src_bottom[x0+c], c, += (m - nx)*(m/2+1) );
9236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    for( k = 0; k < nx*cn; k += cn )
9246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        UPDATE_ACC01( src_bottom[k+c], c, += m/2+1 );
9256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
9266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
9276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( (src_step1 > 0 && y < size.height-1) ||
9296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                (src_step1 < 0 && size.height-y-1 > 0) )
9306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                src_bottom += src_step1;
9316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
9326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( y = 0; y < size.height; y++, dst_cur += dst_step1 )
9346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
9356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            // find median
9366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( c = 0; c < cn; c++ )
9376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
9386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int s = 0;
9396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k = 0; ; k++ )
9406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
9416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int t = s + zone0[c][k];
9426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( t > n2 ) break;
9436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s = t;
9446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
9456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k *= N; ;k++ )
9476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
9486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    s += zone1[c][k];
9496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( s > n2 ) break;
9506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
9516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst_cur[c] = (uchar)k;
9536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
9546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( y+1 == size.height )
9566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                break;
9576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( cn == 1 )
9596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
9606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k = 0; k < nx; k++ )
9616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
9626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int p = src_top[k];
9636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int q = src_bottom[k];
9646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    zone1[0][p]--;
9656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    zone0[0][p>>4]--;
9666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    zone1[0][q]++;
9676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    zone0[0][q>>4]++;
9686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
9696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
9706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if( cn == 3 )
9716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
9726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k = 0; k < nx*3; k += 3 )
9736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
9746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    UPDATE_ACC01( src_top[k], 0, -- );
9756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    UPDATE_ACC01( src_top[k+1], 1, -- );
9766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    UPDATE_ACC01( src_top[k+2], 2, -- );
9776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    UPDATE_ACC01( src_bottom[k], 0, ++ );
9796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    UPDATE_ACC01( src_bottom[k+1], 1, ++ );
9806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    UPDATE_ACC01( src_bottom[k+2], 2, ++ );
9816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
9826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
9836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
9846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
9856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                assert( cn == 4 );
9866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k = 0; k < nx*4; k += 4 )
9876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
9886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    UPDATE_ACC01( src_top[k], 0, -- );
9896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    UPDATE_ACC01( src_top[k+1], 1, -- );
9906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    UPDATE_ACC01( src_top[k+2], 2, -- );
9916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    UPDATE_ACC01( src_top[k+3], 3, -- );
9926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    UPDATE_ACC01( src_bottom[k], 0, ++ );
9946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    UPDATE_ACC01( src_bottom[k+1], 1, ++ );
9956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    UPDATE_ACC01( src_bottom[k+2], 2, ++ );
9966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    UPDATE_ACC01( src_bottom[k+3], 3, ++ );
9976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
9986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
9996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( x0 >= 0 )
10016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
10026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( c = 0; c < cn; c++ )
10036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
10046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    UPDATE_ACC01( src_top[x0+c], c, -= (m - nx) );
10056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    UPDATE_ACC01( src_bottom[x0+c], c, += (m - nx) );
10066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
10076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
10086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( (src_step1 > 0 && src_bottom + src_step1 < src_max) ||
10106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                (src_step1 < 0 && src_bottom + src_step1 >= src) )
10116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                src_bottom += src_step1;
10126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( y >= m/2 )
10146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                src_top += src_step1;
10156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
10166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( x >= m/2 )
10186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            src += cn;
10196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( src + nx*cn > src_right ) nx--;
10206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
10216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#undef N
10226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#undef UPDATE_ACC
10236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return CV_OK;
10246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
10256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\
10286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                   Bilateral Filtering
10296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/
10306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
10326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvBilateralFiltering_8u( const CvMat* src, CvMat* dst, int d,
10336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          double sigma_color, double sigma_space )
10346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
10356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat* temp = 0;
10366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    float* color_weight = 0;
10376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    float* space_weight = 0;
10386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int* space_ofs = 0;
10396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvBilateralFiltering_8u" );
10416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
10436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double gauss_color_coeff = -0.5/(sigma_color*sigma_color);
10456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double gauss_space_coeff = -0.5/(sigma_space*sigma_space);
10466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int cn = CV_MAT_CN(src->type);
10476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, j, k, maxk, radius;
10486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSize size = cvGetMatSize(src);
10496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( (CV_MAT_TYPE(src->type) != CV_8UC1 &&
10516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_MAT_TYPE(src->type) != CV_8UC3) ||
10526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        !CV_ARE_TYPES_EQ(src, dst) )
10536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsUnsupportedFormat,
10546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        "Both source and destination must be 8-bit, single-channel or 3-channel images" );
10556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( sigma_color <= 0 )
10576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        sigma_color = 1;
10586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( sigma_space <= 0 )
10596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        sigma_space = 1;
10606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( d == 0 )
10626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        radius = cvRound(sigma_space*1.5);
10636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
10646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        radius = d/2;
10656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    radius = MAX(radius, 1);
10666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    d = radius*2 + 1;
10676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( temp = cvCreateMat( src->rows + radius*2,
10696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        src->cols + radius*2, src->type ));
10706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvCopyMakeBorder( src, temp, cvPoint(radius,radius), IPL_BORDER_REPLICATE ));
10716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( color_weight = (float*)cvAlloc(cn*256*sizeof(color_weight[0])));
10726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( space_weight = (float*)cvAlloc(d*d*sizeof(space_weight[0])));
10736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( space_ofs = (int*)cvAlloc(d*d*sizeof(space_ofs[0])));
10746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // initialize color-related bilateral filter coefficients
10766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < 256*cn; i++ )
10776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        color_weight[i] = (float)exp(i*i*gauss_color_coeff);
10786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // initialize space-related bilateral filter coefficients
10806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = -radius, maxk = 0; i <= radius; i++ )
10816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( j = -radius; j <= radius; j++ )
10826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
10836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double r = sqrt((double)i*i + (double)j*j);
10846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( r > radius )
10856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                continue;
10866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            space_weight[maxk] = (float)exp(r*r*gauss_space_coeff);
10876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            space_ofs[maxk++] = i*temp->step + j*cn;
10886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
10896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < size.height; i++ )
10916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
10926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const uchar* sptr = temp->data.ptr + (i+radius)*temp->step + radius*cn;
10936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        uchar* dptr = dst->data.ptr + i*dst->step;
10946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( cn == 1 )
10966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
10976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( j = 0; j < size.width; j++ )
10986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
10996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                float sum = 0, wsum = 0;
11006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int val0 = sptr[j];
11016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k = 0; k < maxk; k++ )
11026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
11036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int val = sptr[j + space_ofs[k]];
11046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    float w = space_weight[k]*color_weight[abs(val - val0)];
11056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    sum += val*w;
11066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    wsum += w;
11076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
11086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                // overflow is not possible here => there is no need to use CV_CAST_8U
11096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dptr[j] = (uchar)cvRound(sum/wsum);
11106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
11116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
11126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
11136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
11146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            assert( cn == 3 );
11156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( j = 0; j < size.width*3; j += 3 )
11166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
11176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                float sum_b = 0, sum_g = 0, sum_r = 0, wsum = 0;
11186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int b0 = sptr[j], g0 = sptr[j+1], r0 = sptr[j+2];
11196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k = 0; k < maxk; k++ )
11206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
11216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    const uchar* sptr_k = sptr + j + space_ofs[k];
11226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int b = sptr_k[0], g = sptr_k[1], r = sptr_k[2];
11236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    float w = space_weight[k]*color_weight[abs(b - b0) +
11246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        abs(g - g0) + abs(r - r0)];
11256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    sum_b += b*w; sum_g += g*w; sum_r += r*w;
11266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    wsum += w;
11276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
11286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                wsum = 1.f/wsum;
11296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                b0 = cvRound(sum_b*wsum);
11306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                g0 = cvRound(sum_g*wsum);
11316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                r0 = cvRound(sum_r*wsum);
11326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dptr[j] = (uchar)b0; dptr[j+1] = (uchar)g0; dptr[j+2] = (uchar)r0;
11336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
11346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
11356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
11366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
11386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat( &temp );
11406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvFree( &color_weight );
11416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvFree( &space_weight );
11426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvFree( &space_ofs );
11436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
11446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void icvBilateralFiltering_32f( const CvMat* src, CvMat* dst, int d,
11476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                       double sigma_color, double sigma_space )
11486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
11496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  	CvMat* temp = 0;
11506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    float* space_weight = 0;
11516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int* space_ofs = 0;
11526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    float *expLUT = 0;
11536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvBilateralFiltering_32f" );
11556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
11576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double gauss_color_coeff = -0.5/(sigma_color*sigma_color);
11596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double gauss_space_coeff = -0.5/(sigma_space*sigma_space);
11606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int cn = CV_MAT_CN(src->type);
11616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, j, k, maxk, radius;
11626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double minValSrc=-1, maxValSrc=1;
11636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const int kExpNumBinsPerChannel = 1 << 12;
11646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int kExpNumBins = 0;
11656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    float lastExpVal = 1.f;
11666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int temp_step;
11676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    float len, scale_index;
11686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat src_reshaped;
11696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSize size = cvGetMatSize(src);
11716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( (CV_MAT_TYPE(src->type) != CV_32FC1 &&
11736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_MAT_TYPE(src->type) != CV_32FC3) ||
11746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        !CV_ARE_TYPES_EQ(src, dst) )
11756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsUnsupportedFormat,
11766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        "Both source and destination must be 32-bit float, single-channel or 3-channel images" );
11776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( sigma_color <= 0 )
11796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        sigma_color = 1;
11806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( sigma_space <= 0 )
11816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        sigma_space = 1;
11826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( d == 0 )
11846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        radius = cvRound(sigma_space*1.5);
11856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
11866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        radius = d/2;
11876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    radius = MAX(radius, 1);
11886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    d = radius*2 + 1;
11896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // compute the min/max range for the input image (even if multichannel)
11906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvReshape( src, &src_reshaped, 1 ) );
11926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvMinMaxLoc(&src_reshaped, &minValSrc, &maxValSrc) );
11936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // temporary copy of the image with borders for easy processing
11956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( temp = cvCreateMat( src->rows + radius*2,
11966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        src->cols + radius*2, src->type ));
11976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    temp_step = temp->step/sizeof(float);
11986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvCopyMakeBorder( src, temp, cvPoint(radius,radius), IPL_BORDER_REPLICATE ));
11996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // allocate lookup tables
12006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( space_weight = (float*)cvAlloc(d*d*sizeof(space_weight[0])));
12016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( space_ofs = (int*)cvAlloc(d*d*sizeof(space_ofs[0])));
12026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // assign a length which is slightly more than needed
12046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    len = (float)(maxValSrc - minValSrc) * cn;
12056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    kExpNumBins = kExpNumBinsPerChannel * cn;
12066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( expLUT = (float*)cvAlloc((kExpNumBins+2) * sizeof(expLUT[0])));
12076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scale_index = kExpNumBins/len;
12086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // initialize the exp LUT
12106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < kExpNumBins+2; i++ )
12116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
12126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( lastExpVal > 0.f )
12136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
12146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double val =  i / scale_index;
12156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            expLUT[i] = (float)exp(val * val * gauss_color_coeff);
12166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            lastExpVal = expLUT[i];
12176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
12186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
12196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            expLUT[i] = 0.f;
12206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
12216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // initialize space-related bilateral filter coefficients
12236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = -radius, maxk = 0; i <= radius; i++ )
12246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( j = -radius; j <= radius; j++ )
12256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
12266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double r = sqrt((double)i*i + (double)j*j);
12276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( r > radius )
12286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                continue;
12296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            space_weight[maxk] = (float)exp(r*r*gauss_space_coeff);
12306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            space_ofs[maxk++] = i*temp_step + j*cn;
12316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
12326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < size.height; i++ )
12346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
12356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	    const float* sptr = temp->data.fl + (i+radius)*temp_step + radius*cn;
12366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        float* dptr = (float*)(dst->data.ptr + i*dst->step);
12376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( cn == 1 )
12396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
12406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( j = 0; j < size.width; j++ )
12416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
12426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                float sum = 0, wsum = 0;
12436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                float val0 = sptr[j];
12446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k = 0; k < maxk; k++ )
12456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
12466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    float val = sptr[j + space_ofs[k]];
12476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn					float alpha = (float)(fabs(val - val0)*scale_index);
12486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int idx = cvFloor(alpha);
12496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    alpha -= idx;
12506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    float w = space_weight[k]*(expLUT[idx] + alpha*(expLUT[idx+1] - expLUT[idx]));
12516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	                sum += val*w;
12526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    wsum += w;
12536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
12546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dptr[j] = (float)(sum/wsum);
12556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
12566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
12576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
12586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
12596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            assert( cn == 3 );
12606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( j = 0; j < size.width*3; j += 3 )
12616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
12626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                float sum_b = 0, sum_g = 0, sum_r = 0, wsum = 0;
12636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                float b0 = sptr[j], g0 = sptr[j+1], r0 = sptr[j+2];
12646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k = 0; k < maxk; k++ )
12656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
12666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    const float* sptr_k = sptr + j + space_ofs[k];
12676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    float b = sptr_k[0], g = sptr_k[1], r = sptr_k[2];
12686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn					float alpha = (float)((fabs(b - b0) + fabs(g - g0) + fabs(r - r0))*scale_index);
12696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int idx = cvFloor(alpha);
12706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    alpha -= idx;
12716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    float w = space_weight[k]*(expLUT[idx] + alpha*(expLUT[idx+1] - expLUT[idx]));
12726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    sum_b += b*w; sum_g += g*w; sum_r += r*w;
12736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    wsum += w;
12746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
12756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                wsum = 1.f/wsum;
12766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                b0 = sum_b*wsum;
12776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                g0 = sum_g*wsum;
12786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                r0 = sum_r*wsum;
12796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dptr[j] = b0; dptr[j+1] = g0; dptr[j+2] = r0;
12806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
12816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
12826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
12836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
12856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat( &temp );
12876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvFree( &space_weight );
12886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvFree( &space_ofs );
12896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvFree( &expLUT );
12906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
12916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//////////////////////////////// IPP smoothing functions /////////////////////////////////
12936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterMedian_8u_C1R_t icvFilterMedian_8u_C1R_p = 0;
12956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterMedian_8u_C3R_t icvFilterMedian_8u_C3R_p = 0;
12966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterMedian_8u_C4R_t icvFilterMedian_8u_C4R_p = 0;
12976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterBox_8u_C1R_t icvFilterBox_8u_C1R_p = 0;
12996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterBox_8u_C3R_t icvFilterBox_8u_C3R_p = 0;
13006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterBox_8u_C4R_t icvFilterBox_8u_C4R_p = 0;
13016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterBox_32f_C1R_t icvFilterBox_32f_C1R_p = 0;
13026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterBox_32f_C3R_t icvFilterBox_32f_C3R_p = 0;
13036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFilterBox_32f_C4R_t icvFilterBox_32f_C4R_p = 0;
13046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef CvStatus (CV_STDCALL * CvSmoothFixedIPPFunc)
13066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn( const void* src, int srcstep, void* dst, int dststep,
13076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  CvSize size, CvSize ksize, CvPoint anchor );
13086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//////////////////////////////////////////////////////////////////////////////////////////
13106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
13126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvSmooth( const void* srcarr, void* dstarr, int smooth_type,
13136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          int param1, int param2, double param3, double param4 )
13146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
13156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvBoxFilter box_filter;
13166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSepFilter gaussian_filter;
13176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat* temp = 0;
13196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvSmooth" );
13216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
13236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int coi1 = 0, coi2 = 0;
13256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat srcstub, *src = (CvMat*)srcarr;
13266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat dststub, *dst = (CvMat*)dstarr;
13276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSize size;
13286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int src_type, dst_type, depth, cn;
13296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double sigma1 = 0, sigma2 = 0;
13306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool have_ipp = icvFilterMedian_8u_C1R_p != 0;
13316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( src = cvGetMat( src, &srcstub, &coi1 ));
13336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( dst = cvGetMat( dst, &dststub, &coi2 ));
13346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( coi1 != 0 || coi2 != 0 )
13366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_BadCOI, "" );
13376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    src_type = CV_MAT_TYPE( src->type );
13396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dst_type = CV_MAT_TYPE( dst->type );
13406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    depth = CV_MAT_DEPTH(src_type);
13416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cn = CV_MAT_CN(src_type);
13426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    size = cvGetMatSize(src);
13436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_ARE_SIZES_EQ( src, dst ))
13456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsUnmatchedSizes, "" );
13466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( smooth_type != CV_BLUR_NO_SCALE && !CV_ARE_TYPES_EQ( src, dst ))
13486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsUnmatchedFormats,
13496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        "The specified smoothing algorithm requires input and ouput arrays be of the same type" );
13506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( smooth_type == CV_BLUR || smooth_type == CV_BLUR_NO_SCALE ||
13526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        smooth_type == CV_GAUSSIAN || smooth_type == CV_MEDIAN )
13536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
13546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // automatic detection of kernel size from sigma
13556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( smooth_type == CV_GAUSSIAN )
13566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
13576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            sigma1 = param3;
13586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            sigma2 = param4 ? param4 : param3;
13596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( param1 == 0 && sigma1 > 0 )
13616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                param1 = cvRound(sigma1*(depth == CV_8U ? 3 : 4)*2 + 1)|1;
13626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( param2 == 0 && sigma2 > 0 )
13636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                param2 = cvRound(sigma2*(depth == CV_8U ? 3 : 4)*2 + 1)|1;
13646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
13656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( param2 == 0 )
13676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            param2 = size.height == 1 ? 1 : param1;
13686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( param1 < 1 || (param1 & 1) == 0 || param2 < 1 || (param2 & 1) == 0 )
13696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsOutOfRange,
13706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                "Both mask width and height must be >=1 and odd" );
13716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( param1 == 1 && param2 == 1 )
13736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
13746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvConvert( src, dst );
13756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            EXIT;
13766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
13776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
13786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( have_ipp && (smooth_type == CV_BLUR || (smooth_type == CV_MEDIAN && param1 <= 15)) &&
13806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        size.width >= param1 && size.height >= param2 && param1 > 1 && param2 > 1 )
13816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
13826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvSmoothFixedIPPFunc ipp_median_box_func = 0;
13836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( smooth_type == CV_BLUR )
13856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
13866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ipp_median_box_func =
13876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                src_type == CV_8UC1 ? icvFilterBox_8u_C1R_p :
13886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                src_type == CV_8UC3 ? icvFilterBox_8u_C3R_p :
13896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                src_type == CV_8UC4 ? icvFilterBox_8u_C4R_p :
13906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                src_type == CV_32FC1 ? icvFilterBox_32f_C1R_p :
13916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                src_type == CV_32FC3 ? icvFilterBox_32f_C3R_p :
13926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                src_type == CV_32FC4 ? icvFilterBox_32f_C4R_p : 0;
13936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
13946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else if( smooth_type == CV_MEDIAN )
13956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
13966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ipp_median_box_func =
13976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                src_type == CV_8UC1 ? icvFilterMedian_8u_C1R_p :
13986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                src_type == CV_8UC3 ? icvFilterMedian_8u_C3R_p :
13996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                src_type == CV_8UC4 ? icvFilterMedian_8u_C4R_p : 0;
14006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
14016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( ipp_median_box_func )
14036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
14046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvSize el_size = { param1, param2 };
14056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvPoint el_anchor = { param1/2, param2/2 };
14066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int stripe_size = 1 << 14; // the optimal value may depend on CPU cache,
14076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                       // overhead of the current IPP code etc.
14086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const uchar* shifted_ptr;
14096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int y, dy = 0;
14106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int temp_step, dst_step = dst->step;
14116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( temp = icvIPPFilterInit( src, stripe_size, el_size ));
14136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            shifted_ptr = temp->data.ptr +
14156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                el_anchor.y*temp->step + el_anchor.x*CV_ELEM_SIZE(src_type);
14166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            temp_step = temp->step ? temp->step : CV_STUB_STEP;
14176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( y = 0; y < src->rows; y += dy )
14196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
14206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dy = icvIPPFilterNextStripe( src, temp, y, el_size, el_anchor );
14216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                IPPI_CALL( ipp_median_box_func( shifted_ptr, temp_step,
14226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    dst->data.ptr + y*dst_step, dst_step, cvSize(src->cols, dy),
14236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    el_size, el_anchor ));
14246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
14256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            EXIT;
14266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
14276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
14286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( smooth_type == CV_BLUR || smooth_type == CV_BLUR_NO_SCALE )
14306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
14316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( box_filter.init( src->cols, src_type, dst_type,
14326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            smooth_type == CV_BLUR, cvSize(param1, param2) ));
14336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( box_filter.process( src, dst ));
14346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
14356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( smooth_type == CV_MEDIAN )
14366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
14376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int img_size_mp = size.width*size.height;
14386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        img_size_mp = (img_size_mp + (1<<19)) >> 20;
14396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( depth != CV_8U || (cn != 1 && cn != 3 && cn != 4) )
14416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsUnsupportedFormat,
14426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            "Median filter only supports 8uC1, 8uC3 and 8uC4 images" );
14436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( size.width < param1*2 || size.height < param1*2 ||
14456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            param1 <= 3 + (img_size_mp < 1 ? 12 : img_size_mp < 4 ? 6 : 2)*(MEDIAN_HAVE_SIMD ? 1 : 3))
14466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
14476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            // Special case optimized for 3x3
14486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            IPPI_CALL( icvMedianBlur_8u_CnR_Om( src->data.ptr, src->step,
14496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst->data.ptr, dst->step, size, param1, cn ));
14506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
14516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
14526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
14536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const int r = (param1 - 1) / 2;
14546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const int CACHE_SIZE = (int) ( 0.95 * 256 * 1024 / cn );  // assume a 256 kB cache size
14556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const int STRIPES = (int) cvCeil( (double) (size.width - 2*r) /
14566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    (CACHE_SIZE / sizeof(Histogram) - 2*r) );
14576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const int STRIPE_SIZE = (int) cvCeil(
14586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    (double) ( size.width + STRIPES*2*r - 2*r ) / STRIPES );
14596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( int i = 0; i < size.width; i += STRIPE_SIZE - 2*r )
14616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
14626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int stripe = STRIPE_SIZE;
14636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                // Make sure that the filter kernel fits into one stripe.
14646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( i + STRIPE_SIZE - 2*r >= size.width ||
14656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    size.width - (i + STRIPE_SIZE - 2*r) < 2*r+1 )
14666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    stripe = size.width - i;
14676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                IPPI_CALL( icvMedianBlur_8u_CnR_O1( src->data.ptr + cn*i, src->step,
14696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    dst->data.ptr + cn*i, dst->step, cvSize(stripe, size.height),
14706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    param1, cn, i == 0, stripe == size.width - i ));
14716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( stripe == size.width - i )
14736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
14746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
14756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
14766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
14776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( smooth_type == CV_GAUSSIAN )
14786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
14796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvSize ksize = { param1, param2 };
14806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        float* kx = (float*)cvStackAlloc( ksize.width*sizeof(kx[0]) );
14816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        float* ky = (float*)cvStackAlloc( ksize.height*sizeof(ky[0]) );
14826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvMat KX = cvMat( 1, ksize.width, CV_32F, kx );
14836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvMat KY = cvMat( 1, ksize.height, CV_32F, ky );
14846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvSepFilter::init_gaussian_kernel( &KX, sigma1 );
14866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( ksize.width != ksize.height || fabs(sigma1 - sigma2) > FLT_EPSILON )
14876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvSepFilter::init_gaussian_kernel( &KY, sigma2 );
14886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
14896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            KY.data.fl = kx;
14906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( have_ipp && size.width >= param1*3 &&
14926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            size.height >= param2 && param1 > 1 && param2 > 1 )
14936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
14946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int done;
14956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( done = icvIPPSepFilter( src, dst, &KX, &KY,
14966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        cvPoint(ksize.width/2,ksize.height/2)));
14976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( done )
14986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                EXIT;
14996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
15006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( gaussian_filter.init( src->cols, src_type, dst_type, &KX, &KY ));
15026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( gaussian_filter.process( src, dst ));
15036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
15046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( smooth_type == CV_BILATERAL )
15056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
15066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( param2 != 0 && (param2 != param1 || param1 % 2 == 0) )
15076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsBadSize, "Bilateral filter only supports square windows of odd size" );
15086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        switch( src_type )
15106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
15116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        case CV_32FC1:
15126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        case CV_32FC3:
15136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( icvBilateralFiltering_32f( src, dst, param1, param3, param4 ));
15146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            break;
15156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        case CV_8UC1:
15166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        case CV_8UC3:
15176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( icvBilateralFiltering_8u( src, dst, param1, param3, param4 ));
15186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            break;
15196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        default:
15206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsUnsupportedFormat,
15216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                "Unknown/unsupported format: bilateral filter only supports 8uC1, 8uC3, 32fC1 and 32fC3 formats" );
15226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
15236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
15246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
15266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat( &temp );
15286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
15296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* End of file. */
1531