*d++ = y1;
*d++ = (v0+v1) >> 1;
}
+ if ( width % 2 )
+ {
+ r = *s++;
+ g = *s++;
+ b = *s++;
+ *alpha++ = *s++;
+ RGB2YUV (r, g, b, y0, u0 , v0);
+ *d++ = y0;
+ *d++ = u0;
+ }
}
return ret;
}
*d++ = y1;
*d++ = (v0+v1) >> 1;
}
+ if ( width % 2 )
+ {
+ r = *s++;
+ g = *s++;
+ b = *s++;
+ RGB2YUV (r, g, b, y0, u0 , v0);
+ *d++ = y0;
+ *d++ = u0;
+ }
}
return ret;
}
TARGET = ../libmltgtk2.so
OBJS = factory.o \
- producer_pixbuf.o
+ producer_pixbuf.o \
+ producer_pango.o
-CFLAGS = `pkg-config gdk-pixbuf-2.0 --cflags` -I../../ -Wall -g -D_FILE_OFFSET_BITS=64 -pthread
+CFLAGS = `pkg-config gdk-pixbuf-2.0 --cflags` `pkg-config pangoft2 --cflags` -I../../ -Wall -g -D_FILE_OFFSET_BITS=64 -pthread
-LDFLAGS = `pkg-config gdk-pixbuf-2.0 --libs`
+LDFLAGS = `pkg-config gdk-pixbuf-2.0 --libs` `pkg-config pangoft2 --libs`
SRCS := $(OBJS:.o=.c)
#include <string.h>
#include "producer_pixbuf.h"
+#include "producer_pango.h"
void *mlt_create_producer( char *id, void *arg )
{
if ( !strcmp( id, "pixbuf" ) )
return producer_pixbuf_init( arg );
+ else if ( !strcmp( id, "pango" ) )
+ return producer_pango_init( arg );
return NULL;
}
--- /dev/null
+/*
+ * producer_pango.c -- a pango-based titler
+ * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
+ * Author: Dan Dennedy <dan@dennedy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "producer_pango.h"
+#include <framework/mlt_frame.h>
+#include <stdlib.h>
+#include <string.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <pango/pangoft2.h>
+#include <freetype/freetype.h>
+
+// special color type used by internal pango routines
+typedef struct
+{
+ uint8_t r, g, b, a;
+} rgba_color;
+
+// Forward declarations
+static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int index );
+static void producer_close( mlt_producer parent );
+static void pango_draw_background( GdkPixbuf *pixbuf, rgba_color bg );
+static GdkPixbuf *pango_get_pixbuf( const char *markup, rgba_color fg, rgba_color bg, int pad, int align );
+
+mlt_producer producer_pango_init( const char *markup )
+{
+ producer_pango this = calloc( sizeof( struct producer_pango_s ), 1 );
+ if ( this != NULL && mlt_producer_init( &this->parent, this ) == 0 )
+ {
+ mlt_producer producer = &this->parent;
+
+ producer->get_frame = producer_get_frame;
+ producer->close = producer_close;
+
+ this->markup = strdup( markup );
+ this->is_pal = 1;
+ g_type_init();
+
+ return producer;
+ }
+ free( this );
+ return NULL;
+}
+
+static int producer_get_image( mlt_frame this, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
+{
+ // Obtain properties of frame
+ mlt_properties properties = mlt_frame_properties( this );
+
+ // May need to know the size of the image to clone it
+ int size = 0;
+
+ // Get the image
+ uint8_t *image = mlt_properties_get_data( properties, "image", &size );
+
+ // Get width and height
+ *width = mlt_properties_get_int( properties, "width" );
+ *height = mlt_properties_get_int( properties, "height" );
+
+ // Clone if necessary
+ if ( writable )
+ {
+ // Clone our image
+ uint8_t *copy = malloc( size );
+ memcpy( copy, image, size );
+
+ // We're going to pass the copy on
+ image = copy;
+
+ // Now update properties so we free the copy after
+ mlt_properties_set_data( properties, "image", copy, size, free, NULL );
+ }
+
+ // Pass on the image
+ *buffer = image;
+
+ return 0;
+}
+
+static uint8_t *producer_get_alpha_mask( mlt_frame this )
+{
+ // Obtain properties of frame
+ mlt_properties properties = mlt_frame_properties( this );
+
+ // Return the alpha mask
+ return mlt_properties_get_data( properties, "alpha", NULL );
+}
+
+static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index )
+{
+ producer_pango this = producer->child;
+ GdkPixbuf *pixbuf = NULL;
+
+ // Generate a frame
+ *frame = mlt_frame_init( );
+
+ // Obtain properties of frame
+ mlt_properties properties = mlt_frame_properties( *frame );
+
+ // optimization for subsequent iterations on single picture
+ if ( this->image != NULL )
+ {
+ // Set width/height
+ mlt_properties_set_int( properties, "width", this->width );
+ mlt_properties_set_int( properties, "height", this->height );
+
+ // if picture sequence pass the image and alpha data without destructor
+ mlt_properties_set_data( properties, "image", this->image, 0, NULL, NULL );
+ mlt_properties_set_data( properties, "alpha", this->alpha, 0, NULL, NULL );
+
+ // Set alpha mask call back
+ ( *frame )->get_alpha_mask = producer_get_alpha_mask;
+
+ // Stack the get image callback
+ mlt_frame_push_get_image( *frame, producer_get_image );
+
+ }
+ else
+ {
+ // the following four will be replaced by properties
+ rgba_color fg = { 0xff, 0xff, 0xff, 0xff };
+ rgba_color bg = { 0, 0, 0, 0x7f };
+ int pad = 8;
+ int align = 0; /* left */
+
+ // Render the title
+ pixbuf = pango_get_pixbuf( this->markup, fg, bg, pad, align );
+ }
+
+ // If we have a pixbuf
+ if ( pixbuf )
+ {
+ // Scale to adjust for sample aspect ratio
+ if ( this->is_pal )
+ {
+ GdkPixbuf *temp = pixbuf;
+ GdkPixbuf *scaled = gdk_pixbuf_scale_simple( pixbuf,
+ (gint) ( (float) gdk_pixbuf_get_width( pixbuf ) * 54.0/59.0),
+ gdk_pixbuf_get_height( pixbuf ), GDK_INTERP_HYPER );
+ pixbuf = scaled;
+ g_object_unref( temp );
+ }
+ else
+ {
+ GdkPixbuf *temp = pixbuf;
+ GdkPixbuf *scaled = gdk_pixbuf_scale_simple( pixbuf,
+ (gint) ( (float) gdk_pixbuf_get_width( pixbuf ) * 11.0/10.0 ),
+ gdk_pixbuf_get_height( pixbuf ), GDK_INTERP_HYPER );
+ pixbuf = scaled;
+ g_object_unref( temp );
+ }
+
+ // Store width and height
+ this->width = gdk_pixbuf_get_width( pixbuf );
+ this->height = gdk_pixbuf_get_height( pixbuf );
+
+ // Allocate/define image and alpha
+ uint8_t *image = malloc( this->width * this->height * 2 );
+ uint8_t *alpha = NULL;
+
+ // Extract YUV422 and alpha
+ if ( gdk_pixbuf_get_has_alpha( pixbuf ) )
+ {
+ // Allocate the alpha mask
+ alpha = malloc( this->width * this->height );
+
+ // Convert the image
+ mlt_convert_rgb24a_to_yuv422( gdk_pixbuf_get_pixels( pixbuf ),
+ this->width, this->height,
+ gdk_pixbuf_get_rowstride( pixbuf ),
+ image, alpha );
+ }
+ else
+ {
+ // No alpha to extract
+ mlt_convert_rgb24_to_yuv422( gdk_pixbuf_get_pixels( pixbuf ),
+ this->width, this->height,
+ gdk_pixbuf_get_rowstride( pixbuf ),
+ image );
+ }
+
+ // Finished with pixbuf now
+ g_object_unref( pixbuf );
+
+ // Set width/height of frame
+ mlt_properties_set_int( properties, "width", this->width );
+ mlt_properties_set_int( properties, "height", this->height );
+
+ // if single picture, reference the image and alpha in the producer
+ this->image = image;
+ this->alpha = alpha;
+
+ // pass the image and alpha data without destructor
+ mlt_properties_set_data( properties, "image", image, 0, NULL, NULL );
+ mlt_properties_set_data( properties, "alpha", alpha, 0, NULL, NULL );
+
+ // Set alpha call back
+ ( *frame )->get_alpha_mask = producer_get_alpha_mask;
+
+ // Push the get_image method
+ mlt_frame_push_get_image( *frame, producer_get_image );
+ }
+
+ // Update timecode on the frame we're creating
+ mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) );
+
+ // Calculate the next timecode
+ mlt_producer_prepare_next( producer );
+
+ return 0;
+}
+
+static void producer_close( mlt_producer parent )
+{
+ producer_pango this = parent->child;
+ if ( this->markup )
+ free( this->markup );
+ if ( this->image )
+ free( this->image );
+ if ( this->alpha )
+ free( this->alpha );
+ parent->close = NULL;
+ mlt_producer_close( parent );
+ free( this );
+}
+
+static void pango_draw_background( GdkPixbuf *pixbuf, rgba_color bg )
+{
+ int ww = gdk_pixbuf_get_width( pixbuf );
+ int hh = gdk_pixbuf_get_height( pixbuf );
+ uint8_t *p = gdk_pixbuf_get_pixels( pixbuf );
+ int i, j;
+
+ for ( j = 0; j < hh; j++ )
+ {
+ for ( i = 0; i < ww; i++ )
+ {
+ *p++ = bg.r;
+ *p++ = bg.g;
+ *p++ = bg.b;
+ *p++ = bg.a;
+ }
+ }
+}
+
+static GdkPixbuf *pango_get_pixbuf( const char *markup, rgba_color fg, rgba_color bg, int pad, int align )
+{
+ PangoFT2FontMap *fontmap = (PangoFT2FontMap*) pango_ft2_font_map_new();
+ PangoContext *context = pango_ft2_font_map_create_context( fontmap );
+ PangoLayout *layout = pango_layout_new( context );
+// PangoFontDescription *font;
+ int w, h, x;
+ int i, j;
+ GdkPixbuf *pixbuf = NULL;
+ FT_Bitmap bitmap;
+ uint8_t *src = NULL;
+ uint8_t* dest = NULL;
+ int stride;
+
+ pango_ft2_font_map_set_resolution( fontmap, 72, 72 );
+ pango_layout_set_width( layout, -1 ); // set wrapping constraints
+// pango_layout_set_font_description( layout, "Sans 48" );
+// pango_layout_set_spacing( layout, space );
+ pango_layout_set_alignment( layout, ( PangoAlignment ) align );
+ pango_layout_set_markup( layout, markup, (markup == NULL ? 0 : strlen( markup ) ) );
+ pango_layout_get_pixel_size( layout, &w, &h );
+
+ pixbuf = gdk_pixbuf_new( GDK_COLORSPACE_RGB, TRUE /* has alpha */, 8, w + 2 * pad, h + 2 * pad );
+ pango_draw_background( pixbuf, bg );
+
+ stride = gdk_pixbuf_get_rowstride( pixbuf );
+
+ bitmap.width = w;
+ bitmap.pitch = 32 * ( ( w + 31 ) / 31 );
+ bitmap.rows = h;
+ bitmap.buffer = ( unsigned char * ) calloc( 1, h * bitmap.pitch );
+ bitmap.num_grays = 256;
+ bitmap.pixel_mode = ft_pixel_mode_grays;
+
+ pango_ft2_render_layout( &bitmap, layout, 0, 0 );
+
+ src = bitmap.buffer;
+ x = ( gdk_pixbuf_get_width( pixbuf ) - w - 2 * pad ) * align / 2 + pad;
+ dest = gdk_pixbuf_get_pixels( pixbuf ) + 4 * x + pad * stride;
+ for ( j = 0; j < h; j++ )
+ {
+ uint8_t *d = dest;
+ for ( i = 0; i < w; i++ )
+ {
+ float a = ( float ) bitmap.buffer[ j * bitmap.pitch + i ] / 255.0;
+ *d++ = ( int ) ( a * fg.r + ( 1 - a ) * bg.r );
+ *d++ = ( int ) ( a * fg.g + ( 1 - a ) * bg.g );
+ *d++ = ( int ) ( a * fg.b + ( 1 - a ) * bg.b );
+ *d++ = ( int ) ( a * fg.a + ( 1 - a ) * bg.a );
+ }
+ dest += stride;
+ }
+ free( bitmap.buffer );
+
+ g_object_unref( layout );
+ g_object_unref( context );
+ g_object_unref( fontmap );
+
+ return pixbuf;
+}
+
--- /dev/null
+/*
+ * producer_pango.h -- a pango-based titler
+ * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
+ * Author: Dan Dennedy <dan@dennedy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _PRODUCER_PANGO_H_
+#define _PRODUCER_PANGO_H_
+
+#include <framework/mlt_producer.h>
+
+typedef struct producer_pango_s *producer_pango;
+
+struct producer_pango_s
+{
+ struct mlt_producer_s parent;
+ char *markup;
+ int width;
+ int height;
+ uint8_t *image;
+ uint8_t *alpha;
+ int is_pal;
+};
+
+extern mlt_producer producer_pango_init( const char *markup );
+
+#endif
this->filename = strdup( filename );
this->counter = -1;
+ this->is_pal = 1;
g_type_init();
return producer;
return 0;
}
-uint8_t *producer_get_alpha_mask( mlt_frame this )
+static uint8_t *producer_get_alpha_mask( mlt_frame this )
{
// Obtain properties of frame
mlt_properties properties = mlt_frame_properties( this );
// If we have a pixbuf
if ( pixbuf )
{
+ // Scale to adjust for sample aspect ratio
+ if ( this->is_pal )
+ {
+ GdkPixbuf *temp = pixbuf;
+ GdkPixbuf *scaled = gdk_pixbuf_scale_simple( pixbuf,
+ (gint) ( (float) gdk_pixbuf_get_width( pixbuf ) * 54.0/59.0),
+ gdk_pixbuf_get_height( pixbuf ), GDK_INTERP_HYPER );
+ pixbuf = scaled;
+ g_object_unref( temp );
+ }
+ else
+ {
+ GdkPixbuf *temp = pixbuf;
+ GdkPixbuf *scaled = gdk_pixbuf_scale_simple( pixbuf,
+ (gint) ( (float) gdk_pixbuf_get_width( pixbuf ) * 11.0/10.0 ),
+ gdk_pixbuf_get_height( pixbuf ), GDK_INTERP_HYPER );
+ pixbuf = scaled;
+ g_object_unref( temp );
+ }
+
// Store width and height
this->width = gdk_pixbuf_get_width( pixbuf );
this->height = gdk_pixbuf_get_height( pixbuf );
int height;
uint8_t *image;
uint8_t *alpha;
+ int is_pal;
};
extern mlt_producer producer_pixbuf_init( const char *filename );
mlt_producer dv1 = mlt_factory_producer( "libdv", file1 );
//mlt_producer dv1 = producer_pixbuf_init( file1 );
//mlt_producer dv2 = producer_libdv_init( file2 );
- mlt_producer dv2 = mlt_factory_producer( "pixbuf", file2 );
+ //mlt_producer dv2 = mlt_factory_producer( "pixbuf", file2 );
+ mlt_producer dv2 = mlt_factory_producer( "pango", "<span font_desc=\"Sans Bold 24\">Mutton Lettuce Tomato</span>" );
// Register producers(s) with a multitrack object
mlt_multitrack multitrack = mlt_multitrack_init( );
*d++ = y1;
*d++ = (v0+v1) >> 1;
}
+ if ( width % 2 )
+ {
+ r = *s++;
+ g = *s++;
+ b = *s++;
+ *alpha++ = *s++;
+ RGB2YUV (r, g, b, y0, u0 , v0);
+ *d++ = y0;
+ *d++ = u0;
+ }
}
return ret;
}
*d++ = y1;
*d++ = (v0+v1) >> 1;
}
+ if ( width % 2 )
+ {
+ r = *s++;
+ g = *s++;
+ b = *s++;
+ RGB2YUV (r, g, b, y0, u0 , v0);
+ *d++ = y0;
+ *d++ = u0;
+ }
}
return ret;
}
TARGET = ../libmltgtk2.so
OBJS = factory.o \
- producer_pixbuf.o
+ producer_pixbuf.o \
+ producer_pango.o
-CFLAGS = `pkg-config gdk-pixbuf-2.0 --cflags` -I../../ -Wall -g -D_FILE_OFFSET_BITS=64 -pthread
+CFLAGS = `pkg-config gdk-pixbuf-2.0 --cflags` `pkg-config pangoft2 --cflags` -I../../ -Wall -g -D_FILE_OFFSET_BITS=64 -pthread
-LDFLAGS = `pkg-config gdk-pixbuf-2.0 --libs`
+LDFLAGS = `pkg-config gdk-pixbuf-2.0 --libs` `pkg-config pangoft2 --libs`
SRCS := $(OBJS:.o=.c)
#include <string.h>
#include "producer_pixbuf.h"
+#include "producer_pango.h"
void *mlt_create_producer( char *id, void *arg )
{
if ( !strcmp( id, "pixbuf" ) )
return producer_pixbuf_init( arg );
+ else if ( !strcmp( id, "pango" ) )
+ return producer_pango_init( arg );
return NULL;
}
--- /dev/null
+/*
+ * producer_pango.c -- a pango-based titler
+ * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
+ * Author: Dan Dennedy <dan@dennedy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "producer_pango.h"
+#include <framework/mlt_frame.h>
+#include <stdlib.h>
+#include <string.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <pango/pangoft2.h>
+#include <freetype/freetype.h>
+
+// special color type used by internal pango routines
+typedef struct
+{
+ uint8_t r, g, b, a;
+} rgba_color;
+
+// Forward declarations
+static int producer_get_frame( mlt_producer parent, mlt_frame_ptr frame, int index );
+static void producer_close( mlt_producer parent );
+static void pango_draw_background( GdkPixbuf *pixbuf, rgba_color bg );
+static GdkPixbuf *pango_get_pixbuf( const char *markup, rgba_color fg, rgba_color bg, int pad, int align );
+
+mlt_producer producer_pango_init( const char *markup )
+{
+ producer_pango this = calloc( sizeof( struct producer_pango_s ), 1 );
+ if ( this != NULL && mlt_producer_init( &this->parent, this ) == 0 )
+ {
+ mlt_producer producer = &this->parent;
+
+ producer->get_frame = producer_get_frame;
+ producer->close = producer_close;
+
+ this->markup = strdup( markup );
+ this->is_pal = 1;
+ g_type_init();
+
+ return producer;
+ }
+ free( this );
+ return NULL;
+}
+
+static int producer_get_image( mlt_frame this, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
+{
+ // Obtain properties of frame
+ mlt_properties properties = mlt_frame_properties( this );
+
+ // May need to know the size of the image to clone it
+ int size = 0;
+
+ // Get the image
+ uint8_t *image = mlt_properties_get_data( properties, "image", &size );
+
+ // Get width and height
+ *width = mlt_properties_get_int( properties, "width" );
+ *height = mlt_properties_get_int( properties, "height" );
+
+ // Clone if necessary
+ if ( writable )
+ {
+ // Clone our image
+ uint8_t *copy = malloc( size );
+ memcpy( copy, image, size );
+
+ // We're going to pass the copy on
+ image = copy;
+
+ // Now update properties so we free the copy after
+ mlt_properties_set_data( properties, "image", copy, size, free, NULL );
+ }
+
+ // Pass on the image
+ *buffer = image;
+
+ return 0;
+}
+
+static uint8_t *producer_get_alpha_mask( mlt_frame this )
+{
+ // Obtain properties of frame
+ mlt_properties properties = mlt_frame_properties( this );
+
+ // Return the alpha mask
+ return mlt_properties_get_data( properties, "alpha", NULL );
+}
+
+static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index )
+{
+ producer_pango this = producer->child;
+ GdkPixbuf *pixbuf = NULL;
+
+ // Generate a frame
+ *frame = mlt_frame_init( );
+
+ // Obtain properties of frame
+ mlt_properties properties = mlt_frame_properties( *frame );
+
+ // optimization for subsequent iterations on single picture
+ if ( this->image != NULL )
+ {
+ // Set width/height
+ mlt_properties_set_int( properties, "width", this->width );
+ mlt_properties_set_int( properties, "height", this->height );
+
+ // if picture sequence pass the image and alpha data without destructor
+ mlt_properties_set_data( properties, "image", this->image, 0, NULL, NULL );
+ mlt_properties_set_data( properties, "alpha", this->alpha, 0, NULL, NULL );
+
+ // Set alpha mask call back
+ ( *frame )->get_alpha_mask = producer_get_alpha_mask;
+
+ // Stack the get image callback
+ mlt_frame_push_get_image( *frame, producer_get_image );
+
+ }
+ else
+ {
+ // the following four will be replaced by properties
+ rgba_color fg = { 0xff, 0xff, 0xff, 0xff };
+ rgba_color bg = { 0, 0, 0, 0x7f };
+ int pad = 8;
+ int align = 0; /* left */
+
+ // Render the title
+ pixbuf = pango_get_pixbuf( this->markup, fg, bg, pad, align );
+ }
+
+ // If we have a pixbuf
+ if ( pixbuf )
+ {
+ // Scale to adjust for sample aspect ratio
+ if ( this->is_pal )
+ {
+ GdkPixbuf *temp = pixbuf;
+ GdkPixbuf *scaled = gdk_pixbuf_scale_simple( pixbuf,
+ (gint) ( (float) gdk_pixbuf_get_width( pixbuf ) * 54.0/59.0),
+ gdk_pixbuf_get_height( pixbuf ), GDK_INTERP_HYPER );
+ pixbuf = scaled;
+ g_object_unref( temp );
+ }
+ else
+ {
+ GdkPixbuf *temp = pixbuf;
+ GdkPixbuf *scaled = gdk_pixbuf_scale_simple( pixbuf,
+ (gint) ( (float) gdk_pixbuf_get_width( pixbuf ) * 11.0/10.0 ),
+ gdk_pixbuf_get_height( pixbuf ), GDK_INTERP_HYPER );
+ pixbuf = scaled;
+ g_object_unref( temp );
+ }
+
+ // Store width and height
+ this->width = gdk_pixbuf_get_width( pixbuf );
+ this->height = gdk_pixbuf_get_height( pixbuf );
+
+ // Allocate/define image and alpha
+ uint8_t *image = malloc( this->width * this->height * 2 );
+ uint8_t *alpha = NULL;
+
+ // Extract YUV422 and alpha
+ if ( gdk_pixbuf_get_has_alpha( pixbuf ) )
+ {
+ // Allocate the alpha mask
+ alpha = malloc( this->width * this->height );
+
+ // Convert the image
+ mlt_convert_rgb24a_to_yuv422( gdk_pixbuf_get_pixels( pixbuf ),
+ this->width, this->height,
+ gdk_pixbuf_get_rowstride( pixbuf ),
+ image, alpha );
+ }
+ else
+ {
+ // No alpha to extract
+ mlt_convert_rgb24_to_yuv422( gdk_pixbuf_get_pixels( pixbuf ),
+ this->width, this->height,
+ gdk_pixbuf_get_rowstride( pixbuf ),
+ image );
+ }
+
+ // Finished with pixbuf now
+ g_object_unref( pixbuf );
+
+ // Set width/height of frame
+ mlt_properties_set_int( properties, "width", this->width );
+ mlt_properties_set_int( properties, "height", this->height );
+
+ // if single picture, reference the image and alpha in the producer
+ this->image = image;
+ this->alpha = alpha;
+
+ // pass the image and alpha data without destructor
+ mlt_properties_set_data( properties, "image", image, 0, NULL, NULL );
+ mlt_properties_set_data( properties, "alpha", alpha, 0, NULL, NULL );
+
+ // Set alpha call back
+ ( *frame )->get_alpha_mask = producer_get_alpha_mask;
+
+ // Push the get_image method
+ mlt_frame_push_get_image( *frame, producer_get_image );
+ }
+
+ // Update timecode on the frame we're creating
+ mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) );
+
+ // Calculate the next timecode
+ mlt_producer_prepare_next( producer );
+
+ return 0;
+}
+
+static void producer_close( mlt_producer parent )
+{
+ producer_pango this = parent->child;
+ if ( this->markup )
+ free( this->markup );
+ if ( this->image )
+ free( this->image );
+ if ( this->alpha )
+ free( this->alpha );
+ parent->close = NULL;
+ mlt_producer_close( parent );
+ free( this );
+}
+
+static void pango_draw_background( GdkPixbuf *pixbuf, rgba_color bg )
+{
+ int ww = gdk_pixbuf_get_width( pixbuf );
+ int hh = gdk_pixbuf_get_height( pixbuf );
+ uint8_t *p = gdk_pixbuf_get_pixels( pixbuf );
+ int i, j;
+
+ for ( j = 0; j < hh; j++ )
+ {
+ for ( i = 0; i < ww; i++ )
+ {
+ *p++ = bg.r;
+ *p++ = bg.g;
+ *p++ = bg.b;
+ *p++ = bg.a;
+ }
+ }
+}
+
+static GdkPixbuf *pango_get_pixbuf( const char *markup, rgba_color fg, rgba_color bg, int pad, int align )
+{
+ PangoFT2FontMap *fontmap = (PangoFT2FontMap*) pango_ft2_font_map_new();
+ PangoContext *context = pango_ft2_font_map_create_context( fontmap );
+ PangoLayout *layout = pango_layout_new( context );
+// PangoFontDescription *font;
+ int w, h, x;
+ int i, j;
+ GdkPixbuf *pixbuf = NULL;
+ FT_Bitmap bitmap;
+ uint8_t *src = NULL;
+ uint8_t* dest = NULL;
+ int stride;
+
+ pango_ft2_font_map_set_resolution( fontmap, 72, 72 );
+ pango_layout_set_width( layout, -1 ); // set wrapping constraints
+// pango_layout_set_font_description( layout, "Sans 48" );
+// pango_layout_set_spacing( layout, space );
+ pango_layout_set_alignment( layout, ( PangoAlignment ) align );
+ pango_layout_set_markup( layout, markup, (markup == NULL ? 0 : strlen( markup ) ) );
+ pango_layout_get_pixel_size( layout, &w, &h );
+
+ pixbuf = gdk_pixbuf_new( GDK_COLORSPACE_RGB, TRUE /* has alpha */, 8, w + 2 * pad, h + 2 * pad );
+ pango_draw_background( pixbuf, bg );
+
+ stride = gdk_pixbuf_get_rowstride( pixbuf );
+
+ bitmap.width = w;
+ bitmap.pitch = 32 * ( ( w + 31 ) / 31 );
+ bitmap.rows = h;
+ bitmap.buffer = ( unsigned char * ) calloc( 1, h * bitmap.pitch );
+ bitmap.num_grays = 256;
+ bitmap.pixel_mode = ft_pixel_mode_grays;
+
+ pango_ft2_render_layout( &bitmap, layout, 0, 0 );
+
+ src = bitmap.buffer;
+ x = ( gdk_pixbuf_get_width( pixbuf ) - w - 2 * pad ) * align / 2 + pad;
+ dest = gdk_pixbuf_get_pixels( pixbuf ) + 4 * x + pad * stride;
+ for ( j = 0; j < h; j++ )
+ {
+ uint8_t *d = dest;
+ for ( i = 0; i < w; i++ )
+ {
+ float a = ( float ) bitmap.buffer[ j * bitmap.pitch + i ] / 255.0;
+ *d++ = ( int ) ( a * fg.r + ( 1 - a ) * bg.r );
+ *d++ = ( int ) ( a * fg.g + ( 1 - a ) * bg.g );
+ *d++ = ( int ) ( a * fg.b + ( 1 - a ) * bg.b );
+ *d++ = ( int ) ( a * fg.a + ( 1 - a ) * bg.a );
+ }
+ dest += stride;
+ }
+ free( bitmap.buffer );
+
+ g_object_unref( layout );
+ g_object_unref( context );
+ g_object_unref( fontmap );
+
+ return pixbuf;
+}
+
--- /dev/null
+/*
+ * producer_pango.h -- a pango-based titler
+ * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
+ * Author: Dan Dennedy <dan@dennedy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _PRODUCER_PANGO_H_
+#define _PRODUCER_PANGO_H_
+
+#include <framework/mlt_producer.h>
+
+typedef struct producer_pango_s *producer_pango;
+
+struct producer_pango_s
+{
+ struct mlt_producer_s parent;
+ char *markup;
+ int width;
+ int height;
+ uint8_t *image;
+ uint8_t *alpha;
+ int is_pal;
+};
+
+extern mlt_producer producer_pango_init( const char *markup );
+
+#endif
this->filename = strdup( filename );
this->counter = -1;
+ this->is_pal = 1;
g_type_init();
return producer;
return 0;
}
-uint8_t *producer_get_alpha_mask( mlt_frame this )
+static uint8_t *producer_get_alpha_mask( mlt_frame this )
{
// Obtain properties of frame
mlt_properties properties = mlt_frame_properties( this );
// If we have a pixbuf
if ( pixbuf )
{
+ // Scale to adjust for sample aspect ratio
+ if ( this->is_pal )
+ {
+ GdkPixbuf *temp = pixbuf;
+ GdkPixbuf *scaled = gdk_pixbuf_scale_simple( pixbuf,
+ (gint) ( (float) gdk_pixbuf_get_width( pixbuf ) * 54.0/59.0),
+ gdk_pixbuf_get_height( pixbuf ), GDK_INTERP_HYPER );
+ pixbuf = scaled;
+ g_object_unref( temp );
+ }
+ else
+ {
+ GdkPixbuf *temp = pixbuf;
+ GdkPixbuf *scaled = gdk_pixbuf_scale_simple( pixbuf,
+ (gint) ( (float) gdk_pixbuf_get_width( pixbuf ) * 11.0/10.0 ),
+ gdk_pixbuf_get_height( pixbuf ), GDK_INTERP_HYPER );
+ pixbuf = scaled;
+ g_object_unref( temp );
+ }
+
// Store width and height
this->width = gdk_pixbuf_get_width( pixbuf );
this->height = gdk_pixbuf_get_height( pixbuf );
int height;
uint8_t *image;
uint8_t *alpha;
+ int is_pal;
};
extern mlt_producer producer_pixbuf_init( const char *filename );
mlt_producer dv1 = mlt_factory_producer( "libdv", file1 );
//mlt_producer dv1 = producer_pixbuf_init( file1 );
//mlt_producer dv2 = producer_libdv_init( file2 );
- mlt_producer dv2 = mlt_factory_producer( "pixbuf", file2 );
+ //mlt_producer dv2 = mlt_factory_producer( "pixbuf", file2 );
+ mlt_producer dv2 = mlt_factory_producer( "pango", "<span font_desc=\"Sans Bold 24\">Mutton Lettuce Tomato</span>" );
// Register producers(s) with a multitrack object
mlt_multitrack multitrack = mlt_multitrack_init( );