1 /*****************************************************************************
2 * colorthres.c: Theshold color based on similarity to reference color
3 *****************************************************************************
4 * Copyright (C) 2000-2009 the VideoLAN team
7 * Authors: Sigmund Augdal <dnumgis@videolan.org>
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.
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.
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 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
35 #include <vlc_common.h>
36 #include <vlc_plugin.h>
39 #include <vlc_filter.h>
40 #include "filter_picture.h"
42 /*****************************************************************************
44 *****************************************************************************/
45 static int Create ( vlc_object_t * );
46 static void Destroy ( vlc_object_t * );
48 static picture_t *Filter( filter_t *, picture_t * );
50 /*****************************************************************************
52 *****************************************************************************/
53 #define COLOR_TEXT N_("Color")
54 #define COLOR_LONGTEXT N_("Colors similar to this will be kept, others will be "\
55 "grayscaled. This must be an hexadecimal (like HTML colors). The first two "\
56 "chars are for red, then green, then blue. #000000 = black, #FF0000 = red,"\
57 " #00FF00 = green, #FFFF00 = yellow (red + green), #FFFFFF = white" )
58 static const int pi_color_values[] = {
59 0x00FF0000, 0x00FF00FF, 0x00FFFF00, 0x0000FF00, 0x000000FF, 0x0000FFFF };
61 static const char *const ppsz_color_descriptions[] = {
62 N_("Red"), N_("Fuchsia"), N_("Yellow"), N_("Lime"), N_("Blue"), N_("Aqua") };
64 #define CFG_PREFIX "colorthres-"
67 set_description( N_("Color threshold filter") )
68 set_shortname( N_("Color threshold" ))
69 set_category( CAT_VIDEO )
70 set_subcategory( SUBCAT_VIDEO_VFILTER )
71 set_capability( "video filter2", 0 )
72 add_integer( CFG_PREFIX "color", 0x00FF0000, NULL, COLOR_TEXT,
73 COLOR_LONGTEXT, false )
74 change_integer_list( pi_color_values, ppsz_color_descriptions, NULL )
75 add_integer( CFG_PREFIX "saturationthres", 20, NULL,
76 N_("Saturaton threshold"), "", false )
77 add_integer( CFG_PREFIX "similaritythres", 15, NULL,
78 N_("Similarity threshold"), "", false )
79 set_callbacks( Create, Destroy )
82 static const char *const ppsz_filter_options[] = {
83 "color", "saturationthes", "similaritythres", NULL
86 /*****************************************************************************
88 *****************************************************************************/
89 static int FilterCallback( vlc_object_t *, char const *,
90 vlc_value_t, vlc_value_t, void * );
93 /*****************************************************************************
94 * filter_sys_t: adjust filter method descriptor
95 *****************************************************************************/
104 /*****************************************************************************
105 * Create: allocates adjust video thread output method
106 *****************************************************************************
107 * This function allocates and initializes a adjust vout method.
108 *****************************************************************************/
109 static int Create( vlc_object_t *p_this )
111 filter_t *p_filter = (filter_t *)p_this;
114 switch( p_filter->fmt_in.video.i_chroma )
120 msg_Err( p_filter, "Unsupported input chroma (%4s)",
121 (char*)&(p_filter->fmt_in.video.i_chroma) );
125 if( p_filter->fmt_in.video.i_chroma != p_filter->fmt_out.video.i_chroma )
127 msg_Err( p_filter, "Input and output chromas don't match" );
131 /* Allocate structure */
132 p_sys = p_filter->p_sys = malloc( sizeof( filter_sys_t ) );
133 if( p_filter->p_sys == NULL )
136 config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options,
138 p_sys->i_color = var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "color" );
139 p_sys->i_simthres = var_CreateGetIntegerCommand( p_filter,
140 CFG_PREFIX "similaritythres" );
141 p_sys->i_satthres = var_CreateGetIntegerCommand( p_filter,
142 CFG_PREFIX "saturationthres" );
144 vlc_mutex_init( &p_sys->lock );
146 var_AddCallback( p_filter, CFG_PREFIX "color", FilterCallback, NULL );
147 var_AddCallback( p_filter, CFG_PREFIX "similaritythres", FilterCallback, NULL );
148 var_AddCallback( p_filter, CFG_PREFIX "saturationthres", FilterCallback, NULL );
150 p_filter->pf_video_filter = Filter;
155 /*****************************************************************************
156 * Destroy: destroy adjust video thread output method
157 *****************************************************************************
158 * Terminate an output method created by adjustCreateOutputMethod
159 *****************************************************************************/
160 static void Destroy( vlc_object_t *p_this )
162 filter_t *p_filter = (filter_t *)p_this;
164 var_DelCallback( p_filter, CFG_PREFIX "color", FilterCallback, NULL );
165 var_DelCallback( p_filter, CFG_PREFIX "similaritythres", FilterCallback, NULL );
166 var_DelCallback( p_filter, CFG_PREFIX "saturationthres", FilterCallback, NULL );
168 vlc_mutex_destroy( &p_filter->p_sys->lock );
169 free( p_filter->p_sys );
172 /*****************************************************************************
173 * Render: displays previously rendered output
174 *****************************************************************************
175 * This function send the currently rendered image to adjust modified image,
176 * waits until it is displayed and switch the two rendering buffers, preparing
178 *****************************************************************************/
179 static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
182 filter_sys_t *p_sys = p_filter->p_sys;
183 uint8_t *p_in_y, *p_in_u, *p_in_v, *p_in_end_u;
184 uint8_t *p_out_y, *p_out_u, *p_out_v;
186 vlc_mutex_lock( &p_sys->lock );
187 int i_simthres = p_sys->i_simthres;
188 int i_satthres = p_sys->i_satthres;
189 int i_color = p_sys->i_color;
190 vlc_mutex_unlock( &p_sys->lock );
192 if( !p_pic ) return NULL;
194 p_outpic = filter_NewPicture( p_filter );
197 picture_Release( p_pic );
201 p_in_u = p_pic->p[U_PLANE].p_pixels;
202 p_in_v = p_pic->p[V_PLANE].p_pixels;
203 p_in_y = p_pic->p[Y_PLANE].p_pixels;
204 p_in_end_u = p_in_u + p_pic->p[U_PLANE].i_visible_lines
205 * p_pic->p[U_PLANE].i_pitch - 8;
207 p_out_y = p_outpic->p[Y_PLANE].p_pixels;
208 p_out_u = p_outpic->p[U_PLANE].p_pixels;
209 p_out_v = p_outpic->p[V_PLANE].p_pixels;
211 /* Create grayscale version of input */
212 vlc_memcpy( p_out_y, p_in_y, p_pic->p[Y_PLANE].i_visible_lines
213 * p_pic->p[Y_PLANE].i_pitch - 8 );
214 vlc_memset( p_out_u, 0x80, p_pic->p[U_PLANE].i_visible_lines
215 * p_pic->p[U_PLANE].i_pitch - 8 );
216 vlc_memset( p_out_v, 0x80, p_pic->p[U_PLANE].i_visible_lines
217 * p_pic->p[U_PLANE].i_pitch - 8 );
220 * Do the U and V planes
222 int i_red = ( i_color & 0xFF0000 ) >> 16;
223 int i_green = ( i_color & 0xFF00 ) >> 8;
224 int i_blue = i_color & 0xFF;
225 int i_u = (int8_t)(( -38 * i_red - 74 * i_green +
226 112 * i_blue + 128) >> 8) + 128;
227 int i_v = (int8_t)(( 112 * i_red - 94 * i_green -
228 18 * i_blue + 128) >> 8) + 128;
229 int refu = i_u - 0x80; /*bright red*/
230 int refv = i_v - 0x80;
231 int reflength = sqrt(refu*refu+refv*refv);
233 while( p_in_u < p_in_end_u ) {
234 /* Length of color vector */
235 int inu = (*p_in_u) - 0x80;
236 int inv = (*p_in_v) - 0x80;
237 int length = sqrt(inu*inu+inv*inv);
239 int diffu = refu * length - inu *reflength;
240 int diffv = refv * length - inv *reflength;
241 long long int difflen2=diffu*diffu;
242 difflen2 +=diffv*diffv;
243 long long int thres = length*reflength;
245 if( length > i_satthres && (difflen2*i_simthres< thres ) ) {
248 // fprintf(stderr,"keeping color %d %d\n", length, difflen2);
256 return CopyInfoAndRelease( p_outpic, p_pic );
259 static int FilterCallback ( vlc_object_t *p_this, char const *psz_var,
260 vlc_value_t oldval, vlc_value_t newval, void *p_data )
262 (void)oldval; (void)p_data;
263 filter_t *p_filter = (filter_t*)p_this;
264 filter_sys_t *p_sys = p_filter->p_sys;
266 if( !strcmp( psz_var, CFG_PREFIX "color" ) )
268 vlc_mutex_lock( &p_sys->lock );
269 p_sys->i_color = newval.i_int;
270 vlc_mutex_unlock( &p_sys->lock );
272 else if( !strcmp( psz_var, CFG_PREFIX "similaritythres" ) )
274 vlc_mutex_lock( &p_sys->lock );
275 p_sys->i_simthres = newval.i_int;
276 vlc_mutex_unlock( &p_sys->lock );
278 else /* CFG_PREFIX "saturationthres" */
280 vlc_mutex_lock( &p_sys->lock );
281 p_sys->i_satthres = newval.i_int;
282 vlc_mutex_unlock( &p_sys->lock );