gaussianblur.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:10k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * gaussianblur.c : gaussian blur video filter
  3.  *****************************************************************************
  4.  * Copyright (C) 2000-2007 the VideoLAN team
  5.  * $Id: a8f96efc6833908b39e04f8efe865a0e24e45e7d $
  6.  *
  7.  * Authors: Antoine Cellerier <dionoea -at- videolan -dot- org>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #ifdef HAVE_CONFIG_H
  27. # include "config.h"
  28. #endif
  29. #include <vlc_common.h>
  30. #include <vlc_plugin.h>
  31. #include <vlc_vout.h>
  32. #include "vlc_filter.h"
  33. #include "filter_picture.h"
  34. #include <math.h>                                          /* exp(), sqrt() */
  35. /*****************************************************************************
  36.  * Module descriptor
  37.  *****************************************************************************/
  38. static int  Create    ( vlc_object_t * );
  39. static void Destroy   ( vlc_object_t * );
  40. #define SIGMA_TEXT N_("Gaussian's std deviation")
  41. #define SIGMA_LONGTEXT N_( 
  42.     "Gaussian's standard deviation. The bluring will take " 
  43.     "into account pixels up to 3*sigma away in any direction.")
  44. #define FILTER_PREFIX "gaussianblur-"
  45. vlc_module_begin ()
  46.     set_description( N_("Gaussian blur video filter") )
  47.     set_shortname( N_( "Gaussian Blur" ))
  48.     set_capability( "video filter2", 0 )
  49.     set_category( CAT_VIDEO )
  50.     set_subcategory( SUBCAT_VIDEO_VFILTER )
  51.     add_float( FILTER_PREFIX "sigma", 2., NULL, SIGMA_TEXT, SIGMA_LONGTEXT,
  52.                false )
  53.     set_callbacks( Create, Destroy )
  54. vlc_module_end ()
  55. /*****************************************************************************
  56.  * Local prototypes
  57.  *****************************************************************************/
  58. static picture_t *Filter( filter_t *, picture_t * );
  59. static const char *const ppsz_filter_options[] = {
  60.     "sigma", NULL
  61. };
  62. /* Comment this to use floats instead of integers (faster for bigger sigma
  63.  * values)
  64.  * For sigma = 2 ints are faster
  65.  * For sigma = 4 floats are faster
  66.  */
  67. #define DONT_USE_FLOATS
  68. #ifdef DONT_USE_FLOATS
  69. #   define type_t int
  70. #else
  71. #   define type_t float
  72. #endif
  73. struct filter_sys_t
  74. {
  75.     double f_sigma;
  76.     int i_dim;
  77.     type_t *pt_distribution;
  78.     type_t *pt_buffer;
  79.     type_t *pt_scale;
  80. };
  81. static void gaussianblur_InitDistribution( filter_sys_t *p_sys )
  82. {
  83.     double f_sigma = p_sys->f_sigma;
  84.     int i_dim = (int)(3.*f_sigma);
  85.     type_t *pt_distribution = malloc( (2*i_dim+1) * sizeof( type_t ) );
  86.     int x;
  87.     for( x = -i_dim; x <= i_dim; x++ )
  88.     {
  89.         const float f_distribution = sqrt( exp(-(x*x)/(f_sigma*f_sigma) ) / (2.*M_PI*f_sigma*f_sigma) );
  90. #ifdef DONT_USE_FLOATS
  91.         const float f_factor = 1 << 8;
  92. #else
  93.         const float f_factor = 1;
  94. #endif
  95.         pt_distribution[i_dim+x] = (type_t)( f_distribution * f_factor );
  96.         //printf("%fn",(float)pt_distribution[i_dim+x]);
  97.     }
  98.     p_sys->i_dim = i_dim;
  99.     p_sys->pt_distribution = pt_distribution;
  100. }
  101. static int Create( vlc_object_t *p_this )
  102. {
  103.     filter_t *p_filter = (filter_t *)p_this;
  104.     if(   p_filter->fmt_in.video.i_chroma != VLC_FOURCC('I','4','2','0')
  105.        && p_filter->fmt_in.video.i_chroma != VLC_FOURCC('I','Y','U','V')
  106.        && p_filter->fmt_in.video.i_chroma != VLC_FOURCC('J','4','2','0')
  107.        && p_filter->fmt_in.video.i_chroma != VLC_FOURCC('Y','V','1','2')
  108.        && p_filter->fmt_in.video.i_chroma != VLC_FOURCC('I','4','2','2')
  109.        && p_filter->fmt_in.video.i_chroma != VLC_FOURCC('J','4','2','2')
  110.       )
  111.     {
  112.         /* We only want planar YUV 4:2:0 or 4:2:2 */
  113.         msg_Err( p_filter, "Unsupported input chroma (%4s)",
  114.                  (char*)&(p_filter->fmt_in.video.i_chroma) );
  115.         return VLC_EGENERIC;
  116.     }
  117.     if( p_filter->fmt_in.video.i_chroma != p_filter->fmt_out.video.i_chroma )
  118.     {
  119.         msg_Err( p_filter, "Input and output chromas don't match" );
  120.         return VLC_EGENERIC;
  121.     }
  122.     p_filter->p_sys = malloc( sizeof( filter_sys_t ) );
  123.     if( p_filter->p_sys == NULL )
  124.         return VLC_ENOMEM;
  125.     config_ChainParse( p_filter, FILTER_PREFIX, ppsz_filter_options,
  126.                        p_filter->p_cfg );
  127.     p_filter->pf_video_filter = Filter;
  128.     p_filter->p_sys->f_sigma =
  129.         var_CreateGetFloat( p_filter, FILTER_PREFIX "sigma" );
  130.     if( p_filter->p_sys->f_sigma <= 0. )
  131.     {
  132.         msg_Err( p_filter, "sigma must be positive" );
  133.         return VLC_EGENERIC;
  134.     }
  135.     gaussianblur_InitDistribution( p_filter->p_sys );
  136.     msg_Dbg( p_filter, "gaussian distribution is %d pixels wide",
  137.              p_filter->p_sys->i_dim*2+1 );
  138.     p_filter->p_sys->pt_buffer = NULL;
  139.     p_filter->p_sys->pt_scale = NULL;
  140.     return VLC_SUCCESS;
  141. }
  142. static void Destroy( vlc_object_t *p_this )
  143. {
  144.     filter_t *p_filter = (filter_t *)p_this;
  145.     free( p_filter->p_sys->pt_distribution );
  146.     free( p_filter->p_sys->pt_buffer );
  147.     free( p_filter->p_sys->pt_scale );
  148.     free( p_filter->p_sys );
  149. }
  150. static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
  151. {
  152.     picture_t *p_outpic;
  153.     filter_sys_t *p_sys = p_filter->p_sys;
  154.     int i_plane;
  155.     const int i_dim = p_sys->i_dim;
  156.     type_t *pt_buffer;
  157.     type_t *pt_scale;
  158.     const type_t *pt_distribution = p_sys->pt_distribution;
  159.     if( !p_pic ) return NULL;
  160.     p_outpic = filter_NewPicture( p_filter );
  161.     if( !p_outpic )
  162.     {
  163.         picture_Release( p_pic );
  164.         return NULL;
  165.     }
  166.     if( !p_sys->pt_buffer )
  167.     {
  168.         p_sys->pt_buffer = realloc( p_sys->pt_buffer,
  169.                                     p_pic->p[Y_PLANE].i_visible_lines *
  170.                                         p_pic->p[Y_PLANE].i_pitch *
  171.                                         sizeof( type_t ) );
  172.     }
  173.     pt_buffer = p_sys->pt_buffer;
  174.     if( !p_sys->pt_scale )
  175.     {
  176.         const int i_visible_lines = p_pic->p[Y_PLANE].i_visible_lines;
  177.         const int i_visible_pitch = p_pic->p[Y_PLANE].i_visible_pitch;
  178.         const int i_pitch = p_pic->p[Y_PLANE].i_pitch;
  179.         int i_col, i_line;
  180.         p_sys->pt_scale = malloc( i_visible_lines * i_pitch * sizeof( type_t ) );
  181.         pt_scale = p_sys->pt_scale;
  182.         for( i_line = 0 ; i_line < i_visible_lines ; i_line++ )
  183.         {
  184.             for( i_col = 0; i_col < i_visible_pitch ; i_col++ )
  185.             {
  186.                 int x, y;
  187.                 type_t t_value = 0;
  188.                 for( y = __MAX( -i_dim, -i_line );
  189.                      y <= __MIN( i_dim, i_visible_lines - i_line - 1 );
  190.                      y++ )
  191.                 {
  192.                     for( x = __MAX( -i_dim, -i_col );
  193.                          x <= __MIN( i_dim, i_visible_pitch - i_col + 1 );
  194.                          x++ )
  195.                     {
  196.                         t_value += pt_distribution[y+i_dim] *
  197.                                    pt_distribution[x+i_dim];
  198.                     }
  199.                 }
  200.                 pt_scale[i_line*i_pitch+i_col] = t_value;
  201.             }
  202.         }
  203.     }
  204.     pt_scale = p_sys->pt_scale;
  205.     for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
  206.     {
  207.         uint8_t *p_in = p_pic->p[i_plane].p_pixels;
  208.         uint8_t *p_out = p_outpic->p[i_plane].p_pixels;
  209.         const int i_visible_lines = p_pic->p[i_plane].i_visible_lines;
  210.         const int i_visible_pitch = p_pic->p[i_plane].i_visible_pitch;
  211.         const int i_pitch = p_pic->p[i_plane].i_pitch;
  212.         int i_line, i_col;
  213.         const int x_factor = p_pic->p[Y_PLANE].i_visible_pitch/i_visible_pitch-1;
  214.         const int y_factor = p_pic->p[Y_PLANE].i_visible_lines/i_visible_lines-1;
  215.         for( i_line = 0 ; i_line < i_visible_lines ; i_line++ )
  216.         {
  217.             for( i_col = 0; i_col < i_visible_pitch ; i_col++ )
  218.             {
  219.                 type_t t_value = 0;
  220.                 int x;
  221.                 const int c = i_line*i_pitch+i_col;
  222.                 for( x = __MAX( -i_dim, -i_col*(x_factor+1) );
  223.                      x <= __MIN( i_dim, (i_visible_pitch - i_col)*(x_factor+1) + 1 );
  224.                      x++ )
  225.                 {
  226.                     t_value += pt_distribution[x+i_dim] *
  227.                                p_in[c+(x>>x_factor)];
  228.                 }
  229.                 pt_buffer[c] = t_value;
  230.             }
  231.         }
  232.         for( i_line = 0 ; i_line < i_visible_lines ; i_line++ )
  233.         {
  234.             for( i_col = 0; i_col < i_visible_pitch ; i_col++ )
  235.             {
  236.                 type_t t_value = 0;
  237.                 int y;
  238.                 const int c = i_line*i_pitch+i_col;
  239.                 for( y = __MAX( -i_dim, (-i_line)*(y_factor+1) );
  240.                      y <= __MIN( i_dim, (i_visible_lines - i_line)*(y_factor+1) - 1 );
  241.                      y++ )
  242.                 {
  243.                     t_value += pt_distribution[y+i_dim] *
  244.                                pt_buffer[c+(y>>y_factor)*i_pitch];
  245.                 }
  246.                 const type_t t_scale = pt_scale[(i_line<<y_factor)*(i_pitch<<x_factor)+(i_col<<x_factor)];
  247.                 p_out[c] = (uint8_t)(t_value / t_scale); // FIXME wouldn't it be better to round instead of trunc ?
  248.             }
  249.         }
  250.     }
  251.     return CopyInfoAndRelease( p_outpic, p_pic );
  252. }