Author: Janne Liljeblad <janne.liljeblad@gmail.com>
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

