Ongoing GIF implementation

This commit is contained in:
2016-02-19 14:55:43 +01:00
parent 8074486a63
commit fb8bb0504c
3 changed files with 29 additions and 72 deletions

View File

@@ -81,6 +81,7 @@
<ItemGroup> <ItemGroup>
<ClCompile Include="bola.cpp" /> <ClCompile Include="bola.cpp" />
<ClCompile Include="engendro.cpp" /> <ClCompile Include="engendro.cpp" />
<ClCompile Include="gif.c" />
<ClCompile Include="jdraw8.cpp" /> <ClCompile Include="jdraw8.cpp" />
<ClCompile Include="jfile.cpp" /> <ClCompile Include="jfile.cpp" />
<ClCompile Include="jgame.cpp" /> <ClCompile Include="jgame.cpp" />

View File

@@ -60,6 +60,9 @@
<ClCompile Include="sprite.cpp"> <ClCompile Include="sprite.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="gif.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="bola.h"> <ClInclude Include="bola.h">

97
gif.c
View File

@@ -12,6 +12,7 @@
#define COMMENT_EXTENSION 0xFE #define COMMENT_EXTENSION 0xFE
#define PLAINTEXT_EXTENSION 0x01 #define PLAINTEXT_EXTENSION 0x01
#define READ(dst, size) memcpy(dst, buffer, size); buffer += size
typedef struct typedef struct
{ {
unsigned short width; 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 data_length;
int index; int index;
@@ -268,11 +269,7 @@ static int read_sub_blocks( FILE* gif_file, unsigned char **data )
while ( 1 ) while ( 1 )
{ {
if ( fread( &block_size, 1, 1, gif_file ) < 1 ) READ(&block_size, 1);
{
perror( "Invalid GIF file (too short): " );
return -1;
}
if ( block_size == 0 ) // end of sub-blocks 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 ); *data = realloc( *data, data_length );
// TODO this could be split across block size boundaries // TODO this could be split across block size boundaries
if ( fread( *data + index, 1, block_size, gif_file ) < READ(*data + index, block_size);
block_size )
{
perror( "Invalid GIF file (too short): " );
return -1;
}
index += block_size; index += block_size;
} }
@@ -296,7 +288,7 @@ static int read_sub_blocks( FILE* gif_file, unsigned char **data )
return data_length; return data_length;
} }
static int process_image_descriptor( FILE* gif_file, static int process_image_descriptor( unsigned char* buffer,
rgb *gct, rgb *gct,
int gct_size, int gct_size,
int resolution_bits ) int resolution_bits )
@@ -310,25 +302,15 @@ static int process_image_descriptor( FILE* gif_file,
//unsigned char *uncompressed_data = NULL; //unsigned char *uncompressed_data = NULL;
// TODO there could actually be lots of these // TODO there could actually be lots of these
if ( fread( &image_descriptor, 1, 9, gif_file ) < 9 ) READ(&image_descriptor, 9);
{
perror( "Invalid GIF file (too short)" );
disposition = 0;
goto done;
}
// TODO if LCT = true, read the LCT // TODO if LCT = true, read the LCT
disposition = 1; disposition = 1;
if ( fread( &lzw_code_size, 1, 1, gif_file ) < 1 ) READ(&lzw_code_size, 1);
{
perror( "Invalid GIF file (too short): " );
disposition = 0;
goto done;
}
compressed_data_length = read_sub_blocks( gif_file, &compressed_data ); compressed_data_length = read_sub_blocks( buffer, &compressed_data );
width = image_descriptor.image_width; width = image_descriptor.image_width;
height = image_descriptor.image_height; height = image_descriptor.image_height;
@@ -349,7 +331,7 @@ done:
return disposition; return disposition;
} }
static int process_extension( FILE* gif_file ) static int process_extension( unsigned char* buffer )
{ {
extension_t extension; extension_t extension;
graphic_control_extension_t gce; graphic_control_extension_t gce;
@@ -358,39 +340,23 @@ static int process_extension( FILE* gif_file )
unsigned char *extension_data = NULL; unsigned char *extension_data = NULL;
int extension_data_length; int extension_data_length;
if ( fread( &extension, 1, 2, gif_file ) < 2 ) READ(&extension, 2);
{
perror( "Invalid GIF file (too short): " );
return 0;
}
switch ( extension.extension_code ) switch ( extension.extension_code )
{ {
case GRAPHIC_CONTROL: case GRAPHIC_CONTROL:
if ( fread( &gce, 1, 4, gif_file ) < 4 ) READ(&gce, 4);
{
perror( "Invalid GIF file (too short): " );
return 0;
}
break; break;
case APPLICATION_EXTENSION: case APPLICATION_EXTENSION:
if ( fread( &application, 1, 11, gif_file ) < 11 ) READ(&application, 11);
{
perror( "Invalid GIF file (too short): " );
return 0;
}
break; break;
case 0xFE: case 0xFE:
// comment extension; do nothing - all the data is in the // comment extension; do nothing - all the data is in the
// sub-blocks that follow. // sub-blocks that follow.
break; break;
case 0x01: case 0x01:
if ( fread( &plaintext, 1, 12, gif_file ) < 12 ) READ(&plaintext, 12);
{
perror( "Invalid GIF file (too short): " );
return 0;
}
break; break;
default: default:
fprintf( stderr, "Unrecognized extension code.\n" ); 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 // All extensions are followed by data sub-blocks; even if it's
// just a single data sub-block of length 0 // 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 ) if ( extension_data != NULL )
free( extension_data ); 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 * GIF-encoded file. This should point to the first byte in
* the file when invoked. * 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 ]; unsigned char header[ 7 ];
screen_descriptor_t screen_descriptor; screen_descriptor_t screen_descriptor;
@@ -424,11 +390,7 @@ static void process_gif_stream( FILE* gif_file )
unsigned char block_type = 0x0; unsigned char block_type = 0x0;
// A GIF file starts with a Header (section 17) // A GIF file starts with a Header (section 17)
if ( fread( header, 1, 6, gif_file ) != 6 ) READ(header, 6);
{
perror( "Invalid GIF file (too short)" );
return;
}
header[ 6 ] = 0x0; header[ 6 ] = 0x0;
// XXX there's another format, GIF87a, that you may still find // 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; // Can't use sizeof here since GCC does byte alignment;
// sizeof( screen_descriptor_t ) = 8! // sizeof( screen_descriptor_t ) = 8!
if ( fread( &screen_descriptor, 1, 7, gif_file ) < 7 ) READ(&screen_descriptor, 7);
{
perror( "Invalid GIF file (too short)" );
return;
}
color_resolution_bits = ( ( screen_descriptor.fields & 0x70 ) >> 4 ) + 1; 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 ); global_color_table = ( rgb * ) malloc( 3 * global_color_table_size );
// XXX this could conceivably return a short count... // XXX this could conceivably return a short count...
if ( fread( global_color_table, 1, 3 * global_color_table_size, gif_file ) < READ(global_color_table, 3 * global_color_table_size);
3 * global_color_table_size )
{
perror( "Unable to read global color table" );
return;
}
} }
while ( block_type != TRAILER ) while ( block_type != TRAILER )
{ {
if ( fread( &block_type, 1, 1, gif_file ) < 1 ) READ(&block_type, 1);
{
perror( "Invalid GIF file (too short)" );
return;
}
switch ( block_type ) switch ( block_type )
{ {
case IMAGE_DESCRIPTOR: case IMAGE_DESCRIPTOR:
if ( !process_image_descriptor( gif_file, if ( !process_image_descriptor( buffer,
global_color_table, global_color_table,
global_color_table_size, global_color_table_size,
color_resolution_bits ) ) color_resolution_bits ) )
@@ -493,7 +442,7 @@ static void process_gif_stream( FILE* gif_file )
} }
break; break;
case EXTENSION_INTRODUCER: case EXTENSION_INTRODUCER:
if ( !process_extension( gif_file ) ) if ( !process_extension( buffer ) )
{ {
return; 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[] ) int main( int argc, char *argv[] )
{ {
FILE* gif_file; FILE* gif_file;