#include <string.h>
#include <math.h>
-typedef void ( *composite_line_fn )( uint8_t *dest, uint8_t *src, int width_src, uint8_t *alpha_b, uint8_t *alpha_a, int weight, uint16_t *luma, int softness );
+typedef void ( *composite_line_fn )( uint8_t *dest, uint8_t *src, int width_src, uint8_t *alpha_b, uint8_t *alpha_a, int weight, uint16_t *luma, double softness );
/** Geometry struct.
*/
*p++ = ( image[ i ] - 16 ) * 299; // 299 = 65535 / 219
}
-static inline int calculate_mix( uint16_t *luma, int j, int soft, int weight, int alpha )
+static inline int calculate_mix( uint16_t *luma, int j, double soft, int weight, int alpha )
{
- return ( ( ( luma == NULL ) ? weight : smoothstep( luma[ j ], luma[ j ] + soft, weight + soft ) ) * alpha ) >> 8;
+ int32_t i_softness = soft * ( 1 << 16 );
+ uint32_t a = ( 1.0 + soft ) * weight / 100 * ( ( 1 << 16 ) - 1 );
+ return ( ( luma == NULL ) ? weight : smoothstep( luma[ j ], luma[ j ] + i_softness, a ) * alpha ) >> 8;
}
static inline uint8_t sample_mix( uint8_t dest, uint8_t src, int mix )
/** Composite a source line over a destination line
*/
-static void composite_line_yuv( uint8_t *dest, uint8_t *src, int width, uint8_t *alpha_b, uint8_t *alpha_a, int weight, uint16_t *luma, int soft )
+static void composite_line_yuv( uint8_t *dest, uint8_t *src, int width, uint8_t *alpha_b, uint8_t *alpha_a, int weight, uint16_t *luma, double soft )
{
register int j;
register int mix;
}
}
-static void composite_line_yuv_or( uint8_t *dest, uint8_t *src, int width, uint8_t *alpha_b, uint8_t *alpha_a, int weight, uint16_t *luma, int soft )
+static void composite_line_yuv_or( uint8_t *dest, uint8_t *src, int width, uint8_t *alpha_b, uint8_t *alpha_a, int weight, uint16_t *luma, double soft )
{
register int j;
register int mix;
}
}
-static void composite_line_yuv_and( uint8_t *dest, uint8_t *src, int width, uint8_t *alpha_b, uint8_t *alpha_a, int weight, uint16_t *luma, int soft )
+static void composite_line_yuv_and( uint8_t *dest, uint8_t *src, int width, uint8_t *alpha_b, uint8_t *alpha_a, int weight, uint16_t *luma, double soft )
{
register int j;
register int mix;
}
}
-static void composite_line_yuv_xor( uint8_t *dest, uint8_t *src, int width, uint8_t *alpha_b, uint8_t *alpha_a, int weight, uint16_t *luma, int soft )
+static void composite_line_yuv_xor( uint8_t *dest, uint8_t *src, int width, uint8_t *alpha_b, uint8_t *alpha_a, int weight, uint16_t *luma, double soft )
{
register int j;
register int mix;
/** Composite function.
*/
-static int composite_yuv( uint8_t *p_dest, int width_dest, int height_dest, uint8_t *p_src, int width_src, int height_src, uint8_t *alpha_b, uint8_t *alpha_a, struct geometry_s geometry, int field, uint16_t *p_luma, int32_t softness, composite_line_fn line_fn )
+static int composite_yuv( uint8_t *p_dest, int width_dest, int height_dest, uint8_t *p_src, int width_src, int height_src, uint8_t *alpha_b, uint8_t *alpha_a, struct geometry_s geometry, int field, uint16_t *p_luma, double softness, composite_line_fn line_fn )
{
int ret = 0;
int i;
int x_src = -geometry.x_src, y_src = -geometry.y_src;
int uneven_x_src = ( x_src % 2 );
- int32_t weight = ( ( 1 << 16 ) - 1 ) * ( geometry.item.mix / 100 );
int step = ( field > -1 ) ? 2 : 1;
int bpp = 2;
int stride_src = geometry.sw * bpp;
// now do the compositing only to cropped extents
for ( i = 0; i < height_src; i += step )
{
- line_fn( p_dest, p_src, width_src, alpha_b, alpha_a, weight, p_luma, softness );
+ line_fn( p_dest, p_src, width_src, alpha_b, alpha_a, geometry.item.mix, p_luma, softness );
p_src += stride_src;
p_dest += stride_dest;
// Do the calculation
// NB: Locks needed here since the properties are being modified
+ int invert = mlt_properties_get_int( properties, "invert" );
mlt_service_lock( MLT_TRANSITION_SERVICE( this ) );
- composite_calculate( this, &result, a_frame, position );
+ composite_calculate( this, &result, invert ? b_frame : a_frame, position );
mlt_service_unlock( MLT_TRANSITION_SERVICE( this ) );
// Since we are the consumer of the b_frame, we must pass along these
}
// Get the image from the a frame
- mlt_frame_get_image( a_frame, image, format, width, height, 1 );
+ mlt_frame_get_image( a_frame, invert ? &image_b : image, format, width, height, 1 );
alpha_a = mlt_frame_get_alpha_mask( a_frame );
// Optimisation - no compositing required
height_b = mlt_properties_get_int( a_props, "dest_height" );
}
- if ( *image != image_b && ( image_b != NULL || get_b_frame_image( this, b_frame, &image_b, &width_b, &height_b, &result ) == 0 ) )
+ if ( *image != image_b && ( ( invert ? 0 : image_b ) || get_b_frame_image( this, b_frame, invert ? image : &image_b, &width_b, &height_b, &result ) == 0 ) )
{
uint8_t *dest = *image;
uint8_t *src = image_b;
mlt_properties_get_int( properties, "progressive" );
int field;
- int32_t luma_softness = mlt_properties_get_double( properties, "softness" ) * ( 1 << 16 );
+ double luma_softness = mlt_properties_get_double( properties, "softness" );
uint16_t *luma_bitmap = get_luma( this, properties, width_b, height_b );
char *operator = mlt_properties_get( properties, "operator" );
// Do the calculation if we need to
// NB: Locks needed here since the properties are being modified
mlt_service_lock( MLT_TRANSITION_SERVICE( this ) );
- composite_calculate( this, &result, a_frame, field_position );
+ composite_calculate( this, &result, invert ? b_frame : a_frame, field_position );
mlt_service_unlock( MLT_TRANSITION_SERVICE( this ) );
if ( mlt_properties_get_int( properties, "titles" ) )
}
// Composite the b_frame on the a_frame
- composite_yuv( dest, *width, *height, src, width_b, height_b, alpha_b, alpha_a, result, progressive ? -1 : field, luma_bitmap, luma_softness, line_fn );
+ if ( invert )
+ composite_yuv( dest, width_b, height_b, src, *width, *height, alpha_a, alpha_b, result, progressive ? -1 : field, luma_bitmap, luma_softness, line_fn );
+ else
+ composite_yuv( dest, *width, *height, src, width_b, height_b, alpha_b, alpha_a, result, progressive ? -1 : field, luma_bitmap, luma_softness, line_fn );
}
}
}
mlt_properties_set( properties, "start", arg != NULL ? arg : "0,0:100%x100%" );
// Default factory
- mlt_properties_set( properties, "factory", "fezzik" );
+ mlt_properties_set( properties, "factory", mlt_environment( "MLT_PRODUCER" ) );
// Use alignment (and hence alpha of b frame)
mlt_properties_set_int( properties, "aligned", 1 );