static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { mlt_filter filter = mlt_frame_pop_service( frame ); *format = mlt_image_yuv422; int error = mlt_frame_get_image( frame, image, format, width, height, 1 ); if ( error == 0 && *image ) { float smooth, radius, cx, cy, opac; mlt_properties filter_props = MLT_FILTER_PROPERTIES( filter ) ; mlt_position pos = mlt_filter_get_position( filter, frame ); mlt_position len = mlt_filter_get_length2( filter, frame ); smooth = mlt_properties_anim_get_double( filter_props, "smooth", pos, len ) * 100.0; radius = mlt_properties_anim_get_double( filter_props, "radius", pos, len ) * *width; cx = mlt_properties_anim_get_double( filter_props, "x", pos, len ) * *width; cy = mlt_properties_anim_get_double( filter_props, "y", pos, len ) * *height; opac = mlt_properties_anim_get_double( filter_props, "opacity", pos, len ); int mode = mlt_properties_get_int( filter_props , "mode" ); int video_width = *width; int video_height = *height; int x, y; int w2 = cx, h2 = cy; double delta = 1.0; double max_opac = opac; for ( y=0; y < video_height; y++ ) { int h2_pow2 = pow( y - h2, 2.0 ); for ( x = 0; x < video_width; x++ ) { uint8_t *pix = ( *image + y * video_width * 2 + x * 2 ); int dx = sqrt( h2_pow2 + pow( x - w2, 2.0 )); if (radius-smooth > dx) //center, make not darker { continue; } else if ( radius + smooth <= dx ) //max dark after smooth area { delta = 0.0; } else { // linear pos from of opacity (from 0 to 1) delta = (double) ( radius + smooth - dx ) / ( 2.0 * smooth ); if ( mode == 1 ) { //make cos for smoother non linear fade delta = (double) pow( cos((( 1.0 - delta ) * 3.14159 / 2.0 )), 3.0 ); } } delta = MAX( max_opac, delta ); *pix = (double) (*pix) * delta; *(pix+1) = ((double)(*(pix+1) - 127.0 ) * delta ) + 127.0; } } } return error; }
#include <framework/mlt_frame.h> #include <stdio.h> #include <stdlib.h> #include <math.h> #define CLAMP( x, min, max ) (x) < (min) ? (min) : (x) > (max) ? (max) : (x) /** Do it :-). */ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { // Get the image *format = mlt_image_yuv422; int error = mlt_frame_get_image( this, image, format, width, height, 1 ); // Only process if we have no error and a valid colour space if ( error == 0 ) { // Get the brightness level double level = mlt_properties_get_double( MLT_FRAME_PROPERTIES( this ), "brightness" ); // Only process if level is something other than 1 if ( level != 1.0 ) { int i = *width * *height + 1; uint8_t *p = *image; int32_t m = level * ( 1 << 16 ); int32_t n = 128 * ( ( 1 << 16 ) - m );
static void refresh_image( producer_pixbuf self, mlt_frame frame, mlt_image_format format, int width, int height ) { // Obtain properties of frame and producer mlt_properties properties = MLT_FRAME_PROPERTIES( frame ); mlt_producer producer = &self->parent; // Get index and pixbuf int current_idx = refresh_pixbuf( self, frame ); // optimization for subsequent iterations on single picture if ( current_idx != self->image_idx || width != self->width || height != self->height ) self->image = NULL; mlt_log_debug( MLT_PRODUCER_SERVICE( producer ), "image %p pixbuf %p idx %d current_idx %d pixbuf_idx %d width %d\n", self->image, self->pixbuf, current_idx, self->image_idx, self->pixbuf_idx, width ); // If we have a pixbuf and we need an image if ( self->pixbuf && ( !self->image || ( format != mlt_image_none && format != mlt_image_glsl && format != self->format ) ) ) { char *interps = mlt_properties_get( properties, "rescale.interp" ); if ( interps ) interps = strdup( interps ); int interp = GDK_INTERP_BILINEAR; if ( !interps ) { // Keep bilinear by default } else if ( strcmp( interps, "nearest" ) == 0 ) interp = GDK_INTERP_NEAREST; else if ( strcmp( interps, "tiles" ) == 0 ) interp = GDK_INTERP_TILES; else if ( strcmp( interps, "hyper" ) == 0 || strcmp( interps, "bicubic" ) == 0 ) interp = GDK_INTERP_HYPER; free( interps ); // Note - the original pixbuf is already safe and ready for destruction pthread_mutex_lock( &g_mutex ); GdkPixbuf* pixbuf = gdk_pixbuf_scale_simple( self->pixbuf, width, height, interp ); // Store width and height self->width = width; self->height = height; // Allocate/define image int has_alpha = gdk_pixbuf_get_has_alpha( pixbuf ); int src_stride = gdk_pixbuf_get_rowstride( pixbuf ); int dst_stride = self->width * ( has_alpha ? 4 : 3 ); int image_size = dst_stride * ( height + 1 ); self->image = mlt_pool_alloc( image_size ); self->alpha = NULL; self->format = has_alpha ? mlt_image_rgb24a : mlt_image_rgb24; if ( src_stride != dst_stride ) { int y = self->height; uint8_t *src = gdk_pixbuf_get_pixels( pixbuf ); uint8_t *dst = self->image; while ( y-- ) { memcpy( dst, src, dst_stride ); dst += dst_stride; src += src_stride; } } else { memcpy( self->image, gdk_pixbuf_get_pixels( pixbuf ), src_stride * height ); } pthread_mutex_unlock( &g_mutex ); // Convert image to requested format if ( format != mlt_image_none && format != mlt_image_glsl && format != self->format ) { uint8_t *buffer = NULL; // First, set the image so it can be converted when we get it mlt_frame_replace_image( frame, self->image, self->format, width, height ); mlt_frame_set_image( frame, self->image, image_size, mlt_pool_release ); self->format = format; // get_image will do the format conversion mlt_frame_get_image( frame, &buffer, &format, &width, &height, 0 ); // cache copies of the image and alpha buffers if ( buffer ) { image_size = mlt_image_format_size( format, width, height, NULL ); self->image = mlt_pool_alloc( image_size ); memcpy( self->image, buffer, image_size ); } if ( ( buffer = mlt_frame_get_alpha_mask( frame ) ) ) { self->alpha = mlt_pool_alloc( width * height ); memcpy( self->alpha, buffer, width * height ); } } // Update the cache mlt_cache_item_close( self->image_cache ); mlt_service_cache_put( MLT_PRODUCER_SERVICE( producer ), "pixbuf.image", self->image, image_size, mlt_pool_release ); self->image_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "pixbuf.image" ); self->image_idx = current_idx; mlt_cache_item_close( self->alpha_cache ); self->alpha_cache = NULL; if ( self->alpha ) { mlt_service_cache_put( MLT_PRODUCER_SERVICE( producer ), "pixbuf.alpha", self->alpha, width * height, mlt_pool_release ); self->alpha_cache = mlt_service_cache_get( MLT_PRODUCER_SERVICE( producer ), "pixbuf.alpha" ); } // Finished with pixbuf now g_object_unref( pixbuf ); } // Set width/height of frame mlt_properties_set_int( properties, "width", self->width ); mlt_properties_set_int( properties, "height", self->height ); }