1 /*****************************************************************************
2 * colorthres.c: Theshold color based on similarity to reference color
3 *****************************************************************************
4 * Copyright (C) 2000-2006 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 *****************************************************************************/
34 #include "vlc_filter.h"
36 /*****************************************************************************
38 *****************************************************************************/
39 static int Create ( vlc_object_t * );
40 static void Destroy ( vlc_object_t * );
42 static picture_t *Filter( filter_t *, picture_t * );
44 /*****************************************************************************
46 *****************************************************************************/
47 #define COLOR_TEXT N_("Color")
48 #define COLOR_LONGTEXT N_("Colors similar to this will be kept, others will be "\
49 "grayscaled. This must be an hexadecimal (like HTML colors). The first two "\
50 "chars are for red, then green, then blue. #000000 = black, #FF0000 = red,"\
51 " #00FF00 = green, #FFFF00 = yellow (red + green), #FFFFFF = white" )
52 static int pi_color_values[] = {
53 0x00FF0000, 0x00FF00FF, 0x00FFFF00, 0x0000FF00, 0x000000FF, 0x0000FFFF };
55 static const char *ppsz_color_descriptions[] = {
56 N_("Red"), N_("Fuchsia"), N_("Yellow"), N_("Lime"), N_("Blue"), N_("Aqua") };
58 #define CFG_PREFIX "colorthres-"
61 set_description( _("Color threshold filter") );
62 set_shortname( _("Color threshold" ));
63 set_category( CAT_VIDEO );
64 set_subcategory( SUBCAT_VIDEO_VFILTER );
65 set_capability( "video filter2", 0 );
66 add_integer( CFG_PREFIX "color", 0x00FF0000, NULL, COLOR_TEXT,
67 COLOR_LONGTEXT, VLC_FALSE );
68 change_integer_list( pi_color_values, ppsz_color_descriptions, 0 );
69 add_integer( CFG_PREFIX "saturationthres", 20, NULL,
70 _("Saturaton threshold"), "", VLC_FALSE );
71 add_integer( CFG_PREFIX "similaritythres", 15, NULL,
72 _("Similarity threshold"), "", VLC_FALSE );
73 set_callbacks( Create, Destroy );
76 static const char *ppsz_filter_options[] = {
77 "color", "saturationthes", "similaritythres", NULL
80 /*****************************************************************************
81 * filter_sys_t: adjust filter method descriptor
82 *****************************************************************************/
87 /*****************************************************************************
88 * Create: allocates adjust video thread output method
89 *****************************************************************************
90 * This function allocates and initializes a adjust vout method.
91 *****************************************************************************/
92 static int Create( vlc_object_t *p_this )
94 filter_t *p_filter = (filter_t *)p_this;
96 /* XXX: we might need to add/remove some FOURCCs ... */
97 if( p_filter->fmt_in.video.i_chroma != VLC_FOURCC('I','4','2','0') )
99 msg_Err( p_filter, "Unsupported input chroma (%4s)",
100 (char*)&(p_filter->fmt_in.video.i_chroma) );
104 if( p_filter->fmt_in.video.i_chroma != p_filter->fmt_out.video.i_chroma )
106 msg_Err( p_filter, "Input and output chromas don't match" );
110 config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options,
112 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "color" );
113 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "similaritythres" );
114 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "saturationthres" );
116 /* Allocate structure */
117 p_filter->p_sys = malloc( sizeof( filter_sys_t ) );
118 if( p_filter->p_sys == NULL )
120 msg_Err( p_filter, "out of memory" );
124 p_filter->pf_video_filter = Filter;
129 /*****************************************************************************
130 * Destroy: destroy adjust video thread output method
131 *****************************************************************************
132 * Terminate an output method created by adjustCreateOutputMethod
133 *****************************************************************************/
134 static void Destroy( vlc_object_t *p_this )
136 filter_t *p_filter = (filter_t *)p_this;
137 free( p_filter->p_sys );
140 /*****************************************************************************
141 * Render: displays previously rendered output
142 *****************************************************************************
143 * This function send the currently rendered image to adjust modified image,
144 * waits until it is displayed and switch the two rendering buffers, preparing
146 *****************************************************************************/
147 static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
150 uint8_t *p_in_y, *p_in_u, *p_in_v, *p_in_end_u;
151 uint8_t *p_out_y, *p_out_u, *p_out_v;
152 int i_simthres = var_GetInteger( p_filter, "colorthres-similaritythres" );
153 int i_satthres = var_GetInteger( p_filter, "colorthres-saturationthres" );
154 int i_color = var_GetInteger( p_filter, "colorthres-color" );
156 if( !p_pic ) return NULL;
158 p_outpic = p_filter->pf_vout_buffer_new( p_filter );
161 msg_Warn( p_filter, "can't get output picture" );
162 if( p_pic->pf_release )
163 p_pic->pf_release( p_pic );
167 p_in_u = p_pic->p[U_PLANE].p_pixels;
168 p_in_v = p_pic->p[V_PLANE].p_pixels;
169 p_in_y = p_pic->p[Y_PLANE].p_pixels;
170 p_in_end_u = p_in_u + p_pic->p[U_PLANE].i_visible_lines
171 * p_pic->p[U_PLANE].i_pitch - 8;
173 p_out_y = p_outpic->p[Y_PLANE].p_pixels;
174 p_out_u = p_outpic->p[U_PLANE].p_pixels;
175 p_out_v = p_outpic->p[V_PLANE].p_pixels;
177 /* Create grayscale version of input */
179 pf_memcpy( p_out_y, p_in_y, p_pic->p[Y_PLANE].i_visible_lines
180 * p_pic->p[Y_PLANE].i_pitch - 8 );
182 pf_memset( p_out_u, 0x80, p_pic->p[U_PLANE].i_visible_lines
183 * p_pic->p[U_PLANE].i_pitch - 8 );
185 pf_memset( p_out_v, 0x80, p_pic->p[U_PLANE].i_visible_lines
186 * p_pic->p[U_PLANE].i_pitch - 8 );
189 * Do the U and V planes
191 int i_red = ( i_color & 0xFF0000 ) >> 16;
192 int i_green = ( i_color & 0xFF00 ) >> 8;
193 int i_blue = i_color & 0xFF;
194 int i_u = (int8_t)(( -38 * i_red - 74 * i_green +
195 112 * i_blue + 128) >> 8) + 128;
196 int i_v = (int8_t)(( 112 * i_red - 94 * i_green -
197 18 * i_blue + 128) >> 8) + 128;
198 int refu = i_u - 0x80; /*bright red*/
199 int refv = i_v - 0x80;
200 int reflength = sqrt(refu*refu+refv*refv);
202 while( p_in_u < p_in_end_u ) {
203 /* Length of color vector */
204 int inu = (*p_in_u) - 0x80;
205 int inv = (*p_in_v) - 0x80;
206 int length = sqrt(inu*inu+inv*inv);
208 int diffu = refu * length - inu *reflength;
209 int diffv = refv * length - inv *reflength;
210 long long int difflen2=diffu*diffu;
211 difflen2 +=diffv*diffv;
212 long long int thres = length*reflength;
214 if( length > i_satthres && (difflen2*i_simthres< thres ) ) {
217 // fprintf(stderr,"keeping color %d %d\n", length, difflen2);
225 p_outpic->date = p_pic->date;
226 p_outpic->b_force = p_pic->b_force;
227 p_outpic->i_nb_fields = p_pic->i_nb_fields;
228 p_outpic->b_progressive = p_pic->b_progressive;
229 p_outpic->b_top_field_first = p_pic->b_top_field_first;
231 if( p_pic->pf_release )
232 p_pic->pf_release( p_pic );