]> git.sesse.net Git - mlt/commitdiff
Rotoscoping: Set default mode to alpha and add YAML filter description
authorTill Theato <root@ttill.de>
Thu, 27 Jan 2011 22:31:56 +0000 (23:31 +0100)
committerTill Theato <root@ttill.de>
Thu, 27 Jan 2011 22:31:56 +0000 (23:31 +0100)
src/modules/rotoscoping/Makefile
src/modules/rotoscoping/factory.c
src/modules/rotoscoping/filter_rotoscoping.c
src/modules/rotoscoping/filter_rotoscoping.yml [new file with mode: 0644]

index f4e36a3e8c930c38cd3b5283652a3f7b51fa1f2a..782733ac6d189109d9e0188154f3aec41fdf8a2d 100644 (file)
@@ -31,6 +31,8 @@ clean:
 
 install: all
        install -m 755 $(TARGET) "$(DESTDIR)$(libdir)/mlt"
+       install -d $(DESTDIR)$(datadir)/mlt/rotoscoping
+       install -m 644 filter_rotoscoping.yml "$(DESTDIR)$(datadir)/mlt/rotoscoping"
 
 ifneq ($(wildcard .depend),)
 include .depend
index 04c5d856dd3288236182aa0dfe89e660828a98c0..0d6162b1aabd40d17ce660041da08273897f5531 100644 (file)
 
 #include <string.h>
 #include <framework/mlt.h>
+#include <limits.h>
 
 extern mlt_filter filter_rotoscoping_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
 
+static mlt_properties rotoscoping_metadata( mlt_service_type type, const char *id, void *data )
+{
+    char file[ PATH_MAX ];
+    snprintf( file, PATH_MAX, "%s/rotoscoping/filter_%s.yml", mlt_environment( "MLT_DATA" ), id );
+    return mlt_properties_parse_yaml( file );
+}
+
 MLT_REPOSITORY
 {
         MLT_REGISTER( filter_type, "rotoscoping", filter_rotoscoping_init );
+
+        MLT_REGISTER_METADATA( filter_type, "rotoscoping", rotoscoping_metadata, NULL );
 }
index 54d3d569ae78e3292d35ed51cca4aafce16bb50d..e96a8c33d0fa5b6846792db141a456a6260e772e 100644 (file)
@@ -64,7 +64,7 @@ int stringValue( const char *string, const char **stringList, int max )
 }
 
 /** Linear interp */
