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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * adjust.c : Contrast/Hue/Saturation/Brightness video plugin for vlc
  3.  *****************************************************************************
  4.  * Copyright (C) 2000-2006 the VideoLAN team
  5.  * $Id: fa671dc2127d58b5e3f26fd91cee72961f1af140 $
  6.  *
  7.  * Authors: Simon Latapie <garf@via.ecp.fr>
  8.  *          Antoine Cellerier <dionoea -at- videolan d0t org>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  23.  *****************************************************************************/
  24. /*****************************************************************************
  25.  * Preamble
  26.  *****************************************************************************/
  27. #ifdef HAVE_CONFIG_H
  28. # include "config.h"
  29. #endif
  30. #include <errno.h>
  31. #include <math.h>
  32. #include <vlc_common.h>
  33. #include <vlc_plugin.h>
  34. #include <vlc_sout.h>
  35. #include <vlc_vout.h>
  36. #include "vlc_filter.h"
  37. #include "filter_picture.h"
  38. #ifndef M_PI
  39. #   define M_PI 3.14159265358979323846
  40. #endif
  41. #define eight_times( x )    x x x x x x x x
  42. /*****************************************************************************
  43.  * Local prototypes
  44.  *****************************************************************************/
  45. static int  Create    ( vlc_object_t * );
  46. static void Destroy   ( vlc_object_t * );
  47. static picture_t *FilterPlanar( filter_t *, picture_t * );
  48. static picture_t *FilterPacked( filter_t *, picture_t * );
  49. static int AdjustCallback( vlc_object_t *p_this, char const *psz_var,
  50.                            vlc_value_t oldval, vlc_value_t newval,
  51.                            void *p_data );
  52. /*****************************************************************************
  53.  * Module descriptor
  54.  *****************************************************************************/
  55. #define THRES_TEXT N_("Brightness threshold")
  56. #define THRES_LONGTEXT N_("When this mode is enabled, pixels will be " 
  57.         "shown as black or white. The threshold value will be the brighness " 
  58.         "defined below." )
  59. #define CONT_TEXT N_("Image contrast (0-2)")
  60. #define CONT_LONGTEXT N_("Set the image contrast, between 0 and 2. Defaults to 1.")
  61. #define HUE_TEXT N_("Image hue (0-360)")
  62. #define HUE_LONGTEXT N_("Set the image hue, between 0 and 360. Defaults to 0.")
  63. #define SAT_TEXT N_("Image saturation (0-3)")
  64. #define SAT_LONGTEXT N_("Set the image saturation, between 0 and 3. Defaults to 1.")
  65. #define LUM_TEXT N_("Image brightness (0-2)")
  66. #define LUM_LONGTEXT N_("Set the image brightness, between 0 and 2. Defaults to 1.")
  67. #define GAMMA_TEXT N_("Image gamma (0-10)")
  68. #define GAMMA_LONGTEXT N_("Set the image gamma, between 0.01 and 10. Defaults to 1.")
  69. vlc_module_begin ()
  70.     set_description( N_("Image properties filter") )
  71.     set_shortname( N_("Image adjust" ))
  72.     set_category( CAT_VIDEO )
  73.     set_subcategory( SUBCAT_VIDEO_VFILTER )
  74.     set_capability( "video filter2", 0 )
  75.     add_float_with_range( "contrast", 1.0, 0.0, 2.0, NULL,
  76.                           CONT_TEXT, CONT_LONGTEXT, false )
  77.     add_float_with_range( "brightness", 1.0, 0.0, 2.0, NULL,
  78.                            LUM_TEXT, LUM_LONGTEXT, false )
  79.     add_integer_with_range( "hue", 0, 0, 360, NULL,
  80.                             HUE_TEXT, HUE_LONGTEXT, false )
  81.     add_float_with_range( "saturation", 1.0, 0.0, 3.0, NULL,
  82.                           SAT_TEXT, SAT_LONGTEXT, false )
  83.     add_float_with_range( "gamma", 1.0, 0.01, 10.0, NULL,
  84.                           GAMMA_TEXT, GAMMA_LONGTEXT, false )
  85.     add_bool( "brightness-threshold", 0, NULL,
  86.               THRES_TEXT, THRES_LONGTEXT, false )
  87.     add_shortcut( "adjust" )
  88.     set_callbacks( Create, Destroy )
  89. vlc_module_end ()
  90. static const char *const ppsz_filter_options[] = {
  91.     "contrast", "brightness", "hue", "saturation", "gamma",
  92.     "brightness-threshold", NULL
  93. };
  94. /*****************************************************************************
  95.  * filter_sys_t: adjust filter method descriptor
  96.  *****************************************************************************/
  97. struct filter_sys_t
  98. {
  99.     vlc_mutex_t lock;
  100.     double     f_contrast;
  101.     double     f_brightness;
  102.     int        i_hue;
  103.     double     f_saturation;
  104.     double     f_gamma;
  105.     bool b_brightness_threshold;
  106. };
  107. /*****************************************************************************
  108.  * Create: allocates adjust video filter
  109.  *****************************************************************************/
  110. static int Create( vlc_object_t *p_this )
  111. {
  112.     filter_t *p_filter = (filter_t *)p_this;
  113.     filter_sys_t *p_sys;
  114.     switch( p_filter->fmt_in.video.i_chroma )
  115.     {
  116.         CASE_PLANAR_YUV
  117.             /* Planar YUV */
  118.             p_filter->pf_video_filter = FilterPlanar;
  119.             break;
  120.         CASE_PACKED_YUV_422
  121.             /* Packed YUV 4:2:2 */
  122.             p_filter->pf_video_filter = FilterPacked;
  123.             break;
  124.         default:
  125.             msg_Err( p_filter, "Unsupported input chroma (%4s)",
  126.                      (char*)&(p_filter->fmt_in.video.i_chroma) );
  127.             return VLC_EGENERIC;
  128.     }
  129.     if( p_filter->fmt_in.video.i_chroma != p_filter->fmt_out.video.i_chroma )
  130.     {
  131.         msg_Err( p_filter, "Input and output chromas don't match" );
  132.         return VLC_EGENERIC;
  133.     }
  134.     /* Allocate structure */
  135.     p_filter->p_sys = malloc( sizeof( filter_sys_t ) );
  136.     if( p_filter->p_sys == NULL )
  137.         return VLC_ENOMEM;
  138.     p_sys = p_filter->p_sys;
  139.     /* needed to get options passed in transcode using the
  140.      * adjust{name=value} syntax */
  141.     config_ChainParse( p_filter, "", ppsz_filter_options,
  142.                    p_filter->p_cfg );
  143.     p_sys->f_contrast = var_CreateGetFloatCommand( p_filter, "contrast" );
  144.     p_sys->f_brightness = var_CreateGetFloatCommand( p_filter, "brightness" );
  145.     p_sys->i_hue = var_CreateGetIntegerCommand( p_filter, "hue" );
  146.     p_sys->f_saturation = var_CreateGetFloatCommand( p_filter, "saturation" );
  147.     p_sys->f_gamma = var_CreateGetFloatCommand( p_filter, "gamma" );
  148.     p_sys->b_brightness_threshold =
  149.         var_CreateGetBoolCommand( p_filter, "brightness-threshold" );
  150.     vlc_mutex_init( &p_sys->lock );
  151.     var_AddCallback( p_filter, "contrast",   AdjustCallback, p_sys );
  152.     var_AddCallback( p_filter, "brightness", AdjustCallback, p_sys );
  153.     var_AddCallback( p_filter, "hue",        AdjustCallback, p_sys );
  154.     var_AddCallback( p_filter, "saturation", AdjustCallback, p_sys );
  155.     var_AddCallback( p_filter, "gamma",      AdjustCallback, p_sys );
  156.     var_AddCallback( p_filter, "brightness-threshold",
  157.                                              AdjustCallback, p_sys );
  158.     return VLC_SUCCESS;
  159. }
  160. /*****************************************************************************
  161.  * Destroy: destroy adjust video filter
  162.  *****************************************************************************/
  163. static void Destroy( vlc_object_t *p_this )
  164. {
  165.     filter_t *p_filter = (filter_t *)p_this;
  166.     filter_sys_t *p_sys = p_filter->p_sys;
  167.     var_DelCallback( p_filter, "contrast",   AdjustCallback, p_sys );
  168.     var_DelCallback( p_filter, "brightness", AdjustCallback, p_sys );
  169.     var_DelCallback( p_filter, "hue",        AdjustCallback, p_sys );
  170.     var_DelCallback( p_filter, "saturation", AdjustCallback, p_sys );
  171.     var_DelCallback( p_filter, "gamma",      AdjustCallback, p_sys );
  172.     var_DelCallback( p_filter, "brightness-threshold",
  173.                                              AdjustCallback, p_sys );
  174.     vlc_mutex_destroy( &p_sys->lock );
  175.     free( p_sys );
  176. }
  177. /*****************************************************************************
  178.  * Run the filter on a Planar YUV picture
  179.  *****************************************************************************/
  180. static picture_t *FilterPlanar( filter_t *p_filter, picture_t *p_pic )
  181. {
  182.     int pi_luma[256];
  183.     int pi_gamma[256];
  184.     picture_t *p_outpic;
  185.     uint8_t *p_in, *p_in_v, *p_in_end, *p_line_end;
  186.     uint8_t *p_out, *p_out_v;
  187.     bool b_thres;
  188.     double  f_hue;
  189.     double  f_gamma;
  190.     int32_t i_cont, i_lum;
  191.     int i_sat, i_sin, i_cos, i_x, i_y;
  192.     int i;
  193.     filter_sys_t *p_sys = p_filter->p_sys;
  194.     if( !p_pic ) return NULL;
  195.     p_outpic = filter_NewPicture( p_filter );
  196.     if( !p_outpic )
  197.     {
  198.         picture_Release( p_pic );
  199.         return NULL;
  200.     }
  201.     /* Get variables */
  202.     vlc_mutex_lock( &p_sys->lock );
  203.     i_cont = (int)( p_sys->f_contrast * 255 );
  204.     i_lum = (int)( (p_sys->f_brightness - 1.0)*255 );
  205.     f_hue = (float)( p_sys->i_hue * M_PI / 180 );
  206.     i_sat = (int)( p_sys->f_saturation * 256 );
  207.     f_gamma = 1.0 / p_sys->f_gamma;
  208.     b_thres = p_sys->b_brightness_threshold;
  209.     vlc_mutex_unlock( &p_sys->lock );
  210.     /*
  211.      * Threshold mode drops out everything about luma, contrast and gamma.
  212.      */
  213.     if( b_thres != true )
  214.     {
  215.         /* Contrast is a fast but kludged function, so I put this gap to be
  216.          * cleaner :) */
  217.         i_lum += 128 - i_cont / 2;
  218.         /* Fill the gamma lookup table */
  219.         for( i = 0 ; i < 256 ; i++ )
  220.         {
  221.           pi_gamma[ i ] = clip_uint8_vlc( pow(i / 255.0, f_gamma) * 255.0);
  222.         }
  223.         /* Fill the luma lookup table */
  224.         for( i = 0 ; i < 256 ; i++ )
  225.         {
  226.             pi_luma[ i ] = pi_gamma[clip_uint8_vlc( i_lum + i_cont * i / 256)];
  227.         }
  228.     }
  229.     else
  230.     {
  231.         /*
  232.          * We get luma as threshold value: the higher it is, the darker is
  233.          * the image. Should I reverse this?
  234.          */
  235.         for( i = 0 ; i < 256 ; i++ )
  236.         {
  237.             pi_luma[ i ] = (i < i_lum) ? 0 : 255;
  238.         }
  239.         /*
  240.          * Desaturates image to avoid that strange yellow halo...
  241.          */
  242.         i_sat = 0;
  243.     }
  244.     /*
  245.      * Do the Y plane
  246.      */
  247.     p_in = p_pic->p[Y_PLANE].p_pixels;
  248.     p_in_end = p_in + p_pic->p[Y_PLANE].i_visible_lines
  249.                       * p_pic->p[Y_PLANE].i_pitch - 8;
  250.     p_out = p_outpic->p[Y_PLANE].p_pixels;
  251.     for( ; p_in < p_in_end ; )
  252.     {
  253.         p_line_end = p_in + p_pic->p[Y_PLANE].i_visible_pitch - 8;
  254.         for( ; p_in < p_line_end ; )
  255.         {
  256.             /* Do 8 pixels at a time */
  257.             *p_out++ = pi_luma[ *p_in++ ]; *p_out++ = pi_luma[ *p_in++ ];
  258.             *p_out++ = pi_luma[ *p_in++ ]; *p_out++ = pi_luma[ *p_in++ ];
  259.             *p_out++ = pi_luma[ *p_in++ ]; *p_out++ = pi_luma[ *p_in++ ];
  260.             *p_out++ = pi_luma[ *p_in++ ]; *p_out++ = pi_luma[ *p_in++ ];
  261.         }
  262.         p_line_end += 8;
  263.         for( ; p_in < p_line_end ; )
  264.         {
  265.             *p_out++ = pi_luma[ *p_in++ ];
  266.         }
  267.         p_in += p_pic->p[Y_PLANE].i_pitch
  268.               - p_pic->p[Y_PLANE].i_visible_pitch;
  269.         p_out += p_outpic->p[Y_PLANE].i_pitch
  270.                - p_outpic->p[Y_PLANE].i_visible_pitch;
  271.     }
  272.     /*
  273.      * Do the U and V planes
  274.      */
  275.     p_in = p_pic->p[U_PLANE].p_pixels;
  276.     p_in_v = p_pic->p[V_PLANE].p_pixels;
  277.     p_in_end = p_in + p_pic->p[U_PLANE].i_visible_lines
  278.                       * p_pic->p[U_PLANE].i_pitch - 8;
  279.     p_out = p_outpic->p[U_PLANE].p_pixels;
  280.     p_out_v = p_outpic->p[V_PLANE].p_pixels;
  281.     i_sin = sin(f_hue) * 256;
  282.     i_cos = cos(f_hue) * 256;
  283.     i_x = ( cos(f_hue) + sin(f_hue) ) * 32768;
  284.     i_y = ( cos(f_hue) - sin(f_hue) ) * 32768;
  285.     if ( i_sat > 256 )
  286.     {
  287. #define WRITE_UV_CLIP() 
  288.     i_u = *p_in++ ; i_v = *p_in_v++ ; 
  289.     *p_out++ = clip_uint8_vlc( (( ((i_u * i_cos + i_v * i_sin - i_x) >> 8) 
  290.                            * i_sat) >> 8) + 128); 
  291.     *p_out_v++ = clip_uint8_vlc( (( ((i_v * i_cos - i_u * i_sin - i_y) >> 8) 
  292.                            * i_sat) >> 8) + 128)
  293.         uint8_t i_u, i_v;
  294.         for( ; p_in < p_in_end ; )
  295.         {
  296.             p_line_end = p_in + p_pic->p[U_PLANE].i_visible_pitch - 8;
  297.             for( ; p_in < p_line_end ; )
  298.             {
  299.                 /* Do 8 pixels at a time */
  300.                 WRITE_UV_CLIP(); WRITE_UV_CLIP();
  301.                 WRITE_UV_CLIP(); WRITE_UV_CLIP();
  302.                 WRITE_UV_CLIP(); WRITE_UV_CLIP();
  303.                 WRITE_UV_CLIP(); WRITE_UV_CLIP();
  304.             }
  305.             p_line_end += 8;
  306.             for( ; p_in < p_line_end ; )
  307.             {
  308.                 WRITE_UV_CLIP();
  309.             }
  310.             p_in += p_pic->p[U_PLANE].i_pitch
  311.                   - p_pic->p[U_PLANE].i_visible_pitch;
  312.             p_in_v += p_pic->p[V_PLANE].i_pitch
  313.                     - p_pic->p[V_PLANE].i_visible_pitch;
  314.             p_out += p_outpic->p[U_PLANE].i_pitch
  315.                    - p_outpic->p[U_PLANE].i_visible_pitch;
  316.             p_out_v += p_outpic->p[V_PLANE].i_pitch
  317.                      - p_outpic->p[V_PLANE].i_visible_pitch;
  318.         }
  319. #undef WRITE_UV_CLIP
  320.     }
  321.     else
  322.     {
  323. #define WRITE_UV() 
  324.     i_u = *p_in++ ; i_v = *p_in_v++ ; 
  325.     *p_out++ = (( ((i_u * i_cos + i_v * i_sin - i_x) >> 8) 
  326.                        * i_sat) >> 8) + 128; 
  327.     *p_out_v++ = (( ((i_v * i_cos - i_u * i_sin - i_y) >> 8) 
  328.                        * i_sat) >> 8) + 128
  329.         uint8_t i_u, i_v;
  330.         for( ; p_in < p_in_end ; )
  331.         {
  332.             p_line_end = p_in + p_pic->p[U_PLANE].i_visible_pitch - 8;
  333.             for( ; p_in < p_line_end ; )
  334.             {
  335.                 /* Do 8 pixels at a time */
  336.                 WRITE_UV(); WRITE_UV(); WRITE_UV(); WRITE_UV();
  337.                 WRITE_UV(); WRITE_UV(); WRITE_UV(); WRITE_UV();
  338.             }
  339.             p_line_end += 8;
  340.             for( ; p_in < p_line_end ; )
  341.             {
  342.                 WRITE_UV();
  343.             }
  344.             p_in += p_pic->p[U_PLANE].i_pitch
  345.                   - p_pic->p[U_PLANE].i_visible_pitch;
  346.             p_in_v += p_pic->p[V_PLANE].i_pitch
  347.                     - p_pic->p[V_PLANE].i_visible_pitch;
  348.             p_out += p_outpic->p[U_PLANE].i_pitch
  349.                    - p_outpic->p[U_PLANE].i_visible_pitch;
  350.             p_out_v += p_outpic->p[V_PLANE].i_pitch
  351.                      - p_outpic->p[V_PLANE].i_visible_pitch;
  352.         }
  353. #undef WRITE_UV
  354.     }
  355.     return CopyInfoAndRelease( p_outpic, p_pic );
  356. }
  357. /*****************************************************************************
  358.  * Run the filter on a Packed YUV picture
  359.  *****************************************************************************/
  360. static picture_t *FilterPacked( filter_t *p_filter, picture_t *p_pic )
  361. {
  362.     int pi_luma[256];
  363.     int pi_gamma[256];
  364.     picture_t *p_outpic;
  365.     uint8_t *p_in, *p_in_v, *p_in_end, *p_line_end;
  366.     uint8_t *p_out, *p_out_v;
  367.     int i_y_offset, i_u_offset, i_v_offset;
  368.     int i_lines, i_visible_lines, i_pitch, i_visible_pitch;
  369.     bool b_thres;
  370.     double  f_hue;
  371.     double  f_gamma;
  372.     int32_t i_cont, i_lum;
  373.     int i_sat, i_sin, i_cos, i_x, i_y;
  374.     int i;
  375.     filter_sys_t *p_sys = p_filter->p_sys;
  376.     if( !p_pic ) return NULL;
  377.     i_lines = p_pic->p->i_lines;
  378.     i_visible_lines = p_pic->p->i_visible_lines;
  379.     i_pitch = p_pic->p->i_pitch;
  380.     i_visible_pitch = p_pic->p->i_visible_pitch;
  381.     if( GetPackedYuvOffsets( p_pic->format.i_chroma, &i_y_offset,
  382.                              &i_u_offset, &i_v_offset ) != VLC_SUCCESS )
  383.     {
  384.         msg_Warn( p_filter, "Unsupported input chroma (%4s)",
  385.                   (char*)&(p_pic->format.i_chroma) );
  386.         picture_Release( p_pic );
  387.         return NULL;
  388.     }
  389.     p_outpic = p_filter->pf_vout_buffer_new( p_filter );
  390.     if( !p_outpic )
  391.     {
  392.         msg_Warn( p_filter, "can't get output picture" );
  393.         picture_Release( p_pic );
  394.         return NULL;
  395.     }
  396.     /* Get variables */
  397.     vlc_mutex_lock( &p_sys->lock );
  398.     i_cont = (int)( p_sys->f_contrast * 255 );
  399.     i_lum = (int)( (p_sys->f_brightness - 1.0)*255 );
  400.     f_hue = (float)( p_sys->i_hue * M_PI / 180 );
  401.     i_sat = (int)( p_sys->f_saturation * 256 );
  402.     f_gamma = 1.0 / p_sys->f_gamma;
  403.     b_thres = p_sys->b_brightness_threshold;
  404.     vlc_mutex_unlock( &p_sys->lock );
  405.     /*
  406.      * Threshold mode drops out everything about luma, contrast and gamma.
  407.      */
  408.     if( b_thres != true )
  409.     {
  410.         /* Contrast is a fast but kludged function, so I put this gap to be
  411.          * cleaner :) */
  412.         i_lum += 128 - i_cont / 2;
  413.         /* Fill the gamma lookup table */
  414.         for( i = 0 ; i < 256 ; i++ )
  415.         {
  416.           pi_gamma[ i ] = clip_uint8_vlc( pow(i / 255.0, f_gamma) * 255.0);
  417.         }
  418.         /* Fill the luma lookup table */
  419.         for( i = 0 ; i < 256 ; i++ )
  420.         {
  421.             pi_luma[ i ] = pi_gamma[clip_uint8_vlc( i_lum + i_cont * i / 256)];
  422.         }
  423.     }
  424.     else
  425.     {
  426.         /*
  427.          * We get luma as threshold value: the higher it is, the darker is
  428.          * the image. Should I reverse this?
  429.          */
  430.         for( i = 0 ; i < 256 ; i++ )
  431.         {
  432.             pi_luma[ i ] = (i < i_lum) ? 0 : 255;
  433.         }
  434.         /*
  435.          * Desaturates image to avoid that strange yellow halo...
  436.          */
  437.         i_sat = 0;
  438.     }
  439.     /*
  440.      * Do the Y plane
  441.      */
  442.     p_in = p_pic->p->p_pixels + i_y_offset;
  443.     p_in_end = p_in + p_pic->p->i_visible_lines * p_pic->p->i_pitch - 8 * 4;
  444.     p_out = p_outpic->p->p_pixels + i_y_offset;
  445.     for( ; p_in < p_in_end ; )
  446.     {
  447.         p_line_end = p_in + i_visible_pitch - 8 * 4;
  448.         for( ; p_in < p_line_end ; )
  449.         {
  450.             /* Do 8 pixels at a time */
  451.             *p_out = pi_luma[ *p_in ]; p_in += 2; p_out += 2;
  452.             *p_out = pi_luma[ *p_in ]; p_in += 2; p_out += 2;
  453.             *p_out = pi_luma[ *p_in ]; p_in += 2; p_out += 2;
  454.             *p_out = pi_luma[ *p_in ]; p_in += 2; p_out += 2;
  455.             *p_out = pi_luma[ *p_in ]; p_in += 2; p_out += 2;
  456.             *p_out = pi_luma[ *p_in ]; p_in += 2; p_out += 2;
  457.             *p_out = pi_luma[ *p_in ]; p_in += 2; p_out += 2;
  458.             *p_out = pi_luma[ *p_in ]; p_in += 2; p_out += 2;
  459.         }
  460.         p_line_end += 8 * 4;
  461.         for( ; p_in < p_line_end ; )
  462.         {
  463.             *p_out = pi_luma[ *p_in ]; p_in += 2; p_out += 2;
  464.         }
  465.         p_in += i_pitch - p_pic->p->i_visible_pitch;
  466.         p_out += i_pitch - p_outpic->p->i_visible_pitch;
  467.     }
  468.     /*
  469.      * Do the U and V planes
  470.      */
  471.     p_in = p_pic->p->p_pixels + i_u_offset;
  472.     p_in_v = p_pic->p->p_pixels + i_v_offset;
  473.     p_in_end = p_in + i_visible_lines * i_pitch - 8 * 4;
  474.     p_out = p_outpic->p->p_pixels + i_u_offset;
  475.     p_out_v = p_outpic->p->p_pixels + i_v_offset;
  476.     i_sin = sin(f_hue) * 256;
  477.     i_cos = cos(f_hue) * 256;
  478.     i_x = ( cos(f_hue) + sin(f_hue) ) * 32768;
  479.     i_y = ( cos(f_hue) - sin(f_hue) ) * 32768;
  480.     if ( i_sat > 256 )
  481.     {
  482. #define WRITE_UV_CLIP() 
  483.     i_u = *p_in; p_in += 4; i_v = *p_in_v; p_in_v += 4; 
  484.     *p_out = clip_uint8_vlc( (( ((i_u * i_cos + i_v * i_sin - i_x) >> 8) 
  485.                            * i_sat) >> 8) + 128); 
  486.     p_out += 4; 
  487.     *p_out_v = clip_uint8_vlc( (( ((i_v * i_cos - i_u * i_sin - i_y) >> 8) 
  488.                            * i_sat) >> 8) + 128); 
  489.     p_out_v += 4
  490.         uint8_t i_u, i_v;
  491.         for( ; p_in < p_in_end ; )
  492.         {
  493.             p_line_end = p_in + i_visible_pitch - 8 * 4;
  494.             for( ; p_in < p_line_end ; )
  495.             {
  496.                 /* Do 8 pixels at a time */
  497.                 WRITE_UV_CLIP(); WRITE_UV_CLIP();
  498.                 WRITE_UV_CLIP(); WRITE_UV_CLIP();
  499.                 WRITE_UV_CLIP(); WRITE_UV_CLIP();
  500.                 WRITE_UV_CLIP(); WRITE_UV_CLIP();
  501.             }
  502.             p_line_end += 8 * 4;
  503.             for( ; p_in < p_line_end ; )
  504.             {
  505.                 WRITE_UV_CLIP();
  506.             }
  507.             p_in += i_pitch - i_visible_pitch;
  508.             p_in_v += i_pitch - i_visible_pitch;
  509.             p_out += i_pitch - i_visible_pitch;
  510.             p_out_v += i_pitch - i_visible_pitch;
  511.         }
  512. #undef WRITE_UV_CLIP
  513.     }
  514.     else
  515.     {
  516. #define WRITE_UV() 
  517.     i_u = *p_in; p_in += 4; i_v = *p_in_v; p_in_v += 4; 
  518.     *p_out = (( ((i_u * i_cos + i_v * i_sin - i_x) >> 8) 
  519.                        * i_sat) >> 8) + 128; 
  520.     p_out += 4; 
  521.     *p_out_v = (( ((i_v * i_cos - i_u * i_sin - i_y) >> 8) 
  522.                        * i_sat) >> 8) + 128; 
  523.     p_out_v += 4
  524.         uint8_t i_u, i_v;
  525.         for( ; p_in < p_in_end ; )
  526.         {
  527.             p_line_end = p_in + i_visible_pitch - 8 * 4;
  528.             for( ; p_in < p_line_end ; )
  529.             {
  530.                 /* Do 8 pixels at a time */
  531.                 WRITE_UV(); WRITE_UV(); WRITE_UV(); WRITE_UV();
  532.                 WRITE_UV(); WRITE_UV(); WRITE_UV(); WRITE_UV();
  533.             }
  534.             p_line_end += 8 * 4;
  535.             for( ; p_in < p_line_end ; )
  536.             {
  537.                 WRITE_UV();
  538.             }
  539.             p_in += i_pitch - i_visible_pitch;
  540.             p_in_v += i_pitch - i_visible_pitch;
  541.             p_out += i_pitch - i_visible_pitch;
  542.             p_out_v += i_pitch - i_visible_pitch;
  543.         }
  544. #undef WRITE_UV
  545.     }
  546.     return CopyInfoAndRelease( p_outpic, p_pic );
  547. }
  548. static int AdjustCallback( vlc_object_t *p_this, char const *psz_var,
  549.                            vlc_value_t oldval, vlc_value_t newval,
  550.                            void *p_data )
  551. {
  552.     VLC_UNUSED(p_this); VLC_UNUSED(oldval);
  553.     filter_sys_t *p_sys = (filter_sys_t *)p_data;
  554.     vlc_mutex_lock( &p_sys->lock );
  555.     if( !strcmp( psz_var, "contrast" ) )
  556.         p_sys->f_contrast = newval.f_float;
  557.     else if( !strcmp( psz_var, "brightness" ) )
  558.         p_sys->f_brightness = newval.f_float;
  559.     else if( !strcmp( psz_var, "hue" ) )
  560.         p_sys->i_hue = newval.i_int;
  561.     else if( !strcmp( psz_var, "saturation" ) )
  562.         p_sys->f_saturation = newval.f_float;
  563.     else if( !strcmp( psz_var, "gamma" ) )
  564.         p_sys->f_gamma = newval.f_float;
  565.     else if( !strcmp( psz_var, "brightness-threshold" ) )
  566.         p_sys->b_brightness_threshold = newval.b_bool;
  567.     vlc_mutex_unlock( &p_sys->lock );
  568.     return VLC_SUCCESS;
  569. }