lib/gifcomp.c

Go to the documentation of this file.
00001 /* comprs.c - LZW compression code for GIF */
00002 
00003 /*
00004  * ABSTRACT:
00005  *      The compression algorithm builds a string translation table that maps
00006  *      substrings from the input string into fixed-length codes.  These codes
00007  *      are used by the expansion algorithm to rebuild the compressor's table
00008  *      and reconstruct the original data stream.  In it's simplest form, the
00009  *      algorithm can be stated as:
00010  *
00011  *              "if <w>k is in the table, then <w> is in the table"
00012  *
00013  *      <w> is a code which represents a string in the table.  When a new
00014  *      character k is read in, the table is searched for <w>k.  If this
00015  *      combination is found, <w> is set to the code for that combination
00016  *      and the next character is read in.  Otherwise, this combination is
00017  *      added to the table, the code <w> is written to the output stream and
00018  *      <w> is set to k.
00019  *
00020  *      The expansion algorithm builds an identical table by parsing each
00021  *      received code into a prefix string and suffix character.  The suffix
00022  *      character is pushed onto the stack and the prefix string translated
00023  *      again until it is a single character.  This completes the expansion.
00024  *      The expanded code is then output by popping the stack and a new entry
00025  *      is made in the table.
00026  *
00027  *      The algorithm used here has one additional feature.  The output codes
00028  *      are variable length.  They start at a specified number of bits.  Once
00029  *      the number of codes exceeds the current code size, the number of bits
00030  *      in the code is incremented.  When the table is completely full, a
00031  *      clear code is transmitted for the expander and the table is reset.
00032  *      This program uses a maximum code size of 12 bits for a total of 4096
00033  *      codes.
00034  *
00035  *      The expander realizes that the code size is changing when it's table
00036  *      size reaches the maximum for the current code size.  At this point,
00037  *      the code size in increased.  Remember that the expander's table is
00038  *      identical to the compressor's table at any point in the original data
00039  *      stream.
00040  *
00041  *      The compressed data stream is structured as follows:
00042  *              first byte denoting the minimum code size
00043  *              one or more counted byte strings. The first byte contains the
00044  *              length of the string. A null string denotes "end of data"
00045  *
00046  *      This format permits a compressed data stream to be embedded within a
00047  *      non-compressed context.
00048  *
00049  * AUTHOR: Steve Wilhite
00050  *
00051  * REVISION HISTORY:
00052  *   Speed tweaked a bit by Jim Kent 8/29/88
00053  *
00054  */
00055 
00056 #include "common.h"
00057 #include <setjmp.h>
00058 
00059 static char const rcsid[] = "$Id: gifcomp.c,v 1.7 2003/05/21 21:03:22 kent Exp $";
00060 
00061 #define UBYTE unsigned char
00062 
00063 
00064 #define LARGEST_CODE    4095
00065 #define TABLE_SIZE      (8*1024)
00066 
00067 static UBYTE gif_byte_buff[256+3];               /* Current block */
00068 static FILE *gif_file;
00069 
00070 static unsigned char *gif_wpt;
00071 static long gif_wcount;
00072 
00073 static jmp_buf recover;
00074 
00075 static short *prior_codes;
00076 static short *code_ids;
00077 static unsigned char *added_chars;
00078 
00079 static short code_size;
00080 static short clear_code;
00081 static short eof_code;
00082 static short bit_offset;
00083 static short max_code;
00084 static short free_code;
00085 
00086 
00087 static void init_table(short min_code_size)
00088 {
00089 code_size = min_code_size + 1;
00090 clear_code = 1 << min_code_size;
00091 eof_code = clear_code + 1;
00092 free_code = clear_code + 2;
00093 max_code = 1 << code_size;
00094 
00095 zeroBytes(code_ids, TABLE_SIZE*sizeof(code_ids[0]));
00096 }
00097 
00098 
00099 static void flush(size_t n)
00100 {
00101 if (fputc(n,gif_file) < 0)
00102     {
00103     longjmp(recover, -3);
00104     }
00105 if (fwrite(gif_byte_buff, 1, n, gif_file) < n)
00106     {
00107     longjmp(recover, -3);
00108     }
00109 }
00110 
00111 
00112 static void write_code(short code)
00113 {
00114 long temp;
00115 register short byte_offset; 
00116 register short bits_left;
00117 
00118 byte_offset = bit_offset >> 3;
00119 bits_left = bit_offset & 7;
00120 
00121 if (byte_offset >= 254)
00122         {
00123         flush(byte_offset);
00124         gif_byte_buff[0] = gif_byte_buff[byte_offset];
00125         bit_offset = bits_left;
00126         byte_offset = 0;
00127         }
00128 
00129 if (bits_left > 0)
00130         {
00131         temp = ((long) code << bits_left) | gif_byte_buff[byte_offset];
00132         gif_byte_buff[byte_offset] = (UBYTE)temp;
00133         gif_byte_buff[byte_offset + 1] = (UBYTE)(temp >> 8);
00134         gif_byte_buff[byte_offset + 2] = (UBYTE)(temp >> 16);
00135         }
00136 else
00137         {
00138         gif_byte_buff[byte_offset] = (UBYTE)code;
00139         gif_byte_buff[byte_offset + 1] = (UBYTE)(code >> 8);
00140         }
00141 bit_offset += code_size;
00142 }
00143 
00144 
00145 /*
00146  * Function:
00147  *      Compress a stream of data bytes using the LZW algorithm.
00148  *
00149  * Inputs:
00150  *      min_code_size
00151  *              the field size of an input value.  Should be in the range from
00152  *              1 to 9.
00153  *
00154  * Returns:
00155  *       0      normal completion
00156  *      -1      (not used)
00157  *      -2      insufficient dynamic memory
00158  *      -3      bad "min_code_size"
00159  *      < -3    error status from either the get_byte or put_byte routine
00160  */
00161 static short compress_data(int min_code_size)
00162 {
00163 short status;
00164 short prefix_code;
00165 short d;
00166 register int hx;
00167 register short suffix_char;
00168 
00169 status = setjmp(recover);
00170 
00171 if (status != 0)
00172     {
00173     return status;
00174     }
00175 
00176 bit_offset = 0;
00177 init_table(min_code_size);
00178 write_code(clear_code);
00179 suffix_char = *gif_wpt++;
00180 gif_wcount -= 1;
00181 
00182 prefix_code = suffix_char;
00183 
00184 while (--gif_wcount >= 0)
00185     {
00186     suffix_char = *gif_wpt++;
00187     hx = prefix_code ^ suffix_char << 5;
00188     d = 1;
00189 
00190     for (;;)
00191         {
00192         if (code_ids[hx] == 0)
00193             {
00194             write_code(prefix_code);
00195 
00196             d = free_code;
00197 
00198             if (free_code <= LARGEST_CODE)
00199                 {
00200                 prior_codes[hx] = prefix_code;
00201                 added_chars[hx] = (UBYTE)suffix_char;
00202                 code_ids[hx] = free_code;
00203                 free_code++;
00204                 }
00205 
00206             if (d == max_code)
00207                 {
00208                 if (code_size < 12)
00209                     {
00210                     code_size++;
00211                     max_code <<= 1;
00212                     }
00213                 else
00214                     {
00215                     write_code(clear_code);
00216                     init_table(min_code_size);
00217                     }
00218                 }
00219 
00220             prefix_code = suffix_char;
00221             break;
00222             }
00223 
00224         if (prior_codes[hx] == prefix_code &&
00225                 added_chars[hx] == suffix_char)
00226             {
00227             prefix_code = code_ids[hx];
00228             break;
00229             }
00230 
00231         hx += d;
00232         d += 2;
00233         if (hx >= TABLE_SIZE)
00234             hx -= TABLE_SIZE;
00235         }
00236     }
00237 
00238 write_code(prefix_code);
00239 
00240 write_code(eof_code);
00241 
00242 
00243 /* Make sure the code buffer is flushed */
00244 
00245 if (bit_offset > 0)
00246     {
00247     int byte_offset = (bit_offset >> 3);
00248     if (byte_offset == 255)     /* Make sure we don't write a zero by mistake. */
00249         {
00250         int bits_left = bit_offset & 7;
00251         flush(255);
00252         if (bits_left)
00253             {
00254             gif_byte_buff[0] = gif_byte_buff[byte_offset];
00255             flush(1);
00256             }
00257         }
00258     else
00259         {
00260         flush((bit_offset + 7)/8);
00261         }
00262     }
00263 
00264 flush(0);                               /* end-of-data */
00265 return 0;
00266 }
00267 
00268 short gif_compress_data(int min_code_size, unsigned char *pt, long size, FILE *out)
00269 {
00270 int ret;
00271 
00272 /* Make sure min_code_size is reasonable. */
00273 if (min_code_size < 2 || min_code_size > 9)
00274     {
00275     if (min_code_size == 1)
00276         min_code_size = 2;
00277     else
00278         return -3;
00279     }
00280 
00281 /* Store input parameters where rest of routines can use. */
00282 gif_file = out;
00283 gif_wpt = pt;
00284 gif_wcount = size;
00285 
00286 ret = -2;       /* out of memory default */
00287 prior_codes = NULL;
00288 code_ids = NULL;
00289 added_chars = NULL;
00290 if ((prior_codes = (short*)needMem(TABLE_SIZE*sizeof(short))) == NULL)
00291         goto OUT;
00292 if ((code_ids = (short*)needMem(TABLE_SIZE*sizeof(short))) == NULL)
00293         goto OUT;
00294 if ((added_chars = (unsigned char*)needMem(TABLE_SIZE)) == NULL)
00295         goto OUT;
00296 
00297 ret = compress_data(min_code_size);
00298 
00299 OUT:
00300 gentleFree(prior_codes);
00301 gentleFree(code_ids);
00302 gentleFree(added_chars);
00303 return(ret);
00304 }
00305 

Generated on Tue Dec 25 18:39:31 2007 for blat by  doxygen 1.5.2