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