]> git.sesse.net Git - vlc/blob - modules/video_filter/colorthres.c
i18n fixes
[vlc] / modules / video_filter / colorthres.c
1 /*****************************************************************************
2  * colorthres.c: Theshold color based on similarity to reference color
3  *****************************************************************************
4  * Copyright (C) 2000-2006 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Sigmund Augdal <dnumgis@videolan.org>
8  *
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.
13  *
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.
18  *
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  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <errno.h>
28 #include <stdlib.h>                                      /* malloc(), free() */
29 #include <string.h>
30 #include <math.h>
31
32 #include <vlc/vlc.h>
33 #include <vlc_sout.h>
34 #include <vlc_vout.h>
35
36 #include "vlc_filter.h"
37
38 /*****************************************************************************
39  * Local prototypes
40  *****************************************************************************/
41 static int  Create    ( vlc_object_t * );
42 static void Destroy   ( vlc_object_t * );
43
44 static picture_t *Filter( filter_t *, picture_t * );
45
46 /*****************************************************************************
47  * Module descriptor
48  *****************************************************************************/
49 #define COLOR_TEXT N_("Color")
50 #define COLOR_LONGTEXT N_("Colors similar to this will be kept, others will be "\
51     "grayscaled. This must be an hexadecimal (like HTML colors). The first two "\
52     "chars are for red, then green, then blue. #000000 = black, #FF0000 = red,"\
53     " #00FF00 = green, #FFFF00 = yellow (red + green), #FFFFFF = white" )
54 static int pi_color_values[] = {
55   0x00FF0000, 0x00FF00FF, 0x00FFFF00, 0x0000FF00, 0x000000FF, 0x0000FFFF };
56
57 static const char *ppsz_color_descriptions[] = {
58   N_("Red"), N_("Fuchsia"), N_("Yellow"), N_("Lime"), N_("Blue"), N_("Aqua") };
59
60 #define CFG_PREFIX "colorthres-"
61
62 vlc_module_begin();
63     set_description( _("Color threshold filter") );
64     set_shortname( _("Color threshold" ));
65     set_category( CAT_VIDEO );
66     set_subcategory( SUBCAT_VIDEO_VFILTER );
67     set_capability( "video filter2", 0 );
68     add_integer( CFG_PREFIX "color", 0x00FF0000, NULL, COLOR_TEXT,
69                  COLOR_LONGTEXT, VLC_FALSE );
70         change_integer_list( pi_color_values, ppsz_color_descriptions, 0 );
71     add_integer( CFG_PREFIX "saturationthres", 20, NULL,
72                  _("Saturaton threshold"), "", VLC_FALSE );
73     add_integer( CFG_PREFIX "similaritythres", 15, NULL, 
74                  _("Similarity threshold"), "", VLC_FALSE );
75     set_callbacks( Create, Destroy );
76 vlc_module_end();
77
78 static const char *ppsz_filter_options[] = {
79     "color", "saturationthes", "similaritythres", NULL
80 };
81
82 /*****************************************************************************
83  * filter_sys_t: adjust filter method descriptor
84  *****************************************************************************/
85 struct filter_sys_t
86 {
87 };
88
89 /*****************************************************************************
90  * Create: allocates adjust video thread output method
91  *****************************************************************************
92  * This function allocates and initializes a adjust vout method.
93  *****************************************************************************/
94 static int Create( vlc_object_t *p_this )
95 {
96     filter_t *p_filter = (filter_t *)p_this;
97
98     /* XXX: we might need to add/remove some FOURCCs ... */
99     if(   p_filter->fmt_in.video.i_chroma != VLC_FOURCC('I','4','2','0') )
100     {
101         msg_Err( p_filter, "Unsupported input chroma (%4s)",
102                  (char*)&(p_filter->fmt_in.video.i_chroma) );
103         return VLC_EGENERIC;
104     }
105
106     if( p_filter->fmt_in.video.i_chroma != p_filter->fmt_out.video.i_chroma )
107     {
108         msg_Err( p_filter, "Input and output chromas don't match" );
109         return VLC_EGENERIC;
110     }
111
112     config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options,
113                        p_filter->p_cfg );
114     var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "color" );
115     var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "similaritythres" );
116     var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "saturationthres" );
117
118     /* Allocate structure */
119     p_filter->p_sys = malloc( sizeof( filter_sys_t ) );
120     if( p_filter->p_sys == NULL )
121     {
122         msg_Err( p_filter, "out of memory" );
123         return VLC_ENOMEM;
124     }
125
126     p_filter->pf_video_filter = Filter;
127
128     return VLC_SUCCESS;
129 }
130
131 /*****************************************************************************
132  * Destroy: destroy adjust video thread output method
133  *****************************************************************************
134  * Terminate an output method created by adjustCreateOutputMethod
135  *****************************************************************************/
136 static void Destroy( vlc_object_t *p_this )
137 {
138     filter_t *p_filter = (filter_t *)p_this;
139     free( p_filter->p_sys );
140 }
141
142 /*****************************************************************************
143  * Render: displays previously rendered output
144  *****************************************************************************
145  * This function send the currently rendered image to adjust modified image,
146  * waits until it is displayed and switch the two rendering buffers, preparing
147  * next frame.
148  *****************************************************************************/
149 static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
150 {
151     picture_t *p_outpic;
152     uint8_t *p_in_y, *p_in_u, *p_in_v, *p_in_end_u;
153     uint8_t *p_out_y, *p_out_u, *p_out_v;
154     int i_simthres = var_GetInteger( p_filter, "colorthres-similaritythres" );
155     int i_satthres = var_GetInteger( p_filter, "colorthres-saturationthres" );
156     int i_color = var_GetInteger( p_filter, "colorthres-color" );
157
158     if( !p_pic ) return NULL;
159
160     p_outpic = p_filter->pf_vout_buffer_new( p_filter );
161     if( !p_outpic )
162     {
163         msg_Warn( p_filter, "can't get output picture" );
164         if( p_pic->pf_release )
165             p_pic->pf_release( p_pic );
166         return NULL;
167     }
168
169     p_in_u = p_pic->p[U_PLANE].p_pixels;
170     p_in_v = p_pic->p[V_PLANE].p_pixels;
171     p_in_y = p_pic->p[Y_PLANE].p_pixels;
172     p_in_end_u = p_in_u + p_pic->p[U_PLANE].i_visible_lines
173                         * p_pic->p[U_PLANE].i_pitch - 8;
174
175     p_out_y = p_outpic->p[Y_PLANE].p_pixels;
176     p_out_u = p_outpic->p[U_PLANE].p_pixels;
177     p_out_v = p_outpic->p[V_PLANE].p_pixels;
178
179     /* Create grayscale version of input */
180     p_filter->p_libvlc->
181     pf_memcpy( p_out_y, p_in_y, p_pic->p[Y_PLANE].i_visible_lines
182                * p_pic->p[Y_PLANE].i_pitch - 8 );
183     p_filter->p_libvlc->
184     pf_memset( p_out_u, 0x80, p_pic->p[U_PLANE].i_visible_lines
185                * p_pic->p[U_PLANE].i_pitch - 8 );
186     p_filter->p_libvlc->
187     pf_memset( p_out_v, 0x80, p_pic->p[U_PLANE].i_visible_lines
188                * p_pic->p[U_PLANE].i_pitch - 8 );
189
190     /*
191      * Do the U and V planes
192      */
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);
203
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);
209
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;
215         thres *= thres;
216         if( length > i_satthres && (difflen2*i_simthres< thres ) ) {
217             *p_out_u = *p_in_u;
218             *p_out_v = *p_in_v;
219 //        fprintf(stderr,"keeping color %d %d\n", length, difflen2);
220         }
221         p_in_u++;
222         p_in_v++;
223         p_out_u++;
224         p_out_v++;
225     }
226
227     p_outpic->date = p_pic->date;
228     p_outpic->b_force = p_pic->b_force;
229     p_outpic->i_nb_fields = p_pic->i_nb_fields;
230     p_outpic->b_progressive = p_pic->b_progressive;
231     p_outpic->b_top_field_first = p_pic->b_top_field_first;
232
233     if( p_pic->pf_release )
234         p_pic->pf_release( p_pic );
235
236     return p_outpic;
237 }