-void lerp( const PointF *a, const PointF *b, PointF *result, double t )
+inline void lerp( const PointF *a, const PointF *b, PointF *result, double t )
 {
     result->x = a->x + ( b->x - a->x ) * t;
     result->y = a->y + ( b->y - a->y ) * t;
@@ -72,7 +72,7 @@ void lerp( const PointF *a, const PointF *b, PointF *result, double t )
 
 /** Linear interp. with t = 0.5
  * Speed gain? */
-void lerpHalf( const PointF *a, const PointF *b, PointF *result )
+inline void lerpHalf( const PointF *a, const PointF *b, PointF *result )
 {
     result->x = ( a->x + b->x ) * .5;
     result->y = ( a->y + b->y ) * .5;
@@ -137,7 +137,7 @@ int json2BCurves( cJSON *array, BPointF **points )
  */
 void fillMap( PointF *vertices, int count, int width, int height, uint8_t set, uint8_t *map )
 {
-    int nodes, nodeX[1024], pixelY, i, j, offset;
+    int nodes, nodeX[1024], pixelY, i, j;
 
     memset( map, !set * 255, width * height );
     set *= 255;
@@ -145,7 +145,6 @@ void fillMap( PointF *vertices, int count, int width, int height, uint8_t set, u
     // Loop through the rows of the image
     for ( pixelY = 0; pixelY < height; pixelY++ )
     {
-        offset = width * pixelY;
         /*
          * Build a list of nodes.
          * nodes are located at the borders of the polygon
@@ -168,8 +167,7 @@ void fillMap( PointF *vertices, int count, int width, int height, uint8_t set, u
             {
                 nodeX[i] = MAX( 0, nodeX[i] );
                 nodeX[i+1] = MIN( nodeX[i+1], width );
-                for ( j = nodeX[i]; j <= nodeX[i+1]; j++ )
-                    map[offset + j] = set;
+                memset( map + width * pixelY + nodeX[i], set, nodeX[i+1] - nodeX[i] + 1 );
             }
         }
     }
@@ -180,20 +178,17 @@ void fillMap( PointF *vertices, int count, int width, int height, uint8_t set, u
  */
 void deCasteljau( BPointF *p1, BPointF *p2, BPointF *mid )
 {
-    struct PointF ab, bc, cd, abbc, bccd, final;
+    struct PointF ab, bc, cd;
 
     lerpHalf( &(p1->p), &(p1->h2), &ab );
     lerpHalf( &(p1->h2), &(p2->h1), &bc );
     lerpHalf( &(p2->h1), &(p2->p), &cd );
-    lerpHalf( &ab, &bc, &abbc );
-    lerpHalf( &bc, &cd, &bccd );
-    lerpHalf( &abbc, &bccd, &final );
+    lerpHalf( &ab, &bc, &(mid->h1) ); // mid->h1 = abbc
+    lerpHalf( &bc, &cd, &(mid->h2) ); // mid->h2 = bccd
+    lerpHalf( &(mid->h1), &(mid->h2), &(mid->p) );
 
     p1->h2 = ab;
     p2->h1 = cd;
-    mid->h1 = abbc;
-    mid->p = final;
-    mid->h2 = bccd;
 }
 
 /**
@@ -383,7 +378,7 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
 
     cJSON *root;
     int newSpline = 1;
-    if ( splineOld != NULL && strcmp( spline, splineOld ) == 0 ) {
+    if ( splineOld != NULL && strlen( spline ) && strcmp( spline, splineOld ) == 0 ) {
         // the very same parameter was already parsed by json, use the saved json struct
         newSpline = 0;
         root = mlt_properties_get_data( properties, "spline_json", NULL );
@@ -523,7 +518,7 @@ mlt_filter filter_rotoscoping_init( mlt_profile profile, mlt_service_type type,
         if ( this != NULL )
         {
                 this->process = filter_process;
-                mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "mode", "rgb" );
+                mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "mode", "alpha" );
                 mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "alpha_operation", "clear" );
                 mlt_properties_set_int( MLT_FILTER_PROPERTIES( this ), "invert", 0 );
                 mlt_properties_set_int( MLT_FILTER_PROPERTIES( this ), "precision", 1 );
diff --git a/src/modules/rotoscoping/filter_rotoscoping.yml b/src/modules/rotoscoping/filter_rotoscoping.yml
new file mode 100644 (file)
index 0000000..d409124
--- /dev/null
@@ -0,0 +1,87 @@
+schema_version: 0.1
+type: filter
+identifier: rotoscoping
+title: Rotoscoping
+copyright: Copyright (C) 2011 Till Theato
+version: 0.3
+license: GPL
+language: en
+url: none
+creator: Till Theato <root@ttill.de>
+tags:
+  - Video
+description: Keyframable vector based rotoscoping
+
+notes: ...
+bugs:
+  - in some cases top most row in polygon is assigned to outside
+
+parameters:
+  - identifier: mode
+    title: Mode
+    type: string
+    description: How to visualize the area described by the spline
+    readonly: no
+    required: no
+    default: alpha
+    mutable: yes
+    widget: dropdown
+    values: |
+      alpha
+      matte (black & white)
+      rgb
+
+  - identifier: alpha_operation
+    title: Alpha Operation 
+    type: string
+    description: How to proceed with the current alpha mask (only if mode = alpha)
+    readonly: no
+    required: no
+    default: clear
+    mutable: yes
+    widget: dropdown
+    values: |
+      clear (existing alpha mask is overwritten)
+      max (maximum: existing alpha mask; mask generated by this filter)
+      min (minimum: existing alpha mask; mask generated by this filter)
+      add (existing alpha mask + generated mask)
+      sub (existing alpha mask - generated mask)
+
+  - identifier: invert
+    title: Invert
+    type: integer
+    description: use area inside of spline (0) or the outside (1)
+    readonly: no
+    required: no
+    minimum: 0
+    maximum: 1
+    default: 0
+    mutable: yes
+    widget: checkbox
+
+  - identifier: precision
+    title: Precision
+    type: integer
+    description: |
+      Maximum distance between points calculated for polygon approximating the spline.
+      Big values might make this filter a bit faster but will causes lots of visible edges.
+    readonly: no
+    required: no
+    minimum: 1
+    maximum: 1000 # there is no real limit, but you never wanna use a value that high
+    default: 1
+    mutable: yes
+    widget: spinner
+
+  - identifier: spline
+    title: Spline
+    type: string
+    description: |
+      The spline, a list of cubic Bézier curves, is described using JSON.
+      The most basic parts are the coordinate tuples: [x, y]; x,y will be mapped from the range 0-1 to the image dimensions.
+      Next layer are the Bézier points: [handle 1, point, handle 2] with handle 1, point, handle 2 being coordinate tuples
+      The spline is a list of Bézier points.
+      Optionally keyframes can be defined as a object of frame values, relative to the filter's in point, assigned to splines.
+    readonly: no
+    required: yes
+    mutable: yes