From: Till Theato Date: Thu, 27 Jan 2011 22:31:56 +0000 (+0100) Subject: Rotoscoping: Set default mode to alpha and add YAML filter description X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=4455cda38d09e68c234fcbea7b0f068f78685970;p=mlt Rotoscoping: Set default mode to alpha and add YAML filter description --- diff --git a/src/modules/rotoscoping/Makefile b/src/modules/rotoscoping/Makefile index f4e36a3e..782733ac 100644 --- a/src/modules/rotoscoping/Makefile +++ b/src/modules/rotoscoping/Makefile @@ -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 diff --git a/src/modules/rotoscoping/factory.c b/src/modules/rotoscoping/factory.c index 04c5d856..0d6162b1 100644 --- a/src/modules/rotoscoping/factory.c +++ b/src/modules/rotoscoping/factory.c @@ -20,10 +20,20 @@ #include #include +#include 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 ); } diff --git a/src/modules/rotoscoping/filter_rotoscoping.c b/src/modules/rotoscoping/filter_rotoscoping.c index 54d3d569..e96a8c33 100644 --- a/src/modules/rotoscoping/filter_rotoscoping.c +++ b/src/modules/rotoscoping/filter_rotoscoping.c @@ -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 index 00000000..d4091245 --- /dev/null +++ b/src/modules/rotoscoping/filter_rotoscoping.yml @@ -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 +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