From fb8bb0504cfd470905f38ed04cfe35782e58af96 Mon Sep 17 00:00:00 2001 From: Raimon Zamora Date: Fri, 19 Feb 2016 14:55:43 +0100 Subject: [PATCH] Ongoing GIF implementation --- aee.vcxproj | 1 + aee.vcxproj.filters | 3 ++ gif.c | 97 ++++++++++++--------------------------------- 3 files changed, 29 insertions(+), 72 deletions(-) diff --git a/aee.vcxproj b/aee.vcxproj index 549621d..1e11a08 100644 --- a/aee.vcxproj +++ b/aee.vcxproj @@ -81,6 +81,7 @@ + diff --git a/aee.vcxproj.filters b/aee.vcxproj.filters index 7d396fe..31f9f9c 100644 --- a/aee.vcxproj.filters +++ b/aee.vcxproj.filters @@ -60,6 +60,9 @@ Source Files + + Source Files + diff --git a/gif.c b/gif.c index 061feae..b2ee826 100644 --- a/gif.c +++ b/gif.c @@ -12,6 +12,7 @@ #define COMMENT_EXTENSION 0xFE #define PLAINTEXT_EXTENSION 0x01 +#define READ(dst, size) memcpy(dst, buffer, size); buffer += size typedef struct { unsigned short width; @@ -254,7 +255,7 @@ void uncompress( int code_length, } } -static int read_sub_blocks( FILE* gif_file, unsigned char **data ) +static int read_sub_blocks( unsigned char* buffer, unsigned char **data ) { int data_length; int index; @@ -268,11 +269,7 @@ static int read_sub_blocks( FILE* gif_file, unsigned char **data ) while ( 1 ) { - if ( fread( &block_size, 1, 1, gif_file ) < 1 ) - { - perror( "Invalid GIF file (too short): " ); - return -1; - } + READ(&block_size, 1); if ( block_size == 0 ) // end of sub-blocks { @@ -283,12 +280,7 @@ static int read_sub_blocks( FILE* gif_file, unsigned char **data ) *data = realloc( *data, data_length ); // TODO this could be split across block size boundaries - if ( fread( *data + index, 1, block_size, gif_file ) < - block_size ) - { - perror( "Invalid GIF file (too short): " ); - return -1; - } + READ(*data + index, block_size); index += block_size; } @@ -296,7 +288,7 @@ static int read_sub_blocks( FILE* gif_file, unsigned char **data ) return data_length; } -static int process_image_descriptor( FILE* gif_file, +static int process_image_descriptor( unsigned char* buffer, rgb *gct, int gct_size, int resolution_bits ) @@ -310,25 +302,15 @@ static int process_image_descriptor( FILE* gif_file, //unsigned char *uncompressed_data = NULL; // TODO there could actually be lots of these - if ( fread( &image_descriptor, 1, 9, gif_file ) < 9 ) - { - perror( "Invalid GIF file (too short)" ); - disposition = 0; - goto done; - } + READ(&image_descriptor, 9); // TODO if LCT = true, read the LCT disposition = 1; - if ( fread( &lzw_code_size, 1, 1, gif_file ) < 1 ) - { - perror( "Invalid GIF file (too short): " ); - disposition = 0; - goto done; - } + READ(&lzw_code_size, 1); - compressed_data_length = read_sub_blocks( gif_file, &compressed_data ); + compressed_data_length = read_sub_blocks( buffer, &compressed_data ); width = image_descriptor.image_width; height = image_descriptor.image_height; @@ -349,7 +331,7 @@ done: return disposition; } -static int process_extension( FILE* gif_file ) +static int process_extension( unsigned char* buffer ) { extension_t extension; graphic_control_extension_t gce; @@ -358,39 +340,23 @@ static int process_extension( FILE* gif_file ) unsigned char *extension_data = NULL; int extension_data_length; - if ( fread( &extension, 1, 2, gif_file ) < 2 ) - { - perror( "Invalid GIF file (too short): " ); - return 0; - } + READ(&extension, 2); switch ( extension.extension_code ) { case GRAPHIC_CONTROL: - if ( fread( &gce, 1, 4, gif_file ) < 4 ) - { - perror( "Invalid GIF file (too short): " ); - return 0; - } + READ(&gce, 4); break; case APPLICATION_EXTENSION: - if ( fread( &application, 1, 11, gif_file ) < 11 ) - { - perror( "Invalid GIF file (too short): " ); - return 0; - } + READ(&application, 11); break; case 0xFE: // comment extension; do nothing - all the data is in the // sub-blocks that follow. break; case 0x01: - if ( fread( &plaintext, 1, 12, gif_file ) < 12 ) - { - perror( "Invalid GIF file (too short): " ); - return 0; - } + READ(&plaintext, 12); break; default: fprintf( stderr, "Unrecognized extension code.\n" ); @@ -399,7 +365,7 @@ static int process_extension( FILE* gif_file ) // All extensions are followed by data sub-blocks; even if it's // just a single data sub-block of length 0 - extension_data_length = read_sub_blocks( gif_file, &extension_data ); + extension_data_length = read_sub_blocks( buffer, &extension_data ); if ( extension_data != NULL ) free( extension_data ); @@ -412,7 +378,7 @@ static int process_extension( FILE* gif_file ) * GIF-encoded file. This should point to the first byte in * the file when invoked. */ -static void process_gif_stream( FILE* gif_file ) +static unsigned char* process_gif_stream(unsigned char *buffer, unsigned short* w, unsigned short* h) { unsigned char header[ 7 ]; screen_descriptor_t screen_descriptor; @@ -424,11 +390,7 @@ static void process_gif_stream( FILE* gif_file ) unsigned char block_type = 0x0; // A GIF file starts with a Header (section 17) - if ( fread( header, 1, 6, gif_file ) != 6 ) - { - perror( "Invalid GIF file (too short)" ); - return; - } + READ(header, 6); header[ 6 ] = 0x0; // XXX there's another format, GIF87a, that you may still find @@ -447,11 +409,7 @@ static void process_gif_stream( FILE* gif_file ) // Can't use sizeof here since GCC does byte alignment; // sizeof( screen_descriptor_t ) = 8! - if ( fread( &screen_descriptor, 1, 7, gif_file ) < 7 ) - { - perror( "Invalid GIF file (too short)" ); - return; - } + READ(&screen_descriptor, 7); color_resolution_bits = ( ( screen_descriptor.fields & 0x70 ) >> 4 ) + 1; @@ -465,26 +423,17 @@ static void process_gif_stream( FILE* gif_file ) global_color_table = ( rgb * ) malloc( 3 * global_color_table_size ); // XXX this could conceivably return a short count... - if ( fread( global_color_table, 1, 3 * global_color_table_size, gif_file ) < - 3 * global_color_table_size ) - { - perror( "Unable to read global color table" ); - return; - } + READ(global_color_table, 3 * global_color_table_size); } while ( block_type != TRAILER ) { - if ( fread( &block_type, 1, 1, gif_file ) < 1 ) - { - perror( "Invalid GIF file (too short)" ); - return; - } + READ(&block_type, 1); switch ( block_type ) { case IMAGE_DESCRIPTOR: - if ( !process_image_descriptor( gif_file, + if ( !process_image_descriptor( buffer, global_color_table, global_color_table_size, color_resolution_bits ) ) @@ -493,7 +442,7 @@ static void process_gif_stream( FILE* gif_file ) } break; case EXTENSION_INTRODUCER: - if ( !process_extension( gif_file ) ) + if ( !process_extension( buffer ) ) { return; } @@ -509,6 +458,10 @@ static void process_gif_stream( FILE* gif_file ) } +unsigned char* LoadGif(unsigned char *buffer, unsigned short* w, unsigned short* h) { + return process_gif_stream(buffer, w, h); +} + int main( int argc, char *argv[] ) { FILE* gif_file;