Author: Janne Liljeblad Last-Update: 2013-03-05 Forwarded: yes Origin: upstream, http://git.dyne.org/frei0r/commit/?id=852a4ac Description: Add transparent background option to vectorscope --- src/filter/vectorscope/vectorscope.c | 105 ++++++++++++++++++++++++++++------- 1 file changed, 84 insertions(+), 21 deletions(-) diff --git a/src/filter/vectorscope/vectorscope.c b/src/filter/vectorscope/vectorscope.c index fd28313..e984534 100644 --- a/src/filter/vectorscope/vectorscope.c +++ b/src/filter/vectorscope/vectorscope.c @@ -57,6 +57,8 @@ typedef struct vectorscope_instance { gavl_video_scaler_t* scope_scaler; gavl_video_frame_t* scope_frame_src; gavl_video_frame_t* scope_frame_dst; + double mix; + double overlay_sides; } vectorscope_instance_t; int f0r_init() @@ -74,14 +76,26 @@ void f0r_get_plugin_info( f0r_plugin_info_t* info ) info->color_model = F0R_COLOR_MODEL_RGBA8888; info->frei0r_version = FREI0R_MAJOR_VERSION; info->major_version = 0; - info->minor_version = 1; - info->num_params = 0; + info->minor_version = 2; + info->num_params = 2; info->explanation = "Displays the vectorscope of the video-data"; } void f0r_get_param_info( f0r_param_info_t* info, int param_index ) { - /* empty */ + switch(param_index) + { + case 0: + info->name = "mix"; + info->type = F0R_PARAM_DOUBLE; + info->explanation = "The amount of source image mixed into background of display"; + break; + case 1: + info->name = "overlay sides"; + info->type = F0R_PARAM_BOOL; + info->explanation = "If false, the sides of image are shown without overlay"; + break; + } } f0r_instance_t f0r_construct(unsigned int width, unsigned int height) @@ -94,6 +108,9 @@ f0r_instance_t f0r_construct(unsigned int width, unsigned int height) return NULL; } + inst->mix = 0.0; + inst->overlay_sides = 1.0; + inst->scala = (unsigned char*)malloc( width * height * 4 ); gavl_video_scaler_t* video_scaler; @@ -232,13 +249,35 @@ void f0r_destruct(f0r_instance_t instance) } void f0r_get_param_value(f0r_instance_t instance, f0r_param_t param, int param_index) -{ - /* empty */ +{ + assert(instance); + vectorscope_instance_t* inst = (vectorscope_instance_t*)instance; + + switch(param_index) + { + case 0: + *((double *)param) = inst->mix; + break; + case 1: + *((double *)param) = inst->overlay_sides; + break; + } } void f0r_set_param_value(f0r_instance_t instance, f0r_param_t param, int param_index) -{ - /* empty */ +{ + assert(instance); + vectorscope_instance_t* inst = (vectorscope_instance_t*)instance; + + switch(param_index) + { + case 0: + inst->mix = *((double *)param); + break; + case 1: + inst->overlay_sides = *((double *)param); + break; + } } /* RGB to YCbCr range 0-255 */ @@ -257,7 +296,8 @@ void f0r_update(f0r_instance_t instance, double time, const uint32_t* inframe, u vectorscope_instance_t* inst = (vectorscope_instance_t*)instance; int width = inst->w; - int height = inst->h; + int height = inst->h; + double mix = inst->mix; int len = inst->w * inst->h; int scope_len = SCOPE_WIDTH * SCOPE_HEIGHT; @@ -276,9 +316,17 @@ void f0r_update(f0r_instance_t instance, double time, const uint32_t* inframe, u src_end = src + len; scope_end = scope + scope_len; - while ( dst < dst_end ) { - *(dst++) = 0xFF000000; - } + if ( inst->overlay_sides > 0.5) { + while ( dst < dst_end ) { + *(dst++) = 0xFF000000; + } + } else { + while ( dst < dst_end ) { + *(dst++) = *(src++); + } + src -= len; + } + dst = outframe; while ( scope < scope_end ) { *(scope++) = 0xFF000000; @@ -293,7 +341,6 @@ void f0r_update(f0r_instance_t instance, double time, const uint32_t* inframe, u YCbCr = rgb_to_YCbCr(rgb); x = YCbCr.Cb; y = 255-YCbCr.Cr; - //printf ("Cb: %d, Cr: %d\n", x, y ); if ( x >= 0 && x < SCOPE_WIDTH && y >= 0 && y < SCOPE_HEIGHT ) { pixel = (uint8_t*)&scope[x+SCOPE_WIDTH*y]; if ( pixel[0] < 255 ) { @@ -301,7 +348,6 @@ void f0r_update(f0r_instance_t instance, double time, const uint32_t* inframe, u pixel[1]++; pixel[2]++; } - //dst[x+width*y] += 1;//0xFFFFFFFF; } } @@ -310,17 +356,34 @@ void f0r_update(f0r_instance_t instance, double time, const uint32_t* inframe, u gavl_video_scaler_scale( inst->scope_scaler, inst->scope_frame_src, inst->scope_frame_dst ); - unsigned char *scala8, *dst8, *dst8_end; + unsigned char *scala8, *dst8, *dst8_end, *src8; scala8 = inst->scala; + src8 = (unsigned char*)inframe; dst8 = (unsigned char*)outframe; dst8_end = dst8 + ( len * 4 ); - while ( dst8 < dst8_end ) { - dst8[0] = ( ( ( scala8[0] - dst8[0] ) * 255 * scala8[3] ) >> 16 ) + dst8[0]; - dst8[1] = ( ( ( scala8[1] - dst8[1] ) * 255 * scala8[3] ) >> 16 ) + dst8[1]; - dst8[2] = ( ( ( scala8[2] - dst8[2] ) * 255 * scala8[3] ) >> 16 ) + dst8[2]; - scala8 += 4; - dst8 += 4; - } + if (mix > 0.001 ) { // to not lose performance for non-mixing users + while ( dst8 < dst8_end ) { + dst8[0] = ( ( ( scala8[0] - dst8[0] ) * 255 * scala8[3] ) >> 16 ) + dst8[0]; + dst8[1] = ( ( ( scala8[1] - dst8[1] ) * 255 * scala8[3] ) >> 16 ) + dst8[1]; + dst8[2] = ( ( ( scala8[2] - dst8[2] ) * 255 * scala8[3] ) >> 16 ) + dst8[2]; + if (dst8[0] == 0) { + dst8[0] = src8[0] * mix; + dst8[1] = src8[1] * mix; + dst8[2] = src8[2] * mix; + } + scala8 += 4; + dst8 += 4; + src8 += 4; + } + } else { + while ( dst8 < dst8_end ) { + dst8[0] = ( ( ( scala8[0] - dst8[0] ) * 255 * scala8[3] ) >> 16 ) + dst8[0]; + dst8[1] = ( ( ( scala8[1] - dst8[1] ) * 255 * scala8[3] ) >> 16 ) + dst8[1]; + dst8[2] = ( ( ( scala8[2] - dst8[2] ) * 255 * scala8[3] ) >> 16 ) + dst8[2]; + scala8 += 4; + dst8 += 4; + } + } } -- 2.0.0.rc2