2 * producer_pgm.c -- PGM producer
3 * Copyright (C) 2005 Visual Media Fx Inc.
4 * Author: Charles Yates <charles.yates@gmail.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 #include "producer_pgm.h"
22 #include <framework/mlt_frame.h>
26 static int read_pgm( char *name
, uint8_t **image
, int *width
, int *height
, int *maxval
);
27 static int producer_get_frame( mlt_producer producer
, mlt_frame_ptr frame
, int index
);
28 static void producer_close( mlt_producer parent
);
30 mlt_producer
producer_pgm_init( void *resource
)
32 mlt_producer
this = NULL
;
33 uint8_t *image
= NULL
;
38 if ( read_pgm( resource
, &image
, &width
, &height
, &maxval
) == 0 )
40 this = calloc( 1, sizeof( struct mlt_producer_s
) );
41 if ( this != NULL
&& mlt_producer_init( this, NULL
) == 0 )
43 mlt_properties properties
= MLT_PRODUCER_PROPERTIES( this );
44 this->get_frame
= producer_get_frame
;
45 this->close
= ( mlt_destructor
)producer_close
;
46 mlt_properties_set( properties
, "resource", resource
);
47 mlt_properties_set_data( properties
, "image", image
, 0, mlt_pool_release
, NULL
);
48 mlt_properties_set_int( properties
, "real_width", width
);
49 mlt_properties_set_int( properties
, "real_height", height
);
53 mlt_pool_release( image
);
62 /** Load the PGM file.
65 static int read_pgm( char *name
, uint8_t **image
, int *width
, int *height
, int *maxval
)
67 uint8_t *input
= NULL
;
69 FILE *f
= fopen( name
, "r" );
79 if ( f
!= NULL
&& fgets( data
, 511, f
) != NULL
&& data
[ 0 ] == 'P' && data
[ 1 ] == '5' )
85 // PGM Header parser (probably needs to be strengthened)
86 for ( i
= 0; !error
&& i
< 3; i
++ )
88 if ( *p
!= '\0' && *p
!= '\n' )
89 val
= strtol( p
, &p
, 10 );
93 while ( error
== 0 && p
== NULL
)
95 if ( fgets( data
, 511, f
) == NULL
)
97 else if ( data
[ 0 ] != '#' )
98 val
= strtol( data
, &p
, 10 );
103 case 0: *width
= val
; break;
104 case 1: *height
= val
; break;
105 case 2: *maxval
= val
; break;
111 // Determine if this is one or two bytes per pixel
112 int bpp
= *maxval
> 255 ?
2 : 1;
113 int size
= *width
* *height
* bpp
;
116 // Allocate temporary storage for the data and the image
117 input
= mlt_pool_alloc( *width
* *height
* bpp
);
118 *image
= mlt_pool_alloc( *width
* *height
* sizeof( uint8_t ) * 2 );
121 error
= *image
== NULL
|| input
== NULL
;
126 error
= fread( input
, *width
* *height
* bpp
, 1, f
) != 1;
130 // Convert to yuv422 (very lossy - need to extend this to allow 16 bit alpha out)
131 for ( i
= 0; i
< size
; i
+= bpp
)
133 *p
++ = 16 + ( input
[ i
] * 219 ) / 255;
141 mlt_pool_release( *image
);
142 mlt_pool_release( input
);
155 static int producer_get_image( mlt_frame
this, uint8_t **buffer
, mlt_image_format
*format
, int *width
, int *height
, int writable
)
157 mlt_producer producer
= mlt_frame_pop_service( this );
158 int real_width
= mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "real_width" );
159 int real_height
= mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "real_height" );
160 int size
= real_width
* real_height
;
161 uint8_t *image
= mlt_pool_alloc( size
* 2 );
162 uint8_t *source
= mlt_properties_get_data( MLT_PRODUCER_PROPERTIES( producer
), "image", NULL
);
164 mlt_properties_set_data( MLT_FRAME_PROPERTIES( this ), "image", image
, size
* 2, mlt_pool_release
, NULL
);
167 *height
= real_height
;
168 *format
= mlt_image_yuv422
;
171 if ( image
!= NULL
&& source
!= NULL
)
172 memcpy( image
, source
, size
* 2 );
177 static int producer_get_frame( mlt_producer producer
, mlt_frame_ptr frame
, int index
)
179 // Construct a test frame
180 *frame
= mlt_frame_init( );
182 // Get the frames properties
183 mlt_properties properties
= MLT_FRAME_PROPERTIES( *frame
);
185 // Pass the data on the frame properties
186 mlt_properties_pass_list( properties
, MLT_PRODUCER_PROPERTIES( producer
), "real_width,real_height" );
187 mlt_properties_set_int( properties
, "has_image", 1 );
188 mlt_properties_set_int( properties
, "progressive", 1 );
189 mlt_properties_set_double( properties
, "aspect_ratio", 1 );
191 // Push the image callback
192 mlt_frame_push_service( *frame
, producer
);
193 mlt_frame_push_get_image( *frame
, producer_get_image
);
195 // Update timecode on the frame we're creating
196 mlt_frame_set_position( *frame
, mlt_producer_position( producer
) );
198 // Calculate the next timecode
199 mlt_producer_prepare_next( producer
);
204 static void producer_close( mlt_producer parent
)
206 parent
->close
= NULL
;
207 mlt_producer_close( parent
);