}
/** 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;
/** 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;
*/
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;
// 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
{
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 );
}
}
}
*/
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;
}
/**
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 );
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 );
--- /dev/null
+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