diff --git a/ChangeLog b/ChangeLog index 1771c325bb..9235365b37 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2003-07-29 Dave Neary + + * plug-ins/common/gif.c: Include a patch by Cameron Gergory + which allows a compile-time choice of the + comression algorithm to be used in the gif plug-in. + + * configure.in: Added --with-gif-compress flag to allow + specification of compression algorithm via configure. + 2003-07-28 Helvetix Victorinox * app/composite/Makefile.am: diff --git a/configure.in b/configure.in index 6cfbeacadb..4f5aef6077 100644 --- a/configure.in +++ b/configure.in @@ -830,6 +830,26 @@ AC_SUBST(MNG) AC_SUBST(LIBMNG) +############################################################ +# GIF compression: Allow builder to specify at compile time +# which compression style she wants to use for gifs. The default +# is LZW. The flag is --with-gif-compression=[lzw|rle|none] +# LZW: Unisys patented Lempel-Ziff encoding. +# RLE: Simple runlenght encoding - produces files about twice as +# big as the LZW compressed equivalent +# None: Raw data. +############################################################ + +AC_ARG_WITH(gif-compression, + [ --with-gif-compression=lzw|rle|none Default: lzw]) + +if test x$with_gif_compression = xnone; then + AC_DEFINE(GIF_UN, 1, [Defined when we will use no compression for GIFs]) +elif test x$with_gif_compression = xrle; then + AC_DEFINE(GIF_RLE, 1, [Defined when we will use RLE to compress GIFs]) +fi + + ############################################################ # libexif: Library to allow exif tags to be read from, and # saved to, jpeg files. Currently, this permits exif data to diff --git a/plug-ins/common/gif.c b/plug-ins/common/gif.c index d88e5521de..9ca54ec99a 100644 --- a/plug-ins/common/gif.c +++ b/plug-ins/common/gif.c @@ -38,6 +38,11 @@ * would usually entail writing a somewhat larger image file. * + major version bump to indicate 1.3/1.4 branch. * + * 2002/04/24 - Cameron Gregory, http://www.flamingtext.com/ + * Added no compress option + * Added rlecompress(). 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. @@ -281,6 +286,15 @@ #include "libgimp/stdplugins-intl.h" +/* Define only one of these to determine which kind of gif's you would like. + * GIF_UN means use uncompressed gifs. These will be large, but no + * patent problems. + * GIF_RLE uses Run-length-encoding, which should not be covered by the + * patent, but this is not legal advice. + */ +/* #define GIF_UN */ +/* #define GIF_RLE */ + /* uncomment the line below for a little debugging info */ /* #define GIFDEBUG yesplease */ @@ -625,6 +639,15 @@ int max_progress; static void Putword (int, FILE *); static void compress (int, FILE *, ifunptr); +#ifdef GIF_UN +static void nocompress (int, FILE *, ifunptr); +#else +#ifdef GIF_RLE +static void rlecompress (int, FILE *, ifunptr); +#else +static void normalcompress (int, FILE *, ifunptr); +#endif +#endif static void output (code_int); static void cl_block (void); static void cl_hash (count_int); @@ -2142,12 +2165,28 @@ static void compress (int init_bits, FILE *outfile, ifunptr ReadValue) +{ +#ifdef GIF_UN + nocompress(init_bits, outfile, ReadValue); +#else +#ifdef GIF_RLE + rlecompress(init_bits, outfile, ReadValue); +#else + normalcompress(init_bits, outfile, ReadValue); +#endif +#endif +} + +#ifdef GIF_UN +static void +nocompress (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 disp; register code_int hsize_reg; register int hshift; @@ -2196,6 +2235,229 @@ compress (int init_bits, 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); +} +#else +#ifdef GIF_RLE + +static void +rlecompress (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); +} + +#else + +static void +normalcompress (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 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 (); + + 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) { @@ -2247,6 +2509,7 @@ compress (int init_bits, else cl_block (); } + /* * Put out the final code. */ @@ -2254,6 +2517,10 @@ compress (int init_bits, ++out_count; output ((code_int) EOFCode); } +#endif +#endif + + /***************************************************************** * TAG( output )