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_plugin.h>
39 #include "vlc_filter.h"
41 /*****************************************************************************
43 *****************************************************************************/
44 static int Create ( vlc_object_t * );
45 static void Destroy ( vlc_object_t * );
47 static picture_t *Filter( filter_t *, picture_t * );
49 /*****************************************************************************
51 *****************************************************************************/
52 #define COLOR_TEXT N_("Color")
53 #define COLOR_LONGTEXT N_("Colors similar to this will be kept, others will be "\
54 "grayscaled. This must be an hexadecimal (like HTML colors). The first two "\
55 "chars are for red, then green, then blue. #000000 = black, #FF0000 = red,"\
56 " #00FF00 = green, #FFFF00 = yellow (red + green), #FFFFFF = white" )
57 static int pi_color_values[] = {
58 0x00FF0000, 0x00FF00FF, 0x00FFFF00, 0x0000FF00, 0x000000FF, 0x0000FFFF };
60 static const char *ppsz_color_descriptions[] = {
61 N_("Red"), N_("Fuchsia"), N_("Yellow"), N_("Lime"), N_("Blue"), N_("Aqua") };
63 #define CFG_PREFIX "colorthres-"
66 set_description( N_("Color threshold filter") );
67 set_shortname( N_("Color threshold" ));
68 set_category( CAT_VIDEO );
69 set_subcategory( SUBCAT_VIDEO_VFILTER );
70 set_capability( "video filter2", 0 );
71 add_integer( CFG_PREFIX "color", 0x00FF0000, NULL, COLOR_TEXT,
72 COLOR_LONGTEXT, false );
73 change_integer_list( pi_color_values, ppsz_color_descriptions, 0 );
74 add_integer( CFG_PREFIX "saturationthres", 20, NULL,
75 _("Saturaton threshold"), "", false );
76 add_integer( CFG_PREFIX "similaritythres", 15, NULL,
77 _("Similarity threshold"), "", false );
78 set_callbacks( Create, Destroy );
81 static const char *ppsz_filter_options[] = {
82 "color", "saturationthes", "similaritythres", NULL
85 /*****************************************************************************
86 * filter_sys_t: adjust filter method descriptor
87 *****************************************************************************/
92 /*****************************************************************************
93 * Create: allocates adjust video thread output method
94 *****************************************************************************
95 * This function allocates and initializes a adjust vout method.
96 *****************************************************************************/
97 static int Create( vlc_object_t *p_this )
99 filter_t *p_filter = (filter_t *)p_this;
101 /* XXX: we might need to add/remove some FOURCCs ... */
102 if( p_filter->fmt_in.video.i_chroma != VLC_FOURCC('I','4','2','0')
103 && p_filter->fmt_in.video.i_chroma != VLC_FOURCC('I','Y','U','V')
104 && p_filter->fmt_in.video.i_chroma != VLC_FOURCC('J','4','2','0')
105 && p_filter->fmt_in.video.i_chroma != VLC_FOURCC('Y','V','1','2')
107 && p_filter->fmt_in.video.i_chroma != VLC_FOURCC('I','4','2','2')
108 && p_filter->fmt_in.video.i_chroma != VLC_FOURCC('J','4','2','2') )
110 msg_Err( p_filter, "Unsupported input chroma (%4s)",
111 (char*)&(p_filter->fmt_in.video.i_chroma) );
115 if( p_filter->fmt_in.video.i_chroma != p_filter->fmt_out.video.i_chroma )
117 msg_Err( p_filter, "Input and output chromas don't match" );
121 config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options,
123 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "color" );
124 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "similaritythres" );
125 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "saturationthres" );
127 /* Allocate structure */
128 p_filter->p_sys = malloc( sizeof( filter_sys_t ) );
129 if( p_filter->p_sys == NULL )
131 msg_Err( p_filter, "out of memory" );
135 p_filter->pf_video_filter = Filter;
140 /*****************************************************************************
141 * Destroy: destroy adjust video thread output method
142 *****************************************************************************
143 * Terminate an output method created by adjustCreateOutputMethod
144 *****************************************************************************/
145 static void Destroy( vlc_object_t *p_this )
147 filter_t *p_filter = (filter_t *)p_this;
148 free( p_filter->p_sys );
151 /*****************************************************************************
152 * Render: displays previously rendered output
153 *****************************************************************************
154 * This function send the currently rendered image to adjust modified image,
155 * waits until it is displayed and switch the two rendering buffers, preparing
157 *****************************************************************************/
158 static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
161 uint8_t *p_in_y, *p_in_u, *p_in_v, *p_in_end_u;
162 uint8_t *p_out_y, *p_out_u, *p_out_v;
163 int i_simthres = var_GetInteger( p_filter, "colorthres-similaritythres" );
164 int i_satthres = var_GetInteger( p_filter, "colorthres-saturationthres" );
165 int i_color = var_GetInteger( p_filter, "colorthres-color" );
167 if( !p_pic ) return NULL;
169 p_outpic = p_filter->pf_vout_buffer_new( p_filter );
172 msg_Warn( p_filter, "can't get output picture" );
173 if( p_pic->pf_release )
174 p_pic->pf_release( p_pic );
178 p_in_u = p_pic->p[U_PLANE].p_pixels;
179 p_in_v = p_pic->p[V_PLANE].p_pixels;
180 p_in_y = p_pic->p[Y_PLANE].p_pixels;
181 p_in_end_u = p_in_u + p_pic->p[U_PLANE].i_visible_lines
182 * p_pic->p[U_PLANE].i_pitch - 8;
184 p_out_y = p_outpic->p[Y_PLANE].p_pixels;
185 p_out_u = p_outpic->p[U_PLANE].p_pixels;
186 p_out_v = p_outpic->p[V_PLANE].p_pixels;
188 /* Create grayscale version of input */
189 vlc_memcpy( p_out_y, p_in_y, p_pic->p[Y_PLANE].i_visible_lines
190 * p_pic->p[Y_PLANE].i_pitch - 8 );
191 vlc_memset( p_out_u, 0x80, p_pic->p[U_PLANE].i_visible_lines
192 * p_pic->p[U_PLANE].i_pitch - 8 );
193 vlc_memset( p_out_v, 0x80, p_pic->p[U_PLANE].i_visible_lines
194 * p_pic->p[U_PLANE].i_pitch - 8 );
197 * Do the U and V planes
199 int i_red = ( i_color & 0xFF0000 ) >> 16;
200 int i_green = ( i_color & 0xFF00 ) >> 8;
201 int i_blue = i_color & 0xFF;
202 int i_u = (int8_t)(( -38 * i_red - 74 * i_green +
203 112 * i_blue + 128) >> 8) + 128;
204 int i_v = (int8_t)(( 112 * i_red - 94 * i_green -
205 18 * i_blue + 128) >> 8) + 128;
206 int refu = i_u - 0x80; /*bright red*/
207 int refv = i_v - 0x80;
208 int reflength = sqrt(refu*refu+refv*refv);
210 while( p_in_u < p_in_end_u ) {
211 /* Length of color vector */
212 int inu = (*p_in_u) - 0x80;
213 int inv = (*p_in_v) - 0x80;
214 int length = sqrt(inu*inu+inv*inv);
216 int diffu = refu * length - inu *reflength;
217 int diffv = refv * length - inv *reflength;
218 long long int difflen2=diffu*diffu;
219 difflen2 +=diffv*diffv;
220 long long int thres = length*reflength;
222 if( length > i_satthres && (difflen2*i_simthres< thres ) ) {
225 // fprintf(stderr,"keeping color %d %d\n", length, difflen2);
233 p_outpic->date = p_pic->date;
234 p_outpic->b_force = p_pic->b_force;
235 p_outpic->i_nb_fields = p_pic->i_nb_fields;
236 p_outpic->b_progressive = p_pic->b_progressive;
237 p_outpic->b_top_field_first = p_pic->b_top_field_first;
239 if( p_pic->pf_release )
240 p_pic->pf_release( p_pic );