*** gif.c.orig Fri May 24 13:05:42 2002 --- gif.c Mon May 27 01:17:16 2002 *************** *** 23,28 **** --- 23,38 ---- /* * REVISION HISTORY * + * 2002/04/27 - Cameron Gregory, http://www.flamingtext.com/ + * Added GUI options and compile time options to compile in/out + * RLE/LZW. None, is now in always. + * It's important for people to be able to compile out LWZ/RLE. + * + * 2002/04/24 - Cameron Gregory, http://www.flamingtext.com/ + * Added no_compress() option. + * Added rle_compress(). Should not be covered by lzw patent, + * but this is not legal advice. + * * 99/04/25 * 3.00.02 - Save the comment back onto the image as a persistent * parasite if the comment was edited. *************** *** 276,281 **** --- 286,298 ---- #include "libgimp/stdplugins-intl.h" + /* Define either of these to remove the LZW and/or RLE code. + * Uncompressed GIF's are always compiled in. + * If you define these below, they are removed from the options. + */ + /* #define GIF_NO_LZW */ + /* #define GIF_NO_RLE */ + /* uncomment the line below for a little debugging info */ /* #define GIFDEBUG yesplease */ *************** *** 294,299 **** --- 311,323 ---- DISPOSE_REPLACE }; + enum + { + ENCODE_LZW, + ENCODE_RLE, + ENCODE_NONE + }; + typedef struct { gint interlace; *************** *** 301,306 **** --- 325,331 ---- gint loop; gint default_delay; gint default_dispose; + gint encoding; } GIFSaveVals; typedef struct *************** *** 360,366 **** TRUE, /* save comment */ TRUE, /* loop infinitely */ 100, /* default_delay between frames (100ms) */ ! 0 /* default_dispose = "don't care" */ }; static GIFSaveInterface gsint = --- 385,401 ---- TRUE, /* save comment */ TRUE, /* loop infinitely */ 100, /* default_delay between frames (100ms) */ ! 0, /* default_dispose = "don't care" */ ! /* encoding 0=LZW, 1=RLE, 2=NONE */ ! #ifdef GIF_NO_LZW ! #ifdef GIF_NO_RLE ! ENCODE_NONE ! #else ! ENCODE_RLE ! #endif ! #else ! ENCODE_LZW ! #endif }; static GIFSaveInterface gsint = *************** *** 622,627 **** --- 657,669 ---- static void Putword (int, FILE *); static void compress (int, FILE *, ifunptr); + static void no_compress (int, FILE *, ifunptr); + #ifndef GIF_NO_RLE + static void rle_compress (int, FILE *, ifunptr); + #endif + #ifndef GIF_NO_LZW + static void lzw_compress (int, FILE *, ifunptr); + #endif static void output (code_int); static void cl_block (void); static void cl_hash (count_int); *************** *** 1200,1205 **** --- 1242,1248 ---- GtkWidget *vbox; GtkWidget *hbox; GtkWidget *disposal_option_menu; + GtkWidget *encoding_option_menu; GtkWidget *com_table; GtkWidget *vscrollbar; #ifdef FACEHUGGERS *************** *** 1249,1254 **** --- 1292,1328 ---- gtk_widget_show (toggle); hbox = gtk_hbox_new (FALSE, 4); + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + label = gtk_label_new (_("Encoding: ")); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_widget_show (label); + gtk_widget_show (hbox); + + encoding_option_menu = + gimp_option_menu_new2 (FALSE, gimp_menu_item_update, + &gsvals.encoding, + (gpointer) gsvals.encoding, + + /* REALLY: This should be "set_sensitve" false, but I don't know how :) */ + #ifndef GIF_NO_LZW + _("LZW"), + (gpointer) ENCODE_LZW, NULL, + #endif + #ifndef GIF_NO_RLE + _("RLE"), + (gpointer) ENCODE_RLE, NULL, + #endif + _("None"), + (gpointer) ENCODE_NONE, NULL, + + NULL); + gtk_box_pack_start (GTK_BOX (hbox), encoding_option_menu, FALSE, FALSE, 0); + gtk_widget_show (encoding_option_menu); + + gtk_widget_show (hbox); + + + hbox = gtk_hbox_new (FALSE, 4); gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0); toggle = gtk_check_button_new_with_label (_("GIF Comment:")); *************** *** 1372,1378 **** NULL); gtk_box_pack_start (GTK_BOX (hbox), disposal_option_menu, FALSE, FALSE, 0); gtk_widget_show (disposal_option_menu); - gtk_widget_show (hbox); gtk_widget_show (vbox); --- 1446,1451 ---- *************** *** 2098,2108 **** --- 2171,2428 ---- 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF}; + /* If an option isn't compiled in, it will drop down to the next level */ + static void compress (int init_bits, FILE *outfile, ifunptr ReadValue) { + switch (gsvals.encoding) { + case ENCODE_LZW: + #ifndef GIF_NO_LZW + lzw_compress(init_bits, outfile, ReadValue); + break; + #endif + case ENCODE_RLE: + #ifndef GIF_NO_RLE + rle_compress(init_bits, outfile, ReadValue); + break; + #endif + case ENCODE_NONE: + default: + no_compress(init_bits, outfile, ReadValue); + break; + } + } + + static void + no_compress (int init_bits, + FILE *outfile, + ifunptr ReadValue) + { + register long fcode; + register code_int i /* = 0 */ ; + register int c; + register code_int ent; + register code_int hsize_reg; + register int hshift; + + + /* + * Set up the globals: g_init_bits - initial number of bits + * g_outfile - pointer to output file + */ + g_init_bits = init_bits; + g_outfile = outfile; + + cur_bits = 0; + cur_accum = 0; + + /* + * Set up the necessary values + */ + offset = 0; + out_count = 0; + clear_flg = 0; + in_count = 1; + + ClearCode = (1 << (init_bits - 1)); + EOFCode = ClearCode + 1; + free_ent = ClearCode + 2; + + + /* Had some problems here... should be okay now. --Adam */ + n_bits = g_init_bits; + maxcode = MAXCODE (n_bits); + + + + char_init (); + + ent = GIFNextPixel (ReadValue); + + hshift = 0; + for (fcode = (long) hsize; fcode < 65536L; fcode *= 2L) + ++hshift; + hshift = 8 - hshift; /* set hash code range bound */ + + hsize_reg = hsize; + cl_hash ((count_int) hsize_reg); /* clear hash table */ + + output ((code_int) ClearCode); + + + #ifdef SIGNED_COMPARE_SLOW + while ((c = GIFNextPixel (ReadValue)) != (unsigned) EOF) + { + #else /*SIGNED_COMPARE_SLOW */ + while ((c = GIFNextPixel (ReadValue)) != EOF) + { /* } */ + #endif /*SIGNED_COMPARE_SLOW */ + + ++in_count; + + fcode = (long) (((long) c << maxbits) + ent); + i = (((code_int) c << hshift) ^ ent); /* xor hashing */ + + output ((code_int) ent); + ++out_count; + ent = c; + #ifdef SIGNED_COMPARE_SLOW + if ((unsigned) free_ent < (unsigned) maxmaxcode) + { + #else /*SIGNED_COMPARE_SLOW */ + if (free_ent < maxmaxcode) + { /* } */ + #endif /*SIGNED_COMPARE_SLOW */ + CodeTabOf (i) = free_ent++; /* code -> hashtable */ + HashTabOf (i) = fcode; + } + else + cl_block (); + } + + /* + * Put out the final code. + */ + output ((code_int) ent); + ++out_count; + output ((code_int) EOFCode); + } + + #ifndef GIF_NO_RLE + + static void + rle_compress (int init_bits, + FILE *outfile, + ifunptr ReadValue) + { + register long fcode; + register code_int i /* = 0 */ ; + register int c, last; + register code_int ent; + register code_int disp; + register code_int hsize_reg; + register int hshift; + + + /* + * Set up the globals: g_init_bits - initial number of bits + * g_outfile - pointer to output file + */ + g_init_bits = init_bits; + g_outfile = outfile; + + cur_bits = 0; + cur_accum = 0; + + /* + * Set up the necessary values + */ + offset = 0; + out_count = 0; + clear_flg = 0; + in_count = 1; + + ClearCode = (1 << (init_bits - 1)); + EOFCode = ClearCode + 1; + free_ent = ClearCode + 2; + + + /* Had some problems here... should be okay now. --Adam */ + n_bits = g_init_bits; + maxcode = MAXCODE (n_bits); + + + + char_init (); + + last = ent = GIFNextPixel (ReadValue); + + hshift = 0; + for (fcode = (long) hsize; fcode < 65536L; fcode *= 2L) + ++hshift; + hshift = 8 - hshift; /* set hash code range bound */ + + hsize_reg = hsize; + cl_hash ((count_int) hsize_reg); /* clear hash table */ + + output ((code_int) ClearCode); + + + + #ifdef SIGNED_COMPARE_SLOW + while ((c = GIFNextPixel (ReadValue)) != (unsigned) EOF) + { + #else /*SIGNED_COMPARE_SLOW */ + while ((c = GIFNextPixel (ReadValue)) != EOF) + { /* } */ + #endif /*SIGNED_COMPARE_SLOW */ + + ++in_count; + + fcode = (long) (((long) c << maxbits) + ent); + i = (((code_int) c << hshift) ^ ent); /* xor hashing */ + + + if (last == c) { + if (HashTabOf (i) == fcode) + { + ent = CodeTabOf (i); + continue; + } + else if ((long) HashTabOf (i) < 0) /* empty slot */ + goto nomatch; + disp = hsize_reg - i; /* secondary hash (after G. Knott) */ + if (i == 0) + disp = 1; + probe: + if ((i -= disp) < 0) + i += hsize_reg; + + if (HashTabOf (i) == fcode) + { + ent = CodeTabOf (i); + continue; + } + if ((long) HashTabOf (i) > 0) + goto probe; + } + nomatch: + output ((code_int) ent); + ++out_count; + last = ent = c; + #ifdef SIGNED_COMPARE_SLOW + if ((unsigned) free_ent < (unsigned) maxmaxcode) + { + #else /*SIGNED_COMPARE_SLOW */ + if (free_ent < maxmaxcode) + { /* } */ + #endif /*SIGNED_COMPARE_SLOW */ + CodeTabOf (i) = free_ent++; /* code -> hashtable */ + HashTabOf (i) = fcode; + } + else + cl_block (); + } + + /* + * Put out the final code. + */ + output ((code_int) ent); + ++out_count; + output ((code_int) EOFCode); + } + #endif + + #ifndef GIF_NO_LZW + + static void + lzw_compress (int init_bits, + FILE *outfile, + ifunptr ReadValue) + { register long fcode; register code_int i /* = 0 */ ; register int c; *************** *** 2156,2161 **** --- 2476,2482 ---- output ((code_int) ClearCode); + #ifdef SIGNED_COMPARE_SLOW while ((c = GIFNextPixel (ReadValue)) != (unsigned) EOF) { *************** *** 2207,2212 **** --- 2528,2534 ---- else cl_block (); } + /* * Put out the final code. */ *************** *** 2214,2219 **** --- 2536,2544 ---- ++out_count; output ((code_int) EOFCode); } + #endif + + /***************************************************************** * TAG( output )