added a color threshold filter that can make effects similar to "the

yellow guy" in sin city or the red dressed girl in the beginning of
schindlers list
parent 698c348e
......@@ -1091,7 +1091,7 @@ VLC_ADD_PLUGINS([fixed32tos16 s16tofixed32 u8tofixed32 mono])
VLC_ADD_PLUGINS([trivial_resampler ugly_resampler])
VLC_ADD_PLUGINS([trivial_channel_mixer trivial_mixer])
VLC_ADD_PLUGINS([playlist export sgimb nsc xtag])
VLC_ADD_PLUGINS([i420_rgb rawvideo blend scale image logo magnify puzzle])
VLC_ADD_PLUGINS([i420_rgb rawvideo blend scale image logo magnify puzzle colorthres])
VLC_ADD_PLUGINS([wav araw subtitle vobsub adpcm a52sys dtssys au ty voc xa nuv])
VLC_ADD_PLUGINS([access_directory access_file access_udp access_tcp])
VLC_ADD_PLUGINS([access_http access_mms access_ftp ipv4])
......
......@@ -26,4 +26,5 @@ SOURCES_opencv_example = opencv_example.cpp filter_event_info.h
SOURCES_rotate = rotate.c
SOURCES_noise = noise.c
SOURCES_puzzle = puzzle.c
SOURCES_colorthres = colorthres.c
noinst_HEADERS = filter_common.h
/*****************************************************************************
* colorthres.c: Theshold color based on similarity to reference color
*****************************************************************************
* Copyright (C) 2000-2006 the VideoLAN team
* $Id$
*
* Authors: Sigmund Augdal <dnumgis@videolan.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <errno.h>
#include <stdlib.h> /* malloc(), free() */
#include <string.h>
#include <math.h>
#include <vlc/vlc.h>
#include <vlc/sout.h>
#include <vlc/decoder.h>
#include "vlc_filter.h"
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int Create ( vlc_object_t * );
static void Destroy ( vlc_object_t * );
static picture_t *Filter( filter_t *, picture_t * );
/*****************************************************************************
* Module descriptor
*****************************************************************************/
#define COLOR_TEXT N_("Color")
#define COLOR_LONGTEXT N_("Colors similar to this will be kept, others will be "\
"grayscaled. This must be an hexadecimal (like HTML colors). The first two "\
"chars are for red, then green, then blue. #000000 = black, #FF0000 = red,"\
" #00FF00 = green, #FFFF00 = yellow (red + green), #FFFFFF = white" )
static int pi_color_values[] = {
0x00FF0000, 0x00FF00FF, 0x00FFFF00, 0x0000FF00, 0x000000FF, 0x0000FFFF };
static char *ppsz_color_descriptions[] = {
N_("Red"), N_("Fuchsia"), N_("Yellow"), N_("Lime"), N_("Blue"), N_("Aqua") };
vlc_module_begin();
set_description( _("Color threshold filter") );
set_shortname( _("Color threshold" ));
set_category( CAT_VIDEO );
set_subcategory( SUBCAT_VIDEO_VFILTER );
set_capability( "video filter2", 0 );
add_integer( "colorthres-color", 0x00FF0000, NULL, COLOR_TEXT,
COLOR_LONGTEXT, VLC_FALSE );
change_integer_list( pi_color_values, ppsz_color_descriptions, 0 );
add_integer( "colorthres-saturationthres", 20, NULL, "saturaton threshold",
"", VLC_FALSE );
add_integer( "colorthres-similaritythres", 15, NULL, "similarity threshold",
"", VLC_FALSE );
set_callbacks( Create, Destroy );
vlc_module_end();
/*****************************************************************************
* filter_sys_t: adjust filter method descriptor
*****************************************************************************/
struct filter_sys_t
{
};
/*****************************************************************************
* Create: allocates adjust video thread output method
*****************************************************************************
* This function allocates and initializes a adjust vout method.
*****************************************************************************/
static int Create( vlc_object_t *p_this )
{
filter_t *p_filter = (filter_t *)p_this;
/* XXX: we might need to add/remove some FOURCCs ... */
if( p_filter->fmt_in.video.i_chroma != VLC_FOURCC('I','4','2','0') )
{
msg_Err( p_filter, "Unsupported input chroma (%4s)",
(char*)&(p_filter->fmt_in.video.i_chroma) );
return VLC_EGENERIC;
}
if( p_filter->fmt_in.video.i_chroma != p_filter->fmt_out.video.i_chroma )
{
msg_Err( p_filter, "Input and output chromas don't match" );
return VLC_EGENERIC;
}
var_Create( p_filter, "colorthres-color", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
var_Create( p_filter, "colorthres-similaritythres", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
var_Create( p_filter, "colorthres-saturationthres", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
/* Allocate structure */
p_filter->p_sys = malloc( sizeof( filter_sys_t ) );
if( p_filter->p_sys == NULL )
{
msg_Err( p_filter, "out of memory" );
return VLC_ENOMEM;
}
p_filter->pf_video_filter = Filter;
return VLC_SUCCESS;
}
/*****************************************************************************
* Destroy: destroy adjust video thread output method
*****************************************************************************
* Terminate an output method created by adjustCreateOutputMethod
*****************************************************************************/
static void Destroy( vlc_object_t *p_this )
{
filter_t *p_filter = (filter_t *)p_this;
free( p_filter->p_sys );
}
/*****************************************************************************
* Render: displays previously rendered output
*****************************************************************************
* This function send the currently rendered image to adjust modified image,
* waits until it is displayed and switch the two rendering buffers, preparing
* next frame.
*****************************************************************************/
static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
{
picture_t *p_outpic;
uint8_t *p_in_y, *p_in_u, *p_in_v, *p_in_end_u;
uint8_t *p_out_y, *p_out_u, *p_out_v;
int i_simthres = var_GetInteger( p_filter, "colorthres-similaritythres" );
int i_satthres = var_GetInteger( p_filter, "colorthres-saturationthres" );
int i_color = var_GetInteger( p_filter, "colorthres-color" );
if( !p_pic ) return NULL;
p_outpic = p_filter->pf_vout_buffer_new( p_filter );
if( !p_outpic )
{
msg_Warn( p_filter, "can't get output picture" );
if( p_pic->pf_release )
p_pic->pf_release( p_pic );
return NULL;
}
p_in_u = p_pic->p[U_PLANE].p_pixels;
p_in_v = p_pic->p[V_PLANE].p_pixels;
p_in_y = p_pic->p[Y_PLANE].p_pixels;
p_in_end_u = p_in_u + p_pic->p[U_PLANE].i_visible_lines
* p_pic->p[U_PLANE].i_pitch - 8;
p_out_y = p_outpic->p[Y_PLANE].p_pixels;
p_out_u = p_outpic->p[U_PLANE].p_pixels;
p_out_v = p_outpic->p[V_PLANE].p_pixels;
/* Create grayscale version of input */
memcpy( p_out_y, p_in_y, p_pic->p[Y_PLANE].i_visible_lines
* p_pic->p[Y_PLANE].i_pitch - 8 );
memset( p_out_u, 0x80, p_pic->p[U_PLANE].i_visible_lines
* p_pic->p[U_PLANE].i_pitch - 8 );
memset( p_out_v, 0x80, p_pic->p[U_PLANE].i_visible_lines
* p_pic->p[U_PLANE].i_pitch - 8 );
/*
* Do the U and V planes
*/
int i_red = ( i_color & 0xFF0000 ) >> 16;
int i_green = ( i_color & 0xFF00 ) >> 8;
int i_blue = i_color & 0xFF;
int i_u = (int8_t)(( -38 * i_red - 74 * i_green +
112 * i_blue + 128) >> 8) + 128;
int i_v = (int8_t)(( 112 * i_red - 94 * i_green -
18 * i_blue + 128) >> 8) + 128;
int refu = i_u - 0x80; /*bright red*/
int refv = i_v - 0x80;
int reflength = sqrt(refu*refu+refv*refv);
while( p_in_u < p_in_end_u ) {
/* Length of color vector */
int inu = (*p_in_u) - 0x80;
int inv = (*p_in_v) - 0x80;
int length = sqrt(inu*inu+inv*inv);
int diffu = refu * length - inu *reflength;
int diffv = refv * length - inv *reflength;
long long int difflen2=diffu*diffu;
difflen2 +=diffv*diffv;
long long int thres = length*reflength;
thres *= thres;
if( length > i_satthres && (difflen2*i_simthres< thres ) ) {
*p_out_u = *p_in_u;
*p_out_v = *p_in_v;
// fprintf(stderr,"keeping color %d %d\n", length, difflen2);
}
p_in_u++;
p_in_v++;
p_out_u++;
p_out_v++;
}
p_outpic->date = p_pic->date;
p_outpic->b_force = p_pic->b_force;
p_outpic->i_nb_fields = p_pic->i_nb_fields;
p_outpic->b_progressive = p_pic->b_progressive;
p_outpic->b_top_field_first = p_pic->b_top_field_first;
if( p_pic->pf_release )
p_pic->pf_release( p_pic );
return p_outpic;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment