00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
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];
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
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
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
00244
00245 if (bit_offset > 0)
00246 {
00247 int byte_offset = (bit_offset >> 3);
00248 if (byte_offset == 255)
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);
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
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
00282 gif_file = out;
00283 gif_wpt = pt;
00284 gif_wcount = size;
00285
00286 ret = -2;
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