video_filter_colorthres: fix a typo.
[vlc/solaris.git] / modules / video_filter / colorthres.c
blobeefc09063f8624bb015e02dc00460fece0623360
1 /*****************************************************************************
2 * colorthres.c: Threshold color based on similarity to reference color
3 *****************************************************************************
4 * Copyright (C) 2000-2009 the VideoLAN team
5 * $Id$
7 * Authors: Sigmund Augdal <dnumgis@videolan.org>
8 * Antoine Cellerier <dionoea at videolan dot org>
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.
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.
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 *****************************************************************************/
25 /*****************************************************************************
26 * Preamble
27 *****************************************************************************/
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
33 #include <math.h>
35 #include <vlc_common.h>
36 #include <vlc_plugin.h>
37 #include <vlc_sout.h>
39 #include <vlc_filter.h>
40 #include "filter_picture.h"
42 /*****************************************************************************
43 * Local prototypes
44 *****************************************************************************/
45 static int Create ( vlc_object_t * );
46 static void Destroy ( vlc_object_t * );
48 static picture_t *Filter( filter_t *, picture_t * );
49 static picture_t *FilterPacked( filter_t *, picture_t * );
51 /*****************************************************************************
52 * Module descriptor
53 *****************************************************************************/
54 #define COLOR_TEXT N_("Color")
55 #define COLOR_LONGTEXT N_("Colors similar to this will be kept, others will be "\
56 "grayscaled. This must be an hexadecimal (like HTML colors). The first two "\
57 "chars are for red, then green, then blue. #000000 = black, #FF0000 = red,"\
58 " #00FF00 = green, #FFFF00 = yellow (red + green), #FFFFFF = white" )
59 #define COLOR_HELP N_("Select one color in the video")
60 static const int pi_color_values[] = {
61 0x00FF0000, 0x00FF00FF, 0x00FFFF00, 0x0000FF00, 0x000000FF, 0x0000FFFF };
63 static const char *const ppsz_color_descriptions[] = {
64 N_("Red"), N_("Fuchsia"), N_("Yellow"), N_("Lime"), N_("Blue"), N_("Aqua") };
66 #define CFG_PREFIX "colorthres-"
68 vlc_module_begin ()
69 set_description( N_("Color threshold filter") )
70 set_shortname( N_("Color threshold" ))
71 set_help(COLOR_HELP)
72 set_category( CAT_VIDEO )
73 set_subcategory( SUBCAT_VIDEO_VFILTER )
74 set_capability( "video filter2", 0 )
75 add_integer( CFG_PREFIX "color", 0x00FF0000, NULL, COLOR_TEXT,
76 COLOR_LONGTEXT, false )
77 change_integer_list( pi_color_values, ppsz_color_descriptions, NULL )
78 add_integer( CFG_PREFIX "saturationthres", 20, NULL,
79 N_("Saturaton threshold"), "", false )
80 add_integer( CFG_PREFIX "similaritythres", 15, NULL,
81 N_("Similarity threshold"), "", false )
82 set_callbacks( Create, Destroy )
83 vlc_module_end ()
85 static const char *const ppsz_filter_options[] = {
86 "color", "saturationthres", "similaritythres", NULL
89 /*****************************************************************************
90 * callback prototypes
91 *****************************************************************************/
92 static int FilterCallback( vlc_object_t *, char const *,
93 vlc_value_t, vlc_value_t, void * );
96 /*****************************************************************************
97 * filter_sys_t: adjust filter method descriptor
98 *****************************************************************************/
99 struct filter_sys_t
101 int i_simthres;
102 int i_satthres;
103 int i_color;
104 vlc_mutex_t lock;
107 /*****************************************************************************
108 * Create: allocates adjust video thread output method
109 *****************************************************************************
110 * This function allocates and initializes a adjust vout method.
111 *****************************************************************************/
112 static int Create( vlc_object_t *p_this )
114 filter_t *p_filter = (filter_t *)p_this;
115 filter_sys_t *p_sys;
117 switch( p_filter->fmt_in.video.i_chroma )
119 CASE_PLANAR_YUV
120 p_filter->pf_video_filter = Filter;
121 break;
123 CASE_PACKED_YUV_422
124 p_filter->pf_video_filter = FilterPacked;
125 break;
127 default:
128 msg_Err( p_filter, "Unsupported input chroma (%4.4s)",
129 (char*)&(p_filter->fmt_in.video.i_chroma) );
130 return VLC_EGENERIC;
133 if( p_filter->fmt_in.video.i_chroma != p_filter->fmt_out.video.i_chroma )
135 msg_Err( p_filter, "Input and output chromas don't match" );
136 return VLC_EGENERIC;
139 /* Allocate structure */
140 p_sys = p_filter->p_sys = malloc( sizeof( filter_sys_t ) );
141 if( p_filter->p_sys == NULL )
142 return VLC_ENOMEM;
144 config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options,
145 p_filter->p_cfg );
146 p_sys->i_color = var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "color" );
147 p_sys->i_simthres = var_CreateGetIntegerCommand( p_filter,
148 CFG_PREFIX "similaritythres" );
149 p_sys->i_satthres = var_CreateGetIntegerCommand( p_filter,
150 CFG_PREFIX "saturationthres" );
152 vlc_mutex_init( &p_sys->lock );
154 var_AddCallback( p_filter, CFG_PREFIX "color", FilterCallback, NULL );
155 var_AddCallback( p_filter, CFG_PREFIX "similaritythres", FilterCallback, NULL );
156 var_AddCallback( p_filter, CFG_PREFIX "saturationthres", FilterCallback, NULL );
158 return VLC_SUCCESS;
161 /*****************************************************************************
162 * Destroy: destroy adjust video thread output method
163 *****************************************************************************
164 * Terminate an output method created by adjustCreateOutputMethod
165 *****************************************************************************/
166 static void Destroy( vlc_object_t *p_this )
168 filter_t *p_filter = (filter_t *)p_this;
170 var_DelCallback( p_filter, CFG_PREFIX "color", FilterCallback, NULL );
171 var_DelCallback( p_filter, CFG_PREFIX "similaritythres", FilterCallback, NULL );
172 var_DelCallback( p_filter, CFG_PREFIX "saturationthres", FilterCallback, NULL );
174 vlc_mutex_destroy( &p_filter->p_sys->lock );
175 free( p_filter->p_sys );
178 /*****************************************************************************
179 * Render: displays previously rendered output
180 *****************************************************************************
181 * This function send the currently rendered image to adjust modified image,
182 * waits until it is displayed and switch the two rendering buffers, preparing
183 * next frame.
184 *****************************************************************************/
185 static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
187 picture_t *p_outpic;
188 filter_sys_t *p_sys = p_filter->p_sys;
189 uint8_t *p_in_y, *p_in_u, *p_in_v, *p_in_end_u;
190 uint8_t *p_out_y, *p_out_u, *p_out_v;
192 vlc_mutex_lock( &p_sys->lock );
193 int i_simthres = p_sys->i_simthres;
194 int i_satthres = p_sys->i_satthres;
195 int i_color = p_sys->i_color;
196 vlc_mutex_unlock( &p_sys->lock );
198 if( !p_pic ) return NULL;
200 p_outpic = filter_NewPicture( p_filter );
201 if( !p_outpic )
203 picture_Release( p_pic );
204 return NULL;
207 p_in_u = p_pic->p[U_PLANE].p_pixels;
208 p_in_v = p_pic->p[V_PLANE].p_pixels;
209 p_in_y = p_pic->p[Y_PLANE].p_pixels;
210 p_in_end_u = p_in_u + p_pic->p[U_PLANE].i_visible_lines
211 * p_pic->p[U_PLANE].i_pitch - 8;
213 p_out_y = p_outpic->p[Y_PLANE].p_pixels;
214 p_out_u = p_outpic->p[U_PLANE].p_pixels;
215 p_out_v = p_outpic->p[V_PLANE].p_pixels;
217 /* Create grayscale version of input */
218 vlc_memcpy( p_out_y, p_in_y, p_pic->p[Y_PLANE].i_visible_lines
219 * p_pic->p[Y_PLANE].i_pitch - 8 );
220 vlc_memset( p_out_u, 0x80, p_pic->p[U_PLANE].i_visible_lines
221 * p_pic->p[U_PLANE].i_pitch - 8 );
222 vlc_memset( p_out_v, 0x80, p_pic->p[U_PLANE].i_visible_lines
223 * p_pic->p[U_PLANE].i_pitch - 8 );
226 * Do the U and V planes
228 int i_red = ( i_color & 0xFF0000 ) >> 16;
229 int i_green = ( i_color & 0xFF00 ) >> 8;
230 int i_blue = i_color & 0xFF;
231 int i_u = (int8_t)(( -38 * i_red - 74 * i_green +
232 112 * i_blue + 128) >> 8) + 128;
233 int i_v = (int8_t)(( 112 * i_red - 94 * i_green -
234 18 * i_blue + 128) >> 8) + 128;
235 int refu = i_u - 0x80; /*bright red*/
236 int refv = i_v - 0x80;
237 int reflength = sqrt(refu*refu+refv*refv);
239 while( p_in_u < p_in_end_u ) {
240 /* Length of color vector */
241 int inu = (*p_in_u) - 0x80;
242 int inv = (*p_in_v) - 0x80;
243 int length = sqrt(inu*inu+inv*inv);
245 int diffu = refu * length - inu *reflength;
246 int diffv = refv * length - inv *reflength;
247 long long int difflen2=diffu*diffu;
248 difflen2 +=diffv*diffv;
249 long long int thres = length*reflength;
250 thres *= thres;
251 if( length > i_satthres && (difflen2*i_simthres< thres ) ) {
252 *p_out_u = *p_in_u;
253 *p_out_v = *p_in_v;
254 // fprintf(stderr,"keeping color %d %d\n", length, difflen2);
256 p_in_u++;
257 p_in_v++;
258 p_out_u++;
259 p_out_v++;
262 return CopyInfoAndRelease( p_outpic, p_pic );
265 static picture_t *FilterPacked( filter_t *p_filter, picture_t *p_pic )
267 picture_t *p_outpic;
268 filter_sys_t *p_sys = p_filter->p_sys;
269 uint8_t *p_in_y, *p_in_u, *p_in_v, *p_in_end_u;
270 uint8_t *p_out_y, *p_out_u, *p_out_v;
272 vlc_mutex_lock( &p_sys->lock );
273 int i_simthres = p_sys->i_simthres;
274 int i_satthres = p_sys->i_satthres;
275 int i_color = p_sys->i_color;
276 vlc_mutex_unlock( &p_sys->lock );
278 if( !p_pic ) return NULL;
280 p_outpic = filter_NewPicture( p_filter );
281 if( !p_outpic )
283 picture_Release( p_pic );
284 return NULL;
287 int i_y_offset, i_u_offset, i_v_offset;
288 GetPackedYuvOffsets( p_filter->fmt_in.video.i_chroma,
289 &i_y_offset, &i_u_offset, &i_v_offset );
290 p_in_y = p_pic->p->p_pixels+i_y_offset;
291 p_in_u = p_pic->p->p_pixels+i_u_offset;
292 p_in_v = p_pic->p->p_pixels+i_v_offset;
293 p_in_end_u = p_in_u + p_pic->p->i_visible_lines
294 * p_pic->p->i_pitch - 8;
296 p_out_y = p_outpic->p->p_pixels+i_y_offset;
297 p_out_u = p_outpic->p->p_pixels+i_u_offset;
298 p_out_v = p_outpic->p->p_pixels+i_v_offset;
300 /* Create grayscale version of input */
301 vlc_memcpy( p_outpic->p->p_pixels, p_pic->p->p_pixels,
302 p_pic->p->i_visible_lines * p_pic->p->i_pitch - 8 );
305 * Do the U and V planes
307 int i_red = ( i_color & 0xFF0000 ) >> 16;
308 int i_green = ( i_color & 0xFF00 ) >> 8;
309 int i_blue = i_color & 0xFF;
310 int i_u = (int8_t)(( -38 * i_red - 74 * i_green +
311 112 * i_blue + 128) >> 8) + 128;
312 int i_v = (int8_t)(( 112 * i_red - 94 * i_green -
313 18 * i_blue + 128) >> 8) + 128;
314 int refu = i_u - 0x80; /*bright red*/
315 int refv = i_v - 0x80;
316 int reflength = sqrt(refu*refu+refv*refv);
318 while( p_in_u < p_in_end_u ) {
319 /* Length of color vector */
320 int inu = (*p_in_u) - 0x80;
321 int inv = (*p_in_v) - 0x80;
322 int length = sqrt(inu*inu+inv*inv);
324 int diffu = refu * length - inu *reflength;
325 int diffv = refv * length - inv *reflength;
326 long long int difflen2=diffu*diffu;
327 difflen2 +=diffv*diffv;
328 long long int thres = length*reflength;
329 thres *= thres;
330 if( length > i_satthres && (difflen2*i_simthres< thres ) ) {
331 *p_out_u = *p_in_u;
332 *p_out_v = *p_in_v;
333 // fprintf(stderr,"keeping color %d %d\n", length, difflen2);
335 else
337 *p_out_u = 0x80;
338 *p_out_v = 0x80;
340 p_in_u+=4;
341 p_in_v+=4;
342 p_out_u+=4;
343 p_out_v+=4;
346 return CopyInfoAndRelease( p_outpic, p_pic );
349 static int FilterCallback ( vlc_object_t *p_this, char const *psz_var,
350 vlc_value_t oldval, vlc_value_t newval, void *p_data )
352 (void)oldval; (void)p_data;
353 filter_t *p_filter = (filter_t*)p_this;
354 filter_sys_t *p_sys = p_filter->p_sys;
356 if( !strcmp( psz_var, CFG_PREFIX "color" ) )
358 vlc_mutex_lock( &p_sys->lock );
359 p_sys->i_color = newval.i_int;
360 vlc_mutex_unlock( &p_sys->lock );
362 else if( !strcmp( psz_var, CFG_PREFIX "similaritythres" ) )
364 vlc_mutex_lock( &p_sys->lock );
365 p_sys->i_simthres = newval.i_int;
366 vlc_mutex_unlock( &p_sys->lock );
368 else /* CFG_PREFIX "saturationthres" */
370 vlc_mutex_lock( &p_sys->lock );
371 p_sys->i_satthres = newval.i_int;
372 vlc_mutex_unlock( &p_sys->lock );
375 return VLC_SUCCESS;