static void generate_qimage( mlt_properties frame_properties ) { mlt_producer producer = static_cast<mlt_producer>( mlt_properties_get_data( frame_properties, "_producer_qtext", NULL ) ); mlt_properties producer_properties = MLT_PRODUCER_PROPERTIES( producer ); QImage* qImg = static_cast<QImage*>( mlt_properties_get_data( producer_properties, "_qimg", NULL ) ); QSize target_size( mlt_properties_get_int( frame_properties, "rescale_width" ), mlt_properties_get_int( frame_properties, "rescale_height" ) ); QSize native_size( mlt_properties_get_int( frame_properties, "meta.media.width" ), mlt_properties_get_int( frame_properties, "meta.media.height" ) ); QPainterPath* qPath = static_cast<QPainterPath*>( mlt_properties_get_data( frame_properties, "_qpath", NULL ) ); mlt_color bg_color = mlt_properties_get_color( frame_properties, "_bgcolour" ); mlt_color fg_color = mlt_properties_get_color( frame_properties, "_fgcolour" ); mlt_color ol_color = mlt_properties_get_color( frame_properties, "_olcolour" ); int outline = mlt_properties_get_int( frame_properties, "_outline" ); qreal sx = 1.0; qreal sy = 1.0; // Create a new image and set up scaling if( !target_size.isEmpty() && target_size != native_size ) { *qImg = QImage( target_size, QImage::Format_ARGB32 ); sx = (qreal)target_size.width() / (qreal)native_size.width(); sy = (qreal)target_size.height() / (qreal)native_size.height(); } else { *qImg = QImage( native_size, QImage::Format_ARGB32 ); } qImg->fill( QColor( bg_color.r, bg_color.g, bg_color.b, bg_color.a ).rgba() ); // Draw the text QPainter painter( qImg ); // Scale the painter rather than the image for better looking results. painter.scale( sx, sy ); painter.setRenderHints( QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::HighQualityAntialiasing ); QPen pen; pen.setWidth( outline ); if( outline ) { pen.setColor( QColor( ol_color.r, ol_color.g, ol_color.b, ol_color.a ) ); } else { pen.setColor( QColor( bg_color.r, bg_color.g, bg_color.b, bg_color.a ) ); } painter.setPen( pen ); QBrush brush( QColor( fg_color.r, fg_color.g, fg_color.b, fg_color.a ) ); painter.setBrush( brush ); painter.drawPath( *qPath ); }
static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable ) { // Obtain properties of frame mlt_properties properties = MLT_FRAME_PROPERTIES( frame ); // Obtain the producer for this frame mlt_producer producer = mlt_properties_get_data( properties, "producer_colour", NULL ); mlt_service_lock( MLT_PRODUCER_SERVICE( producer ) ); // Obtain properties of producer mlt_properties producer_props = MLT_PRODUCER_PROPERTIES( producer ); // Get the current and previous colour strings char *now = mlt_properties_get( producer_props, "resource" ); char *then = mlt_properties_get( producer_props, "_resource" ); // Get the current image and dimensions cached in the producer int size = 0; uint8_t *image = mlt_properties_get_data( producer_props, "image", &size ); int current_width = mlt_properties_get_int( producer_props, "_width" ); int current_height = mlt_properties_get_int( producer_props, "_height" ); mlt_image_format current_format = mlt_properties_get_int( producer_props, "_format" ); // Parse the colour if ( now && strchr( now, '/' ) ) { now = strdup( strrchr( now, '/' ) + 1 ); mlt_properties_set( producer_props, "resource", now ); free( now ); now = mlt_properties_get( producer_props, "resource" ); } mlt_color color = mlt_properties_get_color( producer_props, "resource" ); if ( mlt_properties_get( producer_props, "mlt_image_format") ) *format = mlt_image_format_id( mlt_properties_get( producer_props, "mlt_image_format") ); // Choose suitable out values if nothing specific requested if ( *format == mlt_image_none || *format == mlt_image_glsl ) *format = mlt_image_rgb24a; if ( *width <= 0 ) *width = mlt_service_profile( MLT_PRODUCER_SERVICE(producer) )->width; if ( *height <= 0 ) *height = mlt_service_profile( MLT_PRODUCER_SERVICE(producer) )->height; // Choose default image format if specific request is unsupported if (*format!=mlt_image_yuv420p && *format!=mlt_image_yuv422 && *format!=mlt_image_rgb24 && *format!= mlt_image_glsl && *format!= mlt_image_glsl_texture) *format = mlt_image_rgb24a; // See if we need to regenerate if ( !now || ( then && strcmp( now, then ) ) || *width != current_width || *height != current_height || *format != current_format ) { // Color the image int i = *width * *height + 1; int bpp; // Allocate the image size = mlt_image_format_size( *format, *width, *height, &bpp ); uint8_t *p = image = mlt_pool_alloc( size ); // Update the producer mlt_properties_set_data( producer_props, "image", image, size, mlt_pool_release, NULL ); mlt_properties_set_int( producer_props, "_width", *width ); mlt_properties_set_int( producer_props, "_height", *height ); mlt_properties_set_int( producer_props, "_format", *format ); mlt_properties_set( producer_props, "_resource", now ); mlt_service_unlock( MLT_PRODUCER_SERVICE( producer ) ); switch ( *format ) { case mlt_image_yuv420p: { int plane_size = *width * *height; uint8_t y, u, v; RGB2YUV_601_SCALED( color.r, color.g, color.b, y, u, v ); memset(p + 0, y, plane_size); memset(p + plane_size, u, plane_size/4); memset(p + plane_size + plane_size/4, v, plane_size/4); mlt_properties_set_int( properties, "colorspace", 601 ); break; } case mlt_image_yuv422: { int uneven = *width % 2; int count = ( *width - uneven ) / 2 + 1; uint8_t y, u, v; RGB2YUV_601_SCALED( color.r, color.g, color.b, y, u, v ); i = *height + 1; while ( --i ) { int j = count; while ( --j ) { *p ++ = y; *p ++ = u; *p ++ = y; *p ++ = v; } if ( uneven ) { *p ++ = y; *p ++ = u; } } mlt_properties_set_int( properties, "colorspace", 601 ); break; } case mlt_image_rgb24: while ( --i ) { *p ++ = color.r; *p ++ = color.g; *p ++ = color.b; } break; case mlt_image_glsl: case mlt_image_glsl_texture: memset(p, 0, size); break; case mlt_image_rgb24a: while ( --i ) { *p ++ = color.r; *p ++ = color.g; *p ++ = color.b; *p ++ = color.a; } break; default: mlt_log_error( MLT_PRODUCER_SERVICE( producer ), "invalid image format %s\n", mlt_image_format_name( *format ) ); } } else { mlt_service_unlock( MLT_PRODUCER_SERVICE( producer ) ); } // Create the alpha channel int alpha_size = 0; uint8_t *alpha = NULL; // Initialise the alpha if (color.a < 255 || *format == mlt_image_rgb24a) { alpha_size = *width * *height; alpha = mlt_pool_alloc( alpha_size ); if ( alpha ) memset( alpha, color.a, alpha_size ); else alpha_size = 0; } // Clone our image if (buffer && image && size > 0) { *buffer = mlt_pool_alloc( size ); memcpy( *buffer, image, size ); } // Now update properties so we free the copy after mlt_frame_set_image( frame, *buffer, size, mlt_pool_release ); mlt_frame_set_alpha( frame, alpha, alpha_size, mlt_pool_release ); mlt_properties_set_double( properties, "aspect_ratio", mlt_properties_get_double( producer_props, "aspect_ratio" ) ); mlt_properties_set_int( properties, "meta.media.width", *width ); mlt_properties_set_int( properties, "meta.media.height", *height ); return 0; }