/***************************************************************************** VGLGIF.C vglGif( char* file, char far* buffer, char far* palette, int* width, int* height ); Routine to load a 256 color .GIF file into a memory buffer. *Only* 256 color images are supported here! Sorry, no routines to SAVE .GIFs... Memory required is allocated on the fly and no checks are in place. If you don't have enough memory it will likely crash. It's easy to add the checks yourself, just put one after each call to malloc(). If you supply a pointer to a palette, it will be filled in. If you supply a pointer to a width and/or height variable, it will be filled in as well. Mark Morley morley@camosun.bc.ca *****************************************************************************/ #include #define MAX_CODES 4096 static FILE* fp; static int curr_size; static int clear; static int ending; static int newcodes; static int top_slot; static int slot; static int navail_bytes = 0; static int nbits_left = 0; static unsigned char b1; static unsigned char byte_buff[257]; static unsigned char* pbytes; static unsigned char* stack; static unsigned char* suffix; static unsigned int* prefix; static unsigned long code_mask[13] = { 0L, 0x0001L, 0x0003L, 0x0007L, 0x000FL, 0x001FL, 0x003FL, 0x007FL, 0x00FFL, 0x01FFL, 0x03FFL, 0x07FFL, 0x0FFFL }; static int pascal get_next_code() { register int i; static unsigned long ret; if( ! nbits_left ) { if( navail_bytes <= 0 ) { pbytes = byte_buff; navail_bytes = getc( fp ); if( navail_bytes ) for( i = 0; i < navail_bytes; ++i ) *(byte_buff + i) = getc( fp ); } b1 = *pbytes++; nbits_left = 8; --navail_bytes; } ret = b1 >> (8 - nbits_left); while( curr_size > nbits_left ) { if( navail_bytes <= 0 ) { pbytes = byte_buff; navail_bytes = getc( fp ); if( navail_bytes ) for( i = 0; i < navail_bytes; ++i ) *(byte_buff + i) = getc( fp ); } b1 = *pbytes++; ret |= b1 << nbits_left; nbits_left += 8; --navail_bytes; } nbits_left -= curr_size; return( (int) (ret & *(code_mask + curr_size)) ); } vglGif( char* file, char far* buffer, char far* pal, int* width, int* height ) { unsigned char* sp; int code, fc, oc; int i; unsigned char size; int c; unsigned char buf[1028]; unsigned char red; unsigned char grn; unsigned char blu; fp = fopen( file, "rb" ); if( !fp ) return( 0 ); fread( buf, 1, 6, fp ); if( strncmp( buf, "GIF", 3 ) ) { fclose( fp ); return( 0 ); } fread( buf, 1, 7, fp ); for( i = 0; i < 768; ) { red = getc( fp ); grn = getc( fp ); blu = getc( fp ); if( pal ) { pal[i++] = red >> 2; pal[i++] = grn >> 2; pal[i++] = blu >> 2; } else i += 3; } fread( buf, 1, 5, fp ); i = getw( fp ); if( width ) *width = i; i = getw( fp ); if( height ) *height = i; if( !buffer ) return( 1 ); fread( buf, 1, 1, fp ); size = getc( fp ); if( size < 2 || 9 < size ) { fclose( fp ); return( 0 ); } stack = (unsigned char*) malloc( MAX_CODES + 1 ); suffix = (unsigned char*) malloc( MAX_CODES + 1 ); prefix = (unsigned int*) malloc( sizeof(int) * (MAX_CODES + 1) ); curr_size = size + 1; top_slot = 1 << curr_size; clear = 1 << size; ending = clear + 1; slot = newcodes = ending + 1; navail_bytes = nbits_left = 0; oc = fc = 0; sp = stack; while( (c = get_next_code()) != ending ) { if( c == clear ) { curr_size = size + 1; slot = newcodes; top_slot = 1 << curr_size; while( (c = get_next_code()) == clear ); if( c == ending ) break; if( c >= slot ) c = 0; oc = fc = c; *buffer++ = c; } else { code = c; if( code >= slot ) { code = oc; *sp++ = fc; } while( code >= newcodes ) { *sp++ = *(suffix + code); code = *(prefix + code); } *sp++ = code; if( slot < top_slot ) { *(suffix + slot) = fc = code; *(prefix + slot++) = oc; oc = c; } if( slot >= top_slot && curr_size < 12 ) { top_slot <<= 1; ++curr_size; } while( sp > stack ) { --sp; *buffer++ = *sp; } } } free( stack ); free( suffix ); free( prefix ); fclose( fp ); return( 1 ); }