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 *****************************************************************************/
35 #include <vlc_common.h>
36 #include <vlc_plugin.h>
40 #include "vlc_filter.h"
41 #include "filter_picture.h"
43 /*****************************************************************************
45 *****************************************************************************/
46 static int Create ( vlc_object_t * );
47 static void Destroy ( vlc_object_t * );
49 static picture_t *Filter( filter_t *, picture_t * );
51 /*****************************************************************************
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 static const int pi_color_values[] = {
60 0x00FF0000, 0x00FF00FF, 0x00FFFF00, 0x0000FF00, 0x000000FF, 0x0000FFFF };
62 static const char *const ppsz_color_descriptions[] = {
63 N_("Red"), N_("Fuchsia"), N_("Yellow"), N_("Lime"), N_("Blue"), N_("Aqua") };
65 #define CFG_PREFIX "colorthres-"
68 set_description( N_("Color threshold filter") )
69 set_shortname( N_("Color threshold" ))
70 set_category( CAT_VIDEO )
71 set_subcategory( SUBCAT_VIDEO_VFILTER )
72 set_capability( "video filter2", 0 )
73 add_integer( CFG_PREFIX "color", 0x00FF0000, NULL, COLOR_TEXT,
74 COLOR_LONGTEXT, false )
75 change_integer_list( pi_color_values, ppsz_color_descriptions, NULL );
76 add_integer( CFG_PREFIX "saturationthres", 20, NULL,
77 _("Saturaton threshold"), "", false );
78 add_integer( CFG_PREFIX "similaritythres", 15, NULL,
79 _("Similarity threshold"), "", false );
80 set_callbacks( Create, Destroy )
83 static const char *const ppsz_filter_options[] = {
84 "color", "saturationthes", "similaritythres", NULL
87 /*****************************************************************************
88 * filter_sys_t: adjust filter method descriptor
89 *****************************************************************************/
94 /*****************************************************************************
95 * Create: allocates adjust video thread output method
96 *****************************************************************************
97 * This function allocates and initializes a adjust vout method.
98 *****************************************************************************/
99 static int Create( vlc_object_t *p_this )
101 filter_t *p_filter = (filter_t *)p_this;
103 switch( p_filter->fmt_in.video.i_chroma )
109 msg_Err( p_filter, "Unsupported input chroma (%4s)",
110 (char*)&(p_filter->fmt_in.video.i_chroma) );
114 if( p_filter->fmt_in.video.i_chroma != p_filter->fmt_out.video.i_chroma )
116 msg_Err( p_filter, "Input and output chromas don't match" );
120 config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options,
122 var_Create( p_filter, CFG_PREFIX "color", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
123 var_Create( p_filter, CFG_PREFIX "similaritythres", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
124 var_Create( p_filter, CFG_PREFIX "saturationthes", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
126 /* Allocate structure */
127 p_filter->p_sys = malloc( sizeof( filter_sys_t ) );
128 if( p_filter->p_sys == NULL )
131 p_filter->pf_video_filter = Filter;
136 /*****************************************************************************
137 * Destroy: destroy adjust video thread output method
138 *****************************************************************************
139 * Terminate an output method created by adjustCreateOutputMethod
140 *****************************************************************************/
141 static void Destroy( vlc_object_t *p_this )
143 filter_t *p_filter = (filter_t *)p_this;
144 free( p_filter->p_sys );
147 /*****************************************************************************
148 * Render: displays previously rendered output
149 *****************************************************************************
150 * This function send the currently rendered image to adjust modified image,
151 * waits until it is displayed and switch the two rendering buffers, preparing
153 *****************************************************************************/
154 static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
157 uint8_t *p_in_y, *p_in_u, *p_in_v, *p_in_end_u;
158 uint8_t *p_out_y, *p_out_u, *p_out_v;
159 int i_simthres = var_GetInteger( p_filter, "colorthres-similaritythres" );
160 int i_satthres = var_GetInteger( p_filter, "colorthres-saturationthres" );
161 int i_color = var_GetInteger( p_filter, "colorthres-color" );
163 if( !p_pic ) return NULL;
165 p_outpic = filter_NewPicture( p_filter );
168 picture_Release( p_pic );
172 p_in_u = p_pic->p[U_PLANE].p_pixels;
173 p_in_v = p_pic->p[V_PLANE].p_pixels;
174 p_in_y = p_pic->p[Y_PLANE].p_pixels;
175 p_in_end_u = p_in_u + p_pic->p[U_PLANE].i_visible_lines
176 * p_pic->p[U_PLANE].i_pitch - 8;
178 p_out_y = p_outpic->p[Y_PLANE].p_pixels;
179 p_out_u = p_outpic->p[U_PLANE].p_pixels;
180 p_out_v = p_outpic->p[V_PLANE].p_pixels;
182 /* Create grayscale version of input */
183 vlc_memcpy( p_out_y, p_in_y, p_pic->p[Y_PLANE].i_visible_lines
184 * p_pic->p[Y_PLANE].i_pitch - 8 );
185 vlc_memset( p_out_u, 0x80, p_pic->p[U_PLANE].i_visible_lines
186 * p_pic->p[U_PLANE].i_pitch - 8 );
187 vlc_memset( p_out_v, 0x80, p_pic->p[U_PLANE].i_visible_lines
188 * p_pic->p[U_PLANE].i_pitch - 8 );
191 * Do the U and V planes
193 int i_red = ( i_color & 0xFF0000 ) >> 16;
194 int i_green = ( i_color & 0xFF00 ) >> 8;
195 int i_blue = i_color & 0xFF;
196 int i_u = (int8_t)(( -38 * i_red - 74 * i_green +
197 112 * i_blue + 128) >> 8) + 128;
198 int i_v = (int8_t)(( 112 * i_red - 94 * i_green -
199 18 * i_blue + 128) >> 8) + 128;
200 int refu = i_u - 0x80; /*bright red*/
201 int refv = i_v - 0x80;
202 int reflength = sqrt(refu*refu+refv*refv);
204 while( p_in_u < p_in_end_u ) {
205 /* Length of color vector */
206 int inu = (*p_in_u) - 0x80;
207 int inv = (*p_in_v) - 0x80;
208 int length = sqrt(inu*inu+inv*inv);
210 int diffu = refu * length - inu *reflength;
211 int diffv = refv * length - inv *reflength;
212 long long int difflen2=diffu*diffu;
213 difflen2 +=diffv*diffv;
214 long long int thres = length*reflength;
216 if( length > i_satthres && (difflen2*i_simthres< thres ) ) {
219 // fprintf(stderr,"keeping color %d %d\n", length, difflen2);
227 return CopyInfoAndRelease( p_outpic, p_pic );