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>
<ClCompile Include="bola.cpp" />
<ClCompile Include="engendro.cpp" />
<ClCompile Include="gif.c" />
<ClCompile Include="jdraw8.cpp" />
<ClCompile Include="jfile.cpp" />
<ClCompile Include="jgame.cpp" />

View File

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

97
gif.c
View File

@@ -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;