diff --git a/Graphics/gl2gif.cpp b/Graphics/gl2gif.cpp
index a83d130b6b2aada30301c5483394c86b276b990a..c17cecbb3fadb78655ac9acbabdba61f0a6dcacd 100644
--- a/Graphics/gl2gif.cpp
+++ b/Graphics/gl2gif.cpp
@@ -1,1066 +1,1408 @@
-/*
-  This file is a big hack from
-
-  The GIFLIB distribution is Copyright (c) 1997  Eric S. Raymond
-
+/* $Id: gl2gif.cpp,v 1.5 2000-12-28 18:57:05 geuzaine Exp $ */
+/* 
+ * gl2gif: an OpenGL to GIF printing library
+ *
+ * Warning: This code is really a dirty hack. It SHOULD be cleaned
+ * (and most of all, all the static variables should be removed)
+ * 
+ *
+ * Based on 
+ *
+ *  . libppm3.c - ppm utility library part 3
+ *    Copyright (C) 1989, 1991 by Jef Poskanzer.
+ *
+ *  . ppmtogif.c - read a portable pixmap and produce a GIF file
+ *    Copyright (C) 1989 by Jef Poskanzer.
+ *
+ *  . GIFCOMPR.C
+ *    Lempel-Ziv compression based on 'compress.c'. 
+ *    File compression ala IEEE Computer, June 1984.
+ *    By Authors:  Spencer W. Thomas       (decvax!harpo!utah-cs!utah-gr!thomas)
+ *                 Jim McKie               (decvax!mcvax!jim)
+ *                 Steve Davies            (decvax!vax135!petsd!peora!srd)
+ *                 Ken Turkowski           (decvax!decwrl!turtlevax!ken)
+ *                 James A. Woods          (decvax!ihnp4!ames!jaw)
+ *                 Joe Orost               (decvax!vax135!petsd!joe)
+ *    GIF modifications by David Rowley (mgardi@watdcsu.waterloo.edu)
+ *
+ * .  ppmquant.c - quantize the colors in a pixmap down to a specified
+ *    number 
+ *    Copyright (C) 1989, 1991 by Jef Poskanzer.  Based on Paul
+ *    Heckbert's paper "Color Image Quantization for Frame Buffer
+ *    Display", SIGGRAPH '82 Proceedings, page 297.  
+ *
  */
 
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <unistd.h>
-
-#include <GL/gl.h>
+#include "Gmsh.h"
+#include "GmshUI.h"
 #include "gl2gif.h"
 
-static int _GifError = 0;
-static int ExpNumOfColors = 8, ColorMapSize = 256;
+/* ------------------------------------------------------------------
+   PPM colormap routines
+   ------------------------------------------------------------------ */
 
+#define HASH_SIZE 20023
+#define ppm_hashpixel(p) ( ( (int) (p) & 0xfffffffful ) % HASH_SIZE )
 
-/******************************************************************************
-* Initialize HashTable - allocate the memory needed and clear it.             *
-******************************************************************************/
-GifHashTableType *_InitHashTable(void)
-{
-    GifHashTableType *HashTable;
+static int     static_red[MAX_GIFCOLORS];
+static int     static_green[MAX_GIFCOLORS];
+static int     static_blue[MAX_GIFCOLORS];
+static int     static_perm[MAX_GIFCOLORS], static_permi[MAX_GIFCOLORS];
+static int     static_nbcolors;
+static pixel** static_pixels;
+static colorhash_table static_cht;
 
-    if ((HashTable = (GifHashTableType *) malloc(sizeof(GifHashTableType)))
-        == NULL)
-        return NULL;
+colorhash_table ppm_alloccolorhash( ){
+  colorhash_table cht;
+  int i;
+  
+  cht = (colorhash_table) Malloc( HASH_SIZE * sizeof(colorhist_list) );
 
-    _ClearHashTable(HashTable);
+  for ( i = 0; i < HASH_SIZE; ++i )
+    cht[i] = (colorhist_list) 0;
+  
+  return cht;
+}
 
-    return HashTable;
+void ppm_freecolorhash( colorhash_table cht ){
+  int i;
+  colorhist_list chl, chlnext;
+  
+  for ( i = 0; i < HASH_SIZE; ++i )
+    for ( chl = cht[i]; chl != (colorhist_list) 0; chl = chlnext ){
+      chlnext = chl->next;
+      Free( (char*) chl );
+    }
+  Free( (char*) cht );
 }
 
-/******************************************************************************
-* Routine to clear the HashTable to an empty state.                           *
-* This part is a little machine depended. Use the commented part otherwise.   *
-******************************************************************************/
-void _ClearHashTable(GifHashTableType *HashTable)
-{
-  int index = HT_SIZE;
-  unsigned long* HTable = HashTable->HTable;
-  while (--index>=0)
-    HTable[index] = 0xfffffffful;
+colorhash_table ppm_computecolorhash( pixel ** const pixels, 
+				      const int cols, const int rows, 
+				      const int maxcolors, int * const colorsP ){
+  colorhash_table cht;
+  const pixel* pP;
+  colorhist_list chl;
+  int col, row, hash;
+  
+  cht = ppm_alloccolorhash( );
+  *colorsP = 0;
+  
+  /* Go through the entire image, building a hash table of colors. */
+  for ( row = 0; row < rows; ++row )
+    for ( col = 0, pP = pixels[row]; col < cols; ++col, ++pP ){
+      hash = ppm_hashpixel( *pP );
+      for ( chl = cht[hash]; chl != (colorhist_list) 0; chl = chl->next )
+	if ( PPM_EQUAL( chl->ch.color, *pP ) )
+	  break;
+      if ( chl != (colorhist_list) 0 )
+	++(chl->ch.value);
+      else{
+	if ( ++(*colorsP) > maxcolors ){
+	  ppm_freecolorhash( cht );
+	  return (colorhash_table) 0;
+	}
+	chl = (colorhist_list) Malloc( sizeof(struct colorhist_list_item) );
+	chl->ch.color = *pP;
+	chl->ch.value = 1;
+	chl->next = cht[hash];
+	cht[hash] = chl;
+      }
+    }
+  
+  return cht;
 }
 
-/******************************************************************************
-* Routine to generate an HKey for the hashtable out of the given unique key.  *
-* The given Key is assumed to be 20 bits as follows: lower 8 bits are the     *
-* new postfix character, while the upper 12 bits are the prefix code.         *
-* Because the average hit ratio is only 2 (2 hash references per entry),      *
-* evaluating more complex keys (such as twin prime keys) does not worth it!   *
-******************************************************************************/
-static int KeyItem(unsigned long Item)
-{
-    return ((Item >> 12) ^ Item) & HT_KEY_MASK;
+int ppm_addtocolorhash( colorhash_table cht, const pixel * const colorP, 
+			const int value ){
+  register int hash;
+  register colorhist_list chl;
+  
+  chl = (colorhist_list) Malloc( sizeof(struct colorhist_list_item) );
+  hash = ppm_hashpixel( *colorP );
+  chl->ch.color = *colorP;
+  chl->ch.value = value;
+  chl->next = cht[hash];
+  cht[hash] = chl;
+  return 0;
 }
 
-/******************************************************************************
-* Routine to insert a new Item into the HashTable. The data is assumed to be  *
-* new one.                                                                    *
-******************************************************************************/
-void _InsertHashTable(GifHashTableType *HashTable, unsigned long Key, int Code)
-{
-    int HKey = KeyItem(Key);
-    unsigned long *HTable = HashTable -> HTable;
-
-    while (HT_GET_KEY(HTable[HKey]) != 0xFFFFFL) {
-        HKey = (HKey + 1) & HT_KEY_MASK;
+colorhist_vector ppm_colorhashtocolorhist( const colorhash_table cht, 
+					   const int maxcolors ){
+  colorhist_vector chv;
+  colorhist_list chl;
+  int i, j;
+  
+  /* Now collate the hash table into a simple colorhist array. */
+  chv = (colorhist_vector) Malloc( maxcolors * sizeof(struct colorhist_item) );
+  /* Loop through the hash table. */
+  j = 0;
+  for ( i = 0; i < HASH_SIZE; ++i )
+    for ( chl = cht[i]; chl != (colorhist_list) 0; chl = chl->next ){
+      /* Add the new entry. */
+      chv[j] = chl->ch;
+      ++j;
     }
-    HTable[HKey] = HT_PUT_KEY(Key) | HT_PUT_CODE(Code);
+  
+  /* All done. */
+  return chv;
 }
 
-/******************************************************************************
-* Routine to test if given Key exists in HashTable and if so returns its code *
-* Returns the Code if key was found, -1 if not.                               *
-******************************************************************************/
-int _ExistsHashTable(GifHashTableType *HashTable, unsigned long Key)
-{
-    int HKey = KeyItem(Key);
-    unsigned long *HTable = HashTable -> HTable, HTKey;
-
-    while ((HTKey = HT_GET_KEY(HTable[HKey])) != 0xFFFFFL) {
-        if (Key == HTKey) return HT_GET_CODE(HTable[HKey]);
-        HKey = (HKey + 1) & HT_KEY_MASK;
-    }
+colorhash_table ppm_colorhisttocolorhash( const colorhist_vector chv, 
+					  const int colors ){
+  colorhash_table cht;
+  int i, hash;
+  pixel color;
+  colorhist_list chl;
+  
+  cht = ppm_alloccolorhash( );  /* Initializes to NULLs */
+  
+  for ( i = 0; i < colors; ++i ){
+    color = chv[i].color;
+    hash = ppm_hashpixel( color );
+    for ( chl = cht[hash]; chl != (colorhist_list) 0; chl = chl->next )
+      if ( PPM_EQUAL( chl->ch.color, color ) )
+	Msg(ERROR, "GIF: same color found twice - %d %d %d", PPM_GETR(color),
+	    PPM_GETG(color), PPM_GETB(color) );
+    chl = (colorhist_list) Malloc( sizeof(struct colorhist_list_item) );
+    chl->ch.color = color;
+    chl->ch.value = i;
+    chl->next = cht[hash];
+    cht[hash] = chl;
+  }
+  
+  return cht;
+}
 
-    return -1;
+colorhist_vector ppm_computecolorhist( pixel ** const pixels, 
+				       const int cols, const int rows, 
+				       const int maxcolors, 
+				       int * const colorsP ){
+  colorhash_table cht;
+  colorhist_vector chv;
+  
+  cht = ppm_computecolorhash( pixels, cols, rows, maxcolors, colorsP );
+  if ( cht == (colorhash_table) 0 )
+    return (colorhist_vector) 0;
+  chv = ppm_colorhashtocolorhist( cht, maxcolors );
+  ppm_freecolorhash( cht );
+  return chv;
 }
 
-/******************************************************************************
-* Miscellaneous utility functions                                             *
-******************************************************************************/
 
-int BitSize(int n)
-/* return smallest bitfield size n will fit in */
-{
-    register int i;
+int ppm_lookupcolor( const colorhash_table cht, const pixel * const colorP ){
+  int hash;
+  colorhist_list chl;
+  
+  hash = ppm_hashpixel( *colorP );
+  for ( chl = cht[hash]; chl != (colorhist_list) 0; chl = chl->next )
+    if ( PPM_EQUAL( chl->ch.color, *colorP ) )
+      return chl->ch.value;
+  
+  return -1;
+}
 
-    for (i = 1; i <= 8; i++)
-        if ((1 << i) >= n)
-            break;
-    return(i);
+void ppm_freecolorhist( colorhist_vector chv ){
+  Free( (char*) chv );
 }
 
+static int colorstobpp( int colors ){
+  int bpp;
+
+  if ( colors <= 2 )
+    bpp = 1;
+  else if ( colors <= 4 )
+    bpp = 2;
+  else if ( colors <= 8 )
+    bpp = 3;
+  else if ( colors <= 16 )
+    bpp = 4;
+  else if ( colors <= 32 )
+    bpp = 5;
+  else if ( colors <= 64 )
+    bpp = 6;
+  else if ( colors <= 128 )
+    bpp = 7;
+  else if ( colors <= 256 )
+    bpp = 8;
+  else{
+    Msg(ERROR, "GIF: can't happen: too many colors" );
+    bpp = 8 ;
+  }
 
-/******************************************************************************
-* Color map object functions                                                  *
-******************************************************************************/
+  return bpp;
+}
 
-ColorMapObject *MakeMapObject(int ColorCount, GifColorType *ColorMap)
-{
-    ColorMapObject *Object;
 
-    if (ColorCount != (1 << BitSize(ColorCount))){
-      printf("Arrrrrgggg\n");
-      return((ColorMapObject *)NULL);
-    }
+static int sqr(int x){
+  return x*x;
+}
 
-    Object = (ColorMapObject *)malloc(sizeof(ColorMapObject));
-    if (Object == (ColorMapObject *)NULL)
-        return((ColorMapObject *)NULL);
+static int closestcolor(pixel color){
+  int i,r,g,b,d,imin,dmin;
+  
+  r=(int)PPM_GETR(color);
+  g=(int)PPM_GETG(color);
+  b=(int)PPM_GETB(color);
+
+  dmin=1000000;
+  for (i=0 ; i<static_nbcolors ; i++) {
+    d = sqr(r-static_red[i]) + sqr(g-static_green[i]) + sqr(b-static_blue[i]);
+    if (d<dmin) {
+      dmin=d;
+      imin=i; 
+    } 
+  }
+  ppm_addtocolorhash(static_cht,&color,static_permi[imin]);
+  return imin;
+}
 
-    Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType));
-    if (Object->Colors == (GifColorType *)NULL)
-        return((ColorMapObject *)NULL);
 
-    Object->ColorCount = ColorCount;
-    Object->BitsPerPixel = BitSize(ColorCount);
+static int GetPixel( int x, int y ){
+  int color;
+  
+  color = ppm_lookupcolor( static_cht, &static_pixels[y][x] );
+  if (color == -1)
+    color = closestcolor(static_pixels[y][x]);
+  else
+    color = static_perm[color];
+  return color;
+}
 
-    if (ColorMap)
-        memcpy((char *)Object->Colors,
-               (char *)ColorMap, ColorCount * sizeof(GifColorType));
 
-    return(Object);
-}
+/*------------------------------------------------------------------
+  GIF compression routines
+  ------------------------------------------------------------------*/
 
-void FreeMapObject(ColorMapObject *Object)
-{
-    free(Object->Colors);
-    free(Object);
-}
+#define BITS    12
+#define HSIZE   5003  /* 80% occupancy */
+#define TRUE    1
+#define FALSE   0
 
-/*****************************************************************************
-* Print the last GIF error to stderr.                                        *
-*****************************************************************************/
-void PrintGifError(void)
-{
-    char *Err;
-
-    switch(_GifError) {
-        case E_GIF_ERR_OPEN_FAILED:
-            Err = "Failed to open given file";
-            break;
-        case E_GIF_ERR_WRITE_FAILED:
-            Err = "Failed to Write to given file";
-            break;
-        case E_GIF_ERR_HAS_SCRN_DSCR:
-            Err = "Screen Descriptor already been set";
-            break;
-        case E_GIF_ERR_HAS_IMAG_DSCR:
-            Err = "Image Descriptor is still active";
-            break;
-        case E_GIF_ERR_NO_COLOR_MAP:
-            Err = "Neither Global Nor Local color map";
-            break;
-        case E_GIF_ERR_DATA_TOO_BIG:
-            Err = "#Pixels bigger than Width * Height";
-            break;
-        case E_GIF_ERR_NOT_ENOUGH_MEM:
-            Err = "Fail to allocate required memory";
-            break;
-        case E_GIF_ERR_DISK_IS_FULL:
-            Err = "Write failed (disk full?)";
-            break;
-        case E_GIF_ERR_CLOSE_FAILED:
-            Err = "Failed to close given file";
-            break;
-        case E_GIF_ERR_NOT_WRITEABLE:
-            Err = "Given file was not opened for write";
-            break;
-        default:
-            Err = NULL;
-            break;
-    }
-    if (Err != NULL)
-        fprintf(stderr, "Error: %s\n", Err);
-    else
-        fprintf(stderr, "Error: GIF undefined error %d\n", _GifError);
-}
+typedef unsigned char   char_type;
+typedef int (* ifunptr)(int, int);
 
-#define ABS(x)  ((x) > 0 ? (x) : (-(x)))
-
-#define COLOR_ARRAY_SIZE 32768
-#define BITS_PER_PRIM_COLOR 5
-#define MAX_PRIM_COLOR      0x1f
-
-static int SortRGBAxis;
-
-typedef struct QuantizedColorType {
-    GifByteType RGB[3];
-    GifByteType NewColorIndex;
-    long Count;
-    struct QuantizedColorType *Pnext;
-} QuantizedColorType;
-
-typedef struct NewColorMapType {
-    GifByteType RGBMin[3], RGBWidth[3];
-    int NumEntries;    /* # of QuantizedColorType in linked list below. */
-    long Count;        /* Total number of pixels in all the entries. */
-    QuantizedColorType *QuantizedColors;
-} NewColorMapType;
-
-static int SubdivColorMap(NewColorMapType *NewColorSubdiv,
-                          int ColorMapSize,
-                          int *NewColorMapSize);
-static int SortCmpRtn(const VoidPtr Entry1, const VoidPtr Entry2);
-
-/******************************************************************************
-* Quantize high resolution image into lower one. Input image consists of a    *
-* 2D array for each of the RGB colors with size Width by Height. There is no  *
-* Color map for the input. Output is a quantized image with 2D array of       *
-* indexes into the output color map.                                          *
-*   Note input image can be 24 bits at the most (8 for red/green/blue) and    *
-* the output has 256 colors at the most (256 entries in the color map.).      *
-* ColorMapSize specifies size of color map up to 256 and will be updated to   *
-* real size before returning.                                                 *
-*   Also non of the parameter are allocated by this routine.                  *
-*   This function returns GIF_OK if succesfull, GIF_ERROR otherwise.          *
-******************************************************************************/
-int QuantizeBuffer(int Width, int Height, int *ColorMapSize,
-        GifByteType *RedInput, GifByteType *GreenInput, GifByteType *BlueInput,
-        GifByteType *OutputBuffer, GifColorType *OutputColorMap)
-{
-    int Index, NumOfEntries;
-    int i, j, MaxRGBError[3];
-    int NewColorMapSize;
-    long Red, Green, Blue;
-    NewColorMapType NewColorSubdiv[256];
-    QuantizedColorType *ColorArrayEntries, *QuantizedColor;
-
-    if ((ColorArrayEntries = (QuantizedColorType *)
-            malloc(sizeof(QuantizedColorType) * COLOR_ARRAY_SIZE)) == NULL) {
-        _GifError = E_GIF_ERR_NOT_ENOUGH_MEM;
-        return GIF_ERROR;
-    }
+static int    g_init_bits;
+static FILE*  g_outfile;
+static int    Width, Height;
+static int    curx, cury;
+static long   CountDown;
+static int    Pass = 0;
+static int    Interlace;
 
-    for (i = 0; i < COLOR_ARRAY_SIZE; i++) {
-        ColorArrayEntries[i].RGB[0]= i >> (2 * BITS_PER_PRIM_COLOR);
-        ColorArrayEntries[i].RGB[1] = (i >> BITS_PER_PRIM_COLOR) &
-                                                        MAX_PRIM_COLOR;
-        ColorArrayEntries[i].RGB[2] = i & MAX_PRIM_COLOR;
-        ColorArrayEntries[i].Count = 0;
-    }
+#include <ctype.h>
 
-    /* Sample the colors and their distribution: */
-    for (i = 0; i < (int)(Width * Height); i++) {
-        Index = ((RedInput[i] >> (8 - BITS_PER_PRIM_COLOR))
-                    << (2 * BITS_PER_PRIM_COLOR)) +
-                ((GreenInput[i] >> (8 - BITS_PER_PRIM_COLOR))
-                    << BITS_PER_PRIM_COLOR) +
-                (BlueInput[i] >> (8 - BITS_PER_PRIM_COLOR));
-        ColorArrayEntries[Index].Count++;
-    }
+#define ARGVAL() (*++(*argv) || (--argc && *++argv))
 
-    /* Put all the colors in the first entry of the color map, and call the  */
-    /* recursive subdivision process.                                        */
-    for (i = 0; i < 256; i++) {
-        NewColorSubdiv[i].QuantizedColors = NULL;
-        NewColorSubdiv[i].Count = NewColorSubdiv[i].NumEntries = 0;
-        for (j = 0; j < 3; j++) {
-            NewColorSubdiv[i].RGBMin[j] = 0;
-            NewColorSubdiv[i].RGBWidth[j] = 255;
-        }
-    }
+static int       n_bits;            /* number of bits/code */
+static int       maxbits = BITS;    /* user settable max # bits/code */
+static code_int  maxcode;           /* maximum code, given n_bits */
+static code_int  maxmaxcode = (code_int)1 << BITS; 
+                                    /* should NEVER generate this code */
 
-    /* Find the non empty entries in the color table and chain them: */
-    for (i = 0; i < COLOR_ARRAY_SIZE; i++)
-        if (ColorArrayEntries[i].Count > 0) break;
-    QuantizedColor = NewColorSubdiv[0].QuantizedColors = &ColorArrayEntries[i];
-    NumOfEntries = 1;
-    while (++i < COLOR_ARRAY_SIZE)
-        if (ColorArrayEntries[i].Count > 0) {
-            QuantizedColor -> Pnext = &ColorArrayEntries[i];
-            QuantizedColor = &ColorArrayEntries[i];
-            NumOfEntries++;
-        }
-    QuantizedColor -> Pnext = NULL;
-
-    NewColorSubdiv[0].NumEntries = NumOfEntries;/* Different sampled colors. */
-    NewColorSubdiv[0].Count = ((long) Width) * Height;            /* Pixels. */
-    NewColorMapSize = 1;
-    if (SubdivColorMap(NewColorSubdiv, *ColorMapSize, &NewColorMapSize) !=
-                                                                     GIF_OK) {
-        free((char *) ColorArrayEntries);
-        return GIF_ERROR;
-    }
-    if (NewColorMapSize < *ColorMapSize) {
-        /* And clear rest of color map: */
-        for (i = NewColorMapSize; i < *ColorMapSize; i++)
-            OutputColorMap[i].Red =
-            OutputColorMap[i].Green =
-            OutputColorMap[i].Blue = 0;
-    }
+#define MAXCODE(n_bits) (((code_int) 1 << (n_bits)) - 1)
 
-    /* Average the colors in each entry to be the color to be used in the    */
-    /* output color map, and plug it into the output color map itself.       */
-    for (i = 0; i < NewColorMapSize; i++) {
-        if ((j = NewColorSubdiv[i].NumEntries) > 0) {
-            QuantizedColor = NewColorSubdiv[i].QuantizedColors;
-            Red = Green = Blue = 0;
-            while (QuantizedColor) {
-                QuantizedColor -> NewColorIndex = i;
-                Red += QuantizedColor -> RGB[0];
-                Green += QuantizedColor -> RGB[1];
-                Blue += QuantizedColor -> RGB[2];
-                QuantizedColor = QuantizedColor -> Pnext;
-            }
-            OutputColorMap[i].Red = (Red << (8 - BITS_PER_PRIM_COLOR)) / j;
-            OutputColorMap[i].Green = (Green << (8 - BITS_PER_PRIM_COLOR)) / j;
-            OutputColorMap[i].Blue= (Blue << (8 - BITS_PER_PRIM_COLOR)) / j;
-        }
-        else
-            fprintf(stderr, "Warning, Null entry in quantized color map - that's weird\n");
-    }
+static count_int htab [HSIZE];
+static unsigned short codetab [HSIZE];
+#define HashTabOf(i)    htab[i]
+#define CodeTabOf(i)    codetab[i]
 
-    /* Finally scan the input buffer again and put the mapped index in the   */
-    /* output buffer.                                                        */
-    MaxRGBError[0] = MaxRGBError[1] = MaxRGBError[2] = 0;
-    for (i = 0; i < (int)(Width * Height); i++) {
-        Index = ((RedInput[i] >> (8 - BITS_PER_PRIM_COLOR))
-                    << (2 * BITS_PER_PRIM_COLOR)) +
-                ((GreenInput[i] >> (8 - BITS_PER_PRIM_COLOR))
-                    << BITS_PER_PRIM_COLOR) +
-                (BlueInput[i] >> (8 - BITS_PER_PRIM_COLOR));
-        Index = ColorArrayEntries[Index].NewColorIndex;
-        OutputBuffer[i] = Index;
-        if (MaxRGBError[0] < ABS(OutputColorMap[Index].Red - RedInput[i]))
-            MaxRGBError[0] = ABS(OutputColorMap[Index].Red - RedInput[i]);
-        if (MaxRGBError[1] < ABS(OutputColorMap[Index].Green - GreenInput[i]))
-            MaxRGBError[1] = ABS(OutputColorMap[Index].Green - GreenInput[i]);
-        if (MaxRGBError[2] < ABS(OutputColorMap[Index].Blue - BlueInput[i]))
-            MaxRGBError[2] = ABS(OutputColorMap[Index].Blue - BlueInput[i]);
-    }
+static code_int  hsize = HSIZE;     /* for dynamic table sizing */
 
-    free((char *) ColorArrayEntries);
+/*
+ * To save much memory, we overlay the table used by compress() with those
+ * used by decompress().  The tab_prefix table is the same size and type
+ * as the codetab.  The tab_suffix table needs 2**BITS characters.  We
+ * get this from the beginning of htab.  The output stack uses the rest
+ * of htab, and contains characters.  There is plenty of room for any
+ * possible stack (stack used to be 8000 characters).
+ */
 
-    *ColorMapSize = NewColorMapSize;
+#define tab_prefixof(i)  CodeTabOf(i)
+#define tab_suffixof(i)  ((char_type*)(htab))[i]
+#define de_stack         ((char_type*)&tab_suffixof((code_int)1<<BITS))
 
-    return GIF_OK;
-}
+static code_int free_ent = 0;             /* first unused entry */
 
-/******************************************************************************
-* Routine to subdivide the RGB space recursively using median cut in each     *
-* axes alternatingly until ColorMapSize different cubes exists.               *
-* The biggest cube in one dimension is subdivide unless it has only one entry.*
-* Returns GIF_ERROR if failed, otherwise GIF_OK.                              *
-******************************************************************************/
-static int SubdivColorMap(NewColorMapType *NewColorSubdiv,
-                          int ColorMapSize,
-                          int *NewColorMapSize)
-{
-    int MaxSize;
-    int i, j, Index = 0, NumEntries, MinColor, MaxColor;
-    long Sum, Count;
-    QuantizedColorType *QuantizedColor, **SortArray;
-
-    while (ColorMapSize > *NewColorMapSize) {
-        /* Find candidate for subdivision: */
-        MaxSize = -1;
-        for (i = 0; i < *NewColorMapSize; i++) {
-            for (j = 0; j < 3; j++) {
-                if (((int) NewColorSubdiv[i].RGBWidth[j]) > MaxSize &&
-                    NewColorSubdiv[i].NumEntries > 1) {
-                    MaxSize = NewColorSubdiv[i].RGBWidth[j];
-                    Index = i;
-                    SortRGBAxis = j;
-                }
-            }
-        }
-
-        if (MaxSize == -1)
-            return GIF_OK;
-
-        /* Split the entry Index into two along the axis SortRGBAxis: */
-
-        /* Sort all elements in that entry along the given axis and split at */
-        /* the median.                                                       */
-        if ((SortArray = (QuantizedColorType **)
-            malloc(sizeof(QuantizedColorType *) *
-                   NewColorSubdiv[Index].NumEntries)) == NULL)
-            return GIF_ERROR;
-        for (j = 0, QuantizedColor = NewColorSubdiv[Index].QuantizedColors;
-             j < NewColorSubdiv[Index].NumEntries && QuantizedColor != NULL;
-             j++, QuantizedColor = QuantizedColor -> Pnext)
-            SortArray[j] = QuantizedColor;
-        qsort(SortArray, NewColorSubdiv[Index].NumEntries,
-              sizeof(QuantizedColorType *), SortCmpRtn);
-
-        /* Relink the sorted list into one: */
-        for (j = 0; j < NewColorSubdiv[Index].NumEntries - 1; j++)
-            SortArray[j] -> Pnext = SortArray[j + 1];
-        SortArray[NewColorSubdiv[Index].NumEntries - 1] -> Pnext = NULL;
-        NewColorSubdiv[Index].QuantizedColors = QuantizedColor = SortArray[0];
-        free((char *) SortArray);
-
-        /* Now simply add the Counts until we have half of the Count: */
-        Sum = NewColorSubdiv[Index].Count / 2 - QuantizedColor -> Count;
-        NumEntries = 1;
-        Count = QuantizedColor -> Count;
-        while ((Sum -= QuantizedColor -> Pnext -> Count) >= 0 &&
-               QuantizedColor -> Pnext != NULL &&
-               QuantizedColor -> Pnext -> Pnext != NULL) {
-            QuantizedColor = QuantizedColor -> Pnext;
-            NumEntries++;
-            Count += QuantizedColor -> Count;
-        }
-        /* Save the values of the last color of the first half, and first    */
-        /* of the second half so we can update the Bounding Boxes later.     */
-        /* Also as the colors are quantized and the BBoxes are full 0..255,  */
-        /* they need to be rescaled.                                         */
-        MaxColor = QuantizedColor -> RGB[SortRGBAxis];/* Max. of first half. */
-        MinColor = QuantizedColor -> Pnext -> RGB[SortRGBAxis];/* of second. */
-        MaxColor <<= (8 - BITS_PER_PRIM_COLOR);
-        MinColor <<= (8 - BITS_PER_PRIM_COLOR);
-
-        /* Partition right here: */
-        NewColorSubdiv[*NewColorMapSize].QuantizedColors =
-            QuantizedColor -> Pnext;
-        QuantizedColor -> Pnext = NULL;
-        NewColorSubdiv[*NewColorMapSize].Count = Count;
-        NewColorSubdiv[Index].Count -= Count;
-        NewColorSubdiv[*NewColorMapSize].NumEntries =
-            NewColorSubdiv[Index].NumEntries - NumEntries;
-        NewColorSubdiv[Index].NumEntries = NumEntries;
-        for (j = 0; j < 3; j++) {
-            NewColorSubdiv[*NewColorMapSize].RGBMin[j] =
-                NewColorSubdiv[Index].RGBMin[j];
-            NewColorSubdiv[*NewColorMapSize].RGBWidth[j] =
-                NewColorSubdiv[Index].RGBWidth[j];
-        }
-        NewColorSubdiv[*NewColorMapSize].RGBWidth[SortRGBAxis] =
-            NewColorSubdiv[*NewColorMapSize].RGBMin[SortRGBAxis] +
-            NewColorSubdiv[*NewColorMapSize].RGBWidth[SortRGBAxis] -
-            MinColor;
-        NewColorSubdiv[*NewColorMapSize].RGBMin[SortRGBAxis] = MinColor;
-
-        NewColorSubdiv[Index].RGBWidth[SortRGBAxis] =
-            MaxColor - NewColorSubdiv[Index].RGBMin[SortRGBAxis];
-
-        (*NewColorMapSize)++;
-    }
+/*
+ * block compression parameters -- after all codes are used up,
+ * and compression rate changes, start over.
+ */
+static int clear_flg = 0;
 
-    return GIF_OK;
+static int offset;
+static long int in_count = 1;            /* length of input */
+static long int out_count = 0;           /* # of codes output (for debugging) */
+static int ClearCode;
+static int EOFCode;
+
+/*
+ * Number of characters so far in this 'packet'
+ */
+static int a_count;
+
+/*
+ * Set up the 'byte output' routine
+ */
+static void char_init(){
+  a_count = 0;
 }
 
-/******************************************************************************
-* Routine called by qsort to compare to entries.                              *
-******************************************************************************/
-static int SortCmpRtn(const VoidPtr Entry1, const VoidPtr Entry2)
-{
-    return (* ((QuantizedColorType **) Entry1)) -> RGB[SortRGBAxis] -
-           (* ((QuantizedColorType **) Entry2)) -> RGB[SortRGBAxis];
+/*
+ * Define the storage for the packet accumulator
+ */
+static char accum[ 256 ];
+
+
+/*
+ * Flush the packet to disk, and reset the accumulator
+ */
+static void flush_char(){
+  if( a_count > 0 ) {
+    fputc( a_count, g_outfile );
+    fwrite( accum, 1, a_count, g_outfile );
+    a_count = 0;
+  }
 }
 
-#define GIF87_STAMP     "GIF87a"         /* First chars in file - GIF stamp. */
-#define GIF89_STAMP     "GIF89a"         /* First chars in file - GIF stamp. */
+/*
+ * Add a character to the end of the current packet, and if it is 254
+ * characters, flush the packet to disk.
+ */
+static void char_out( int c){
+  accum[ a_count++ ] = c;
+  if( a_count >= 254 )
+    flush_char();
+}
 
-/* Masks given codes to BitsPerPixel, to make sure all codes are in range: */
-static GifPixelType CodeMask[] = {
-    0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff
-};
+/*
+ * Bump the 'curx' and 'cury' to point to the next pixel
+ */
 
-static char *GifVersionPrefix = GIF87_STAMP;
-
-#define WRITE(_gif,_buf,_len)   \
-   fwrite(_buf, 1, _len, ((GifFilePrivateType*)_gif->Private)->File)
-
-static int EGifPutWord(int Word, GifFileType *GifFile);
-static int EGifSetupCompress(GifFileType *GifFile);
-static int EGifCompressLine(GifFileType *GifFile, GifPixelType *Line,
-                                                                int LineLen);
-static int EGifCompressOutput(GifFileType *GifFile, int Code);
-static int EGifBufferedOutput(GifFileType *GifFile, GifByteType *Buf, int c);
-
-/******************************************************************************
-*   Update a new gif file, given its file handle, which must be opened for    *
-* write in binary mode.                                                       *
-*   Returns GifFileType pointer dynamically allocated which serves as the gif *
-* info record. _GifError is cleared if succesfull.                            *
-******************************************************************************/
-GifFileType *EGifOpenFileHandle(FILE *f, int FileHandle)
-{
-    GifFileType *GifFile;
-    GifFilePrivateType *Private;
-
-    if ((GifFile = (GifFileType *) malloc(sizeof(GifFileType))) == NULL) {
-        _GifError = E_GIF_ERR_NOT_ENOUGH_MEM;
-        return NULL;
+static void BumpPixel(){
+  /*
+   * Bump the current X position
+   */
+  ++curx;
+  
+  /*
+   * If we are at the end of a scan line, set curx back to the beginning
+   * If we are interlaced, bump the cury to the appropriate spot,
+   * otherwise, just increment it.
+   */
+  if( curx == Width ) {
+    curx = 0;
+    
+    if( !Interlace )
+      ++cury;
+    else {
+      switch( Pass ) {
+	
+      case 0:
+	cury += 8;
+	if( cury >= Height ) {
+	  ++Pass;
+	  cury = 4;
+	}
+	break;
+	
+      case 1:
+	cury += 8;
+	if( cury >= Height ) {
+	  ++Pass;
+	  cury = 2;
+	}
+	break;
+	
+      case 2:
+	cury += 4;
+	if( cury >= Height ) {
+	  ++Pass;
+	  cury = 1;
+	}
+	break;
+	
+      case 3:
+	cury += 2;
+	break;
+      }
     }
+  }
+}
+
+
+/*
+ * Return the next pixel from the image
+ */
+static int GIFNextPixel( ifunptr getpixel){
+  int r;
+
+  if( CountDown == 0 )
+    return EOF;
+  
+  --CountDown;
+  
+  r = ( * getpixel )( curx, cury );
+  
+  BumpPixel();
+  
+  return r;
+}
+
+
+/*
+ * Output the given code.
+ * Inputs:
+ *      code:   A n_bits-bit integer.  If == -1, then EOF.  This assumes
+ *              that n_bits =< (long)wordsize - 1.
+ * Outputs:
+ *      Outputs code to the file.
+ * Assumptions:
+ *      Chars are 8 bits long.
+ * Algorithm:
+ *      Maintain a BITS character long buffer (so that 8 codes will
+ * fit in it exactly).  Use the VAX insv instruction to insert each
+ * code in turn.  When the buffer fills up empty it and start over.
+ */
 
-    memset(GifFile, '\0', sizeof(GifFileType));
+static unsigned long cur_accum = 0;
+static int cur_bits = 0;
 
-    if ((Private = (GifFilePrivateType *)
-                   malloc(sizeof(GifFilePrivateType))) == NULL) {
-        free(GifFile);
-        _GifError = E_GIF_ERR_NOT_ENOUGH_MEM;
-        return NULL;
+static unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
+				 0x001F, 0x003F, 0x007F, 0x00FF,
+				 0x01FF, 0x03FF, 0x07FF, 0x0FFF,
+				 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
+
+static void output( code_int  code){
+  cur_accum &= masks[ cur_bits ];
+  
+  if( cur_bits > 0 )
+    cur_accum |= ((long)code << cur_bits);
+  else
+    cur_accum = code;
+  
+  cur_bits += n_bits;
+  
+  while( cur_bits >= 8 ) {
+    char_out( (unsigned int)(cur_accum & 0xff) );
+    cur_accum >>= 8;
+    cur_bits -= 8;
+  }
+  
+  /*
+   * If the next entry is going to be too big for the code size,
+   * then increase it, if possible.
+   */
+  if ( free_ent > maxcode || clear_flg ) {
+    
+    if( clear_flg ) {
+      maxcode = MAXCODE (n_bits = g_init_bits);
+      clear_flg = 0;
+    } 
+    else {
+      ++n_bits;
+      if ( n_bits == maxbits )
+	maxcode = maxmaxcode;
+      else
+	maxcode = MAXCODE(n_bits);
     }
-    if ((Private->HashTable = _InitHashTable()) == NULL) {
-        free(GifFile);
-        free(Private);
-        _GifError = E_GIF_ERR_NOT_ENOUGH_MEM;
-        return NULL;
+  }
+  
+  if( code == EOFCode ) {
+    /*
+     * At EOF, write the rest of the buffer.
+     */
+    while( cur_bits > 0 ) {
+      char_out( (unsigned int)(cur_accum & 0xff) );
+      cur_accum >>= 8;
+      cur_bits -= 8;
     }
-
-    GifFile->Private = (VoidPtr) Private;
-    Private->FileHandle = FileHandle;
-    Private->File = f;
-    Private->FileState = FILE_STATE_WRITE;
     
-    _GifError = 0;
+    flush_char();
+    
+    fflush( g_outfile );
+    
+    if( ferror( g_outfile ) )
+      Msg(ERROR, "GIF: Error writing output file");
+  }
+}
+
+
+/*
+ * compress 
+ *
+ * Algorithm:  use open addressing double hashing (no chaining) on the
+ * prefix code / next character combination.  We do a variant of Knuth's
+ * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
+ * secondary probe.  Here, the modular division first probe is gives way
+ * to a faster exclusive-or manipulation.  Also do block compression with
+ * an adaptive reset, whereby the code table is cleared when the compression
+ * ratio decreases, but after the table fills.  The variable-length output
+ * codes are re-sized at this point, and a special CLEAR code is generated
+ * for the decompressor.  Late addition:  construct the table according to
+ * file size for noticeable speed improvement on small files.  Please direct
+ * questions about this implementation to ames!jaw.
+ */
 
-    return GifFile;
+static void cl_hash(register count_int hsize){          /* reset code table */
+  register count_int *htab_p = htab+hsize;
+  
+  register long i;
+  register long m1 = -1;
+  
+  i = hsize - 16;
+  do {                            /* might use Sys V memset(3) here */
+    *(htab_p-16) = m1;
+    *(htab_p-15) = m1;
+    *(htab_p-14) = m1;
+    *(htab_p-13) = m1;
+    *(htab_p-12) = m1;
+    *(htab_p-11) = m1;
+    *(htab_p-10) = m1;
+    *(htab_p-9) = m1;
+    *(htab_p-8) = m1;
+    *(htab_p-7) = m1;
+    *(htab_p-6) = m1;
+    *(htab_p-5) = m1;
+    *(htab_p-4) = m1;
+    *(htab_p-3) = m1;
+    *(htab_p-2) = m1;
+    *(htab_p-1) = m1;
+    htab_p -= 16;
+  } while ((i -= 16) >= 0);
+  
+  for ( i += 16; i > 0; --i )
+    *--htab_p = m1;
 }
 
-/******************************************************************************
-*   Routine to set current GIF version. All files open for write will be      *
-* using this version until next call to this routine. Version consists of     *
-* 3 characters as "87a" or "89a". No test is made to validate the version.    *
-******************************************************************************/
-void EGifSetGifVersion(char *Version)
-{
-    strncpy(&GifVersionPrefix[3], Version, 3);
+
+/*
+ * Clear out the hash table
+ */
+static void cl_block (){             /* table clear for block compress */
+  
+  cl_hash ( (count_int) hsize );
+  free_ent = ClearCode + 2;
+  clear_flg = 1;
+  
+  output( (code_int)ClearCode );
 }
 
-/******************************************************************************
-*   This routine should be called before any other EGif calls, immediately    *
-* follows the GIF file openning.                                              *
-******************************************************************************/
-int EGifPutScreenDesc(GifFileType *GifFile,
-        int Width, int Height, int ColorRes, int BackGround,
-        ColorMapObject *ColorMap)
-{
-    int i;
-    GifByteType Buf[3];
-    GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
-
-    if (Private->FileState & FILE_STATE_SCREEN) {
-        /* If already has screen descriptor - something is wrong! */
-        _GifError = E_GIF_ERR_HAS_SCRN_DSCR;
-        return GIF_ERROR;
-    }
-    if (!IS_WRITEABLE(Private)) {
-        /* This file was NOT open for writing: */
-        _GifError = E_GIF_ERR_NOT_WRITEABLE;
-        return GIF_ERROR;
+static void 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 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;
+  
+  /*
+   * Set up the necessary values
+   */
+  offset = 0;
+  out_count = 0;
+  clear_flg = 0;
+  in_count = 1;
+  maxcode = MAXCODE(n_bits = g_init_bits);
+  
+  ClearCode = (1 << (init_bits - 1));
+  EOFCode = ClearCode + 1;
+  free_ent = ClearCode + 2;
+  
+  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 );
+  
+  while ( (c = GIFNextPixel( ReadValue )) != EOF ) {
+    
+    ++in_count;
+    
+    fcode = (long) (((long) c << maxbits) + ent);
+    i = (((code_int)c << hshift) ^ ent);    /* xor hashing */
+    
+    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;
+    ent = c;
+    if ( free_ent < maxmaxcode ) { 
+      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 );
+}
 
-    /* First write the version prefix into the file. */
-    if (WRITE(GifFile, GifVersionPrefix, strlen(GifVersionPrefix)) != strlen(GifVersionPrefix)) {
-        _GifError = E_GIF_ERR_WRITE_FAILED;
-        return GIF_ERROR;
-    }
 
-    GifFile->SWidth = Width;
-    GifFile->SHeight = Height;
-    GifFile->SColorResolution = ColorRes;
-    GifFile->SBackGroundColor = BackGround;
-    if(ColorMap)
-      GifFile->SColorMap=MakeMapObject(ColorMap->ColorCount,ColorMap->Colors);
-    else
-      GifFile->SColorMap=NULL;
-
-    /* Put the screen descriptor into the file: */
-    EGifPutWord(Width, GifFile);
-    EGifPutWord(Height, GifFile);
-    Buf[0] = (ColorMap ? 0x80 : 0x00) |
-             ((ColorRes - 1) << 4) |
-             (ColorMap->BitsPerPixel - 1);
-    Buf[1] = BackGround;
-    Buf[2] = 0;
-    WRITE(GifFile, Buf, 3);
-
-    /* If we have Global color map - dump it also: */
-    if (ColorMap != NULL)
-        for (i = 0; i < ColorMap->ColorCount; i++) {
-            /* Put the ColorMap out also: */
-            Buf[0] = ColorMap->Colors[i].Red;
-            Buf[1] = ColorMap->Colors[i].Green;
-            Buf[2] = ColorMap->Colors[i].Blue;
-            if (WRITE(GifFile, Buf, 3) != 3) {
-                _GifError = E_GIF_ERR_WRITE_FAILED;
-                return GIF_ERROR;
-            }
-        }
-
-    /* Mark this file as has screen descriptor, and no pixel written yet: */
-    Private->FileState |= FILE_STATE_SCREEN;
-
-    return GIF_OK;
+/*
+ * Write out a word to the GIF file
+ */
+static void Putword( int w, FILE* fp){
+  fputc( w & 0xff, fp );
+  fputc( (w / 256) & 0xff, fp );
 }
 
-/******************************************************************************
-*   This routine should be called before any attemp to dump an image - any    *
-* call to any of the pixel dump routines.                                     *
-******************************************************************************/
-int EGifPutImageDesc(GifFileType *GifFile,
-        int Left, int Top, int Width, int Height, int Interlace,
-        ColorMapObject *ColorMap)
-{
-    int i;
-    GifByteType Buf[3];
-    GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
-
-    if (Private->FileState & FILE_STATE_IMAGE &&
-#if defined(__GNUC__)
-        Private->PixelCount > 0xffff0000UL) {
-#else
-        Private->PixelCount > 0xffff0000) {
-#endif
-        /* If already has active image descriptor - something is wrong! */
-        _GifError = E_GIF_ERR_HAS_IMAG_DSCR;
-        return GIF_ERROR;
-    }
-    if (!IS_WRITEABLE(Private)) {
-        /* This file was NOT open for writing: */
-        _GifError = E_GIF_ERR_NOT_WRITEABLE;
-        return GIF_ERROR;
-    }
-    GifFile->Image.Left = Left;
-    GifFile->Image.Top = Top;
-    GifFile->Image.Width = Width;
-    GifFile->Image.Height = Height;
-    GifFile->Image.Interlace = Interlace;
-    if(ColorMap)
-      GifFile->Image.ColorMap =MakeMapObject(ColorMap->ColorCount,ColorMap->Colors);
-    else
-      GifFile->Image.ColorMap = NULL;
-
-    /* Put the image descriptor into the file: */
-    Buf[0] = ',';                              /* Image seperator character. */
-    WRITE(GifFile, Buf, 1);
-    EGifPutWord(Left, GifFile);
-    EGifPutWord(Top, GifFile);
-    EGifPutWord(Width, GifFile);
-    EGifPutWord(Height, GifFile);
-    Buf[0] = (ColorMap ? 0x80 : 0x00) |
-          (Interlace ? 0x40 : 0x00) |
-          (ColorMap ? ColorMap->BitsPerPixel - 1 : 0);
-    WRITE(GifFile, Buf, 1);
-
-    /* If we have Global color map - dump it also: */
-    if (ColorMap != NULL)
-        for (i = 0; i < ColorMap->ColorCount; i++) {
-            /* Put the ColorMap out also: */
-            Buf[0] = ColorMap->Colors[i].Red;
-            Buf[1] = ColorMap->Colors[i].Green;
-            Buf[2] = ColorMap->Colors[i].Blue;
-            if (WRITE(GifFile, Buf, 3) != 3) {
-                _GifError = E_GIF_ERR_WRITE_FAILED;
-                return GIF_ERROR;
-            }
-        }
-    if (GifFile->SColorMap == NULL && GifFile->Image.ColorMap == NULL)
-    {
-        _GifError = E_GIF_ERR_NO_COLOR_MAP;
-        return GIF_ERROR;
-    }
 
-    /* Mark this file as has screen descriptor: */
-    Private->FileState |= FILE_STATE_IMAGE;
-    Private->PixelCount = (long) Width * (long) Height;
+static void GIFEncode( FILE* fp,
+		       int GWidth, int GHeight,
+		       int GInterlace, int Background, int Transparent,
+		       int BitsPerPixel, int Red[], int Green[], int Blue[],
+		       ifunptr GetPixel){
+  int B;
+  int RWidth, RHeight;
+  int LeftOfs, TopOfs;
+  int Resolution;
+  int ColorMapSize;
+  int InitCodeSize;
+  int i;
 
-    EGifSetupCompress(GifFile);      /* Reset compress algorithm parameters. */
+  /* reset stuff for output */
+  cur_accum = 0;
+  cur_bits = 0;
+  free_ent = 0;
 
-    return GIF_OK;
+  Interlace = GInterlace;
+  
+  ColorMapSize = 1 << BitsPerPixel;
+  
+  RWidth = Width = GWidth;
+  RHeight = Height = GHeight;
+  LeftOfs = TopOfs = 0;
+  
+  Resolution = BitsPerPixel;
+  
+  /*
+   * Calculate number of bits we are expecting
+   */
+  CountDown = (long)Width * (long)Height;
+  
+  /*
+   * Indicate which pass we are on (if interlace)
+   */
+  Pass = 0;
+  
+  /*
+   * The initial code size
+   */
+  if( BitsPerPixel <= 1 )
+    InitCodeSize = 2;
+  else
+    InitCodeSize = BitsPerPixel;
+  
+  /*
+   * Set up the current x and y position
+   */
+  curx = cury = 0;
+  
+  /*
+   * Write the Magic header
+   */
+  fwrite( Transparent < 0 ? "GIF87a" : "GIF89a", 1, 6, fp );
+  
+  /*
+   * Write out the screen width and height
+   */
+  Putword( RWidth, fp );
+  Putword( RHeight, fp );
+  
+  /*
+   * Indicate that there is a global colour map
+   */
+  B = 0x80;       /* Yes, there is a color map */
+  
+  /*
+   * OR in the resolution
+   */
+  B |= (Resolution - 1) << 5;
+  
+  /*
+   * OR in the Bits per Pixel
+   */
+  B |= (BitsPerPixel - 1);
+  
+  /*
+   * Write it out
+   */
+  fputc( B, fp );
+  
+  /*
+   * Write out the Background colour
+   */
+  fputc( Background, fp );
+  
+  /*
+   * Byte of 0's (future expansion)
+   */
+  fputc( 0, fp );
+  
+  /*
+   * Write out the Global Colour Map
+   */
+  for( i=0; i<ColorMapSize; ++i ) {
+    fputc( Red[i], fp );
+    fputc( Green[i], fp );
+    fputc( Blue[i], fp );
+  }
+  
+  /*
+   * Write out extension for transparent colour index, if necessary.
+   */
+  if ( Transparent >= 0 ) {
+    fputc( '!', fp );
+    fputc( 0xf9, fp );
+    fputc( 4, fp );
+    fputc( 1, fp );
+    fputc( 0, fp );
+    fputc( 0, fp );
+    fputc( Transparent, fp );
+    fputc( 0, fp );
+  }
+  
+  /*
+   * Write an Image separator
+   */
+  fputc( ',', fp );
+  
+  /*
+   * Write the Image header
+   */
+  
+  Putword( LeftOfs, fp );
+  Putword( TopOfs, fp );
+  Putword( Width, fp );
+  Putword( Height, fp );
+  
+  /*
+   * Write out whether or not the image is interlaced
+   */
+  if( Interlace )
+    fputc( 0x40, fp );
+  else
+    fputc( 0x00, fp );
+  
+  /*
+   * Write out the initial code size
+   */
+  fputc( InitCodeSize, fp );
+  
+  /*
+   * Go and actually compress the data
+   */
+  compress( InitCodeSize+1, fp, GetPixel );
+  
+  /*
+   * Write out a Zero-length packet (to end the series)
+   */
+  fputc( 0, fp );
+  
+  /*
+   * Write the GIF file terminator
+   */
+  fputc( ';', fp );
+  
 }
 
-/******************************************************************************
-*  Put one full scanned line (Line) of length LineLen into GIF file.          *
-******************************************************************************/
-int EGifPutLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
-{
-    int i;
-    GifPixelType Mask;
-    GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
-
-    if (!IS_WRITEABLE(Private)) {
-        /* This file was NOT open for writing: */
-        _GifError = E_GIF_ERR_NOT_WRITEABLE;
-        return GIF_ERROR;
-    }
-
-    if (!LineLen)
-      LineLen = GifFile->Image.Width;
-    if (Private->PixelCount < (unsigned)LineLen) {
-        _GifError = E_GIF_ERR_DATA_TOO_BIG;
-        return GIF_ERROR;
-    }
-    Private->PixelCount -= LineLen;
 
-    /* Make sure the codes are not out of bit range, as we might generate    */
-    /* wrong code (because of overflow when we combine them) in this case:   */
-    Mask = CodeMask[Private->BitsPerPixel];
-    for (i = 0; i < LineLen; i++) Line[i] &= Mask;
+/* ------------------------------------------------------------------
+   PPM quantization
+   ------------------------------------------------------------------ */
 
-    return EGifCompressLine(GifFile, Line, LineLen);
-}
+/* #define LARGE_NORM */
+#define LARGE_LUM
 
-/******************************************************************************
-*   This routine should be called last, to close GIF file.                    *
-******************************************************************************/
-int EGifCloseFile(GifFileType *GifFile)
-{
-    GifByteType Buf;
-    GifFilePrivateType *Private;
-
-    if (GifFile == NULL) return GIF_ERROR;
-
-    Private = (GifFilePrivateType *) GifFile->Private;
-    if (!IS_WRITEABLE(Private)) {
-        /* This file was NOT open for writing: */
-        _GifError = E_GIF_ERR_NOT_WRITEABLE;
-        return GIF_ERROR;
-    }
+/* #define REP_CENTER_BOX */
+/* #define REP_AVERAGE_COLORS */
+#define REP_AVERAGE_PIXELS
 
-    Buf = ';';
-    WRITE(GifFile, &Buf, 1);
+typedef struct box* box_vector;
+struct box{
+  int ind;
+  int colors;
+  int sum;
+};
 
-    if (GifFile->Image.ColorMap)
-        FreeMapObject(GifFile->Image.ColorMap);
-    if (GifFile->SColorMap)
-        FreeMapObject(GifFile->SColorMap);
-    if (Private) {
-        if (Private->HashTable) free((char *) Private->HashTable);
-            free((char *) Private);
-    }
-    free(GifFile);
-    return GIF_OK;
+static int redcompare( const void *ch1, const void *ch2 ){
+  return (int) PPM_GETR( ((colorhist_vector)ch1)->color ) - 
+    (int) PPM_GETR( ((colorhist_vector)ch2)->color );
 }
 
-/******************************************************************************
-*   Put 2 bytes (word) into the given file:                                   *
-******************************************************************************/
-static int EGifPutWord(int Word, GifFileType *GifFile)
-{
-    char c[2];
-
-    c[0] = Word & 0xff;
-    c[1] = (Word >> 8) & 0xff;
-    if (WRITE(GifFile, c, 2) == 2)
-        return GIF_OK;
-    else
-        return GIF_ERROR;
+static int greencompare( const void *ch1, const void *ch2 ) {
+  return (int) PPM_GETG(((colorhist_vector) ch1)->color ) - 
+    (int) PPM_GETG( ((colorhist_vector)ch2)->color );
 }
 
-/******************************************************************************
-*   Setup the LZ compression for this image:                                  *
-******************************************************************************/
-static int EGifSetupCompress(GifFileType *GifFile)
-{
-    int BitsPerPixel;
-    GifByteType Buf;
-    GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
-
-    /* Test and see what color map to use, and from it # bits per pixel: */
-    if (GifFile->Image.ColorMap)
-        BitsPerPixel = GifFile->Image.ColorMap->BitsPerPixel;
-    else if (GifFile->SColorMap)
-        BitsPerPixel = GifFile->SColorMap->BitsPerPixel;
-    else {
-        _GifError = E_GIF_ERR_NO_COLOR_MAP;
-        return GIF_ERROR;
-    }
+static int bluecompare(const void *ch1, const void *ch2 ) {
+  return (int) PPM_GETB(((colorhist_vector)ch1)->color ) - 
+    (int) PPM_GETB(((colorhist_vector)ch2)->color );
+}
 
-    Buf = BitsPerPixel = (BitsPerPixel < 2 ? 2 : BitsPerPixel);
-    WRITE(GifFile, &Buf, 1);     /* Write the Code size to file. */
-
-    Private->Buf[0] = 0;                          /* Nothing was output yet. */
-    Private->BitsPerPixel = BitsPerPixel;
-    Private->ClearCode = (1 << BitsPerPixel);
-    Private->EOFCode = Private->ClearCode + 1;
-    Private->RunningCode = Private->EOFCode + 1;
-    Private->RunningBits = BitsPerPixel + 1;     /* Number of bits per code. */
-    Private->MaxCode1 = 1 << Private->RunningBits;         /* Max. code + 1. */
-    Private->CrntCode = FIRST_CODE;        /* Signal that this is first one! */
-    Private->CrntShiftState = 0;      /* No information in CrntShiftDWord. */
-    Private->CrntShiftDWord = 0;
-
-   /* Clear hash table and send Clear to make sure the decoder do the same. */
-    _ClearHashTable(Private->HashTable);
-
-    if (EGifCompressOutput(GifFile, Private->ClearCode) == GIF_ERROR) {
-        _GifError = E_GIF_ERR_DISK_IS_FULL;
-        return GIF_ERROR;
-    }
-    return GIF_OK;
+static int sumcompare(const void *b1, const void *b2 ) {
+  return(((box_vector)b2)->sum - ((box_vector)b1)->sum);
 }
 
-/******************************************************************************
-*   The LZ compression routine:                                               *
-*   This version compress the given buffer Line of length LineLen.            *
-*   This routine can be called few times (one per scan line, for example), in *
-* order the complete the whole image.                                         *
-******************************************************************************/
-static int EGifCompressLine(GifFileType *GifFile, GifPixelType *Line,
-                                                                int LineLen)
-{
-    int i = 0, CrntCode, NewCode;
-    unsigned long NewKey;
-    GifPixelType Pixel;
-    GifHashTableType *HashTable;
-    GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
-
-    HashTable = Private->HashTable;
-
-    if (Private->CrntCode == FIRST_CODE)                  /* Its first time! */
-        CrntCode = Line[i++];
+/*
+ * Here is the fun part, the median-cut colormap generator.  This is based
+ * on Paul Heckbert's paper "Color Image Quantization for Frame Buffer
+ * Display", SIGGRAPH '82 Proceedings, page 297.
+ */
+
+static colorhist_vector mediancut( colorhist_vector chv, int colors, 
+				   int sum, pixval maxval, int newcolors ){
+  colorhist_vector colormap;
+  box_vector bv;
+  register int bi, i;
+  int boxes;
+  
+  bv = (box_vector) malloc( sizeof(struct box) * newcolors );
+  colormap =
+    (colorhist_vector) malloc( sizeof(struct colorhist_item) * newcolors );
+  if ( bv == (box_vector) 0 || colormap == (colorhist_vector) 0 )
+    Msg(ERROR,  "GIF: out of memory" );
+  for ( i = 0; i < newcolors; ++i )
+    PPM_ASSIGN( colormap[i].color, 0, 0, 0 );
+  
+  /*
+   * Set up the initial box.
+   */
+  bv[0].ind = 0;
+  bv[0].colors = colors;
+  bv[0].sum = sum;
+  boxes = 1;
+  
+  /*
+   * Main loop: split boxes until we have enough.
+   */
+  while ( boxes < newcolors ){
+    register int indx, clrs;
+    int sm;
+    register int minr, maxr, ming, maxg, minb, maxb, v;
+    int halfsum, lowersum;
+    
+    /*
+    * Find the first splittable box.
+    */
+    for ( bi = 0; bi < boxes; ++bi )
+      if ( bv[bi].colors >= 2 )
+	break;
+    if ( bi == boxes )
+      break;	/* ran out of colors! */
+    indx = bv[bi].ind;
+    clrs = bv[bi].colors;
+    sm = bv[bi].sum;
+    
+    /*
+     * Go through the box finding the minimum and maximum of each
+     * component - the boundaries of the box.
+     */
+    minr = maxr = PPM_GETR( chv[indx].color );
+    ming = maxg = PPM_GETG( chv[indx].color );
+    minb = maxb = PPM_GETB( chv[indx].color );
+    for ( i = 1; i < clrs; ++i ){
+      v = PPM_GETR( chv[indx + i].color );
+      if ( v < minr ) minr = v;
+      if ( v > maxr ) maxr = v;
+      v = PPM_GETG( chv[indx + i].color );
+      if ( v < ming ) ming = v;
+      if ( v > maxg ) maxg = v;
+      v = PPM_GETB( chv[indx + i].color );
+      if ( v < minb ) minb = v;
+      if ( v > maxb ) maxb = v;
+    }
+    
+    /*
+     * Find the largest dimension, and sort by that component.  I have
+     * included two methods for determining the "largest" dimension;
+     * first by simply comparing the range in RGB space, and second
+     * by transforming into luminosities before the comparison.  You
+     * can switch which method is used by switching the commenting on
+     * the LARGE_ defines at the beginning of this source file.
+     */
+#ifdef LARGE_NORM
+    if ( maxr - minr >= maxg - ming && maxr - minr >= maxb - minb )
+      qsort( (char*) &(chv[indx]), clrs, sizeof(struct colorhist_item),
+	     redcompare );
+    else if ( maxg - ming >= maxb - minb )
+      qsort( (char*) &(chv[indx]), clrs, sizeof(struct colorhist_item),
+	     greencompare );
+    else
+      qsort( (char*) &(chv[indx]), clrs, sizeof(struct colorhist_item),
+	     bluecompare );
+#endif 
+
+#ifdef LARGE_LUM
+    pixel p;
+    float rl, gl, bl;
+
+    PPM_ASSIGN(p, maxr - minr, 0, 0);
+    rl = PPM_LUMIN(p);
+    PPM_ASSIGN(p, 0, maxg - ming, 0);
+    gl = PPM_LUMIN(p);
+    PPM_ASSIGN(p, 0, 0, maxb - minb);
+    bl = PPM_LUMIN(p);
+    
+    if ( rl >= gl && rl >= bl )
+      qsort( (char*) &(chv[indx]), clrs, sizeof(struct colorhist_item),
+	     &redcompare );
+    else if ( gl >= bl )
+      qsort( (char*) &(chv[indx]), clrs, sizeof(struct colorhist_item),
+	     &greencompare );
     else
-        CrntCode = Private->CrntCode;     /* Get last code in compression. */
-
-    while (i < LineLen) {                           /* Decode LineLen items. */
-        Pixel = Line[i++];                    /* Get next pixel from stream. */
-       /* Form a new unique key to search hash table for the code combines  */
-       /* CrntCode as Prefix string with Pixel as postfix char.             */
-       NewKey = (((unsigned long) CrntCode) << 8) + Pixel;
-       if ((NewCode = _ExistsHashTable(HashTable, NewKey)) >= 0) {
-           /* This Key is already there, or the string is old one, so       */
-           /* simple take new code as our CrntCode:                         */
-           CrntCode = NewCode;
-       }
-       else {
-           /* Put it in hash table, output the prefix code, and make our    */
-           /* CrntCode equal to Pixel.                                      */
-           if (EGifCompressOutput(GifFile, CrntCode)
-               == GIF_ERROR) {
-               _GifError = E_GIF_ERR_DISK_IS_FULL;
-               return GIF_ERROR;
-           }
-           CrntCode = Pixel;
-
-           /* If however the HashTable if full, we send a clear first and   */
-           /* Clear the hash table.                                         */
-           if (Private->RunningCode >= LZ_MAX_CODE) {
-               /* Time to do some clearance: */
-               if (EGifCompressOutput(GifFile, Private->ClearCode)
-                   == GIF_ERROR) {
-                   _GifError = E_GIF_ERR_DISK_IS_FULL;
-                   return GIF_ERROR;
-               }
-               Private->RunningCode = Private->EOFCode + 1;
-               Private->RunningBits = Private->BitsPerPixel + 1;
-               Private->MaxCode1 = 1 << Private->RunningBits;
-               _ClearHashTable(HashTable);
-           }
-           else {
-               /* Put this unique key with its relative Code in hash table: */
-               _InsertHashTable(HashTable, NewKey, Private->RunningCode++);
-           }
-       }
+      qsort( (char*) &(chv[indx]), clrs, sizeof(struct colorhist_item),
+	     &bluecompare );
+#endif
+    
+    /*
+     * Now find the median based on the counts, so that about half the
+     * pixels (not colors, pixels) are in each subdivision.
+     */
+    lowersum = chv[indx].value;
+    halfsum = sm / 2;
+    for ( i = 1; i < clrs - 1; ++i ){
+      if ( lowersum >= halfsum )
+	break;
+      lowersum += chv[indx + i].value;
+    }
+    
+    /*
+    * Split the box, and sort to bring the biggest boxes to the top.
+    */
+    bv[bi].colors = i;
+    bv[bi].sum = lowersum;
+    bv[boxes].ind = indx + i;
+    bv[boxes].colors = clrs - i;
+    bv[boxes].sum = sm - lowersum;
+    ++boxes;
+    qsort( (char*) bv, boxes, sizeof(struct box), sumcompare );
+  }
 
+  /*
+   * Ok, we've got enough boxes.  Now choose a representative color for
+   * each box.  There are a number of possible ways to make this choice.
+   * One would be to choose the center of the box; this ignores any structure
+   * within the boxes.  Another method would be to average all the colors in
+   * the box - this is the method specified in Heckbert's paper.  A third
+   * method is to average all the pixels in the box.  You can switch which
+   * method is used by switching the commenting on the REP_ defines at
+   * the beginning of this source file.
+   */
+  for ( bi = 0; bi < boxes; ++bi ){
+
+#ifdef REP_CENTER_BOX
+    register int indx = bv[bi].ind;
+    register int clrs = bv[bi].colors;
+    register int minr, maxr, ming, maxg, minb, maxb, v;
+    
+    minr = maxr = PPM_GETR( chv[indx].color );
+    ming = maxg = PPM_GETG( chv[indx].color );
+    minb = maxb = PPM_GETB( chv[indx].color );
+    for ( i = 1; i < clrs; ++i ){
+      v = PPM_GETR( chv[indx + i].color );
+      minr = min( minr, v );
+      maxr = max( maxr, v );
+      v = PPM_GETG( chv[indx + i].color );
+      ming = min( ming, v );
+      maxg = max( maxg, v );
+      v = PPM_GETB( chv[indx + i].color );
+      minb = min( minb, v );
+      maxb = max( maxb, v );
     }
+    PPM_ASSIGN( colormap[bi].color, ( minr + maxr ) / 2, ( ming + maxg ) / 2,
+		( minb + maxb ) / 2 );
+#endif
 
-    /* Preserve the current state of the compression algorithm: */
-    Private->CrntCode = CrntCode;
-
-    if (Private->PixelCount == 0)
-    {
-        /* We are done - output last Code and flush output buffers: */
-        if (EGifCompressOutput(GifFile, CrntCode)
-            == GIF_ERROR) {
-            _GifError = E_GIF_ERR_DISK_IS_FULL;
-            return GIF_ERROR;
-        }
-        if (EGifCompressOutput(GifFile, Private->EOFCode)
-            == GIF_ERROR) {
-            _GifError = E_GIF_ERR_DISK_IS_FULL;
-            return GIF_ERROR;
-        }
-        if (EGifCompressOutput(GifFile, FLUSH_OUTPUT) == GIF_ERROR) {
-            _GifError = E_GIF_ERR_DISK_IS_FULL;
-            return GIF_ERROR;
-        }
+#ifdef REP_AVERAGE_COLORS
+    register int indx = bv[bi].ind;
+    register int clrs = bv[bi].colors;
+    register long r = 0, g = 0, b = 0;
+    
+    for ( i = 0; i < clrs; ++i ){
+      r += PPM_GETR( chv[indx + i].color );
+      g += PPM_GETG( chv[indx + i].color );
+      b += PPM_GETB( chv[indx + i].color );
     }
+    r = r / clrs;
+    g = g / clrs;
+    b = b / clrs;
+    PPM_ASSIGN( colormap[bi].color, r, g, b );
+#endif
 
-    return GIF_OK;
+#ifdef REP_AVERAGE_PIXELS
+    register int indx = bv[bi].ind;
+    register int clrs = bv[bi].colors;
+    register long r = 0, g = 0, b = 0, sum = 0;
+    
+    for ( i = 0; i < clrs; ++i ){
+      r += PPM_GETR( chv[indx + i].color ) * chv[indx + i].value;
+      g += PPM_GETG( chv[indx + i].color ) * chv[indx + i].value;
+      b += PPM_GETB( chv[indx + i].color ) * chv[indx + i].value;
+      sum += chv[indx + i].value;
+    }
+    r = r / sum;
+    if ( r > (long)maxval ) r = maxval;	/* avoid math errors */
+    g = g / sum;
+    if ( g > (long)maxval ) g = maxval;
+    b = b / sum;
+    if ( b > (long)maxval ) b = maxval;
+    PPM_ASSIGN( colormap[bi].color, r, g, b );
+#endif
+  }
+  
+  /*
+   * All done.
+   */
+  return colormap;
 }
 
-/******************************************************************************
-*   The LZ compression output routine:                                        *
-*   This routine is responsible for the compression of the bit stream into    *
-*   8 bits (bytes) packets.                                                   *
-*   Returns GIF_OK if written succesfully.                                    *
-******************************************************************************/
-static int EGifCompressOutput(GifFileType *GifFile, int Code)
-{
-    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
-    int retval = GIF_OK;
-
-    if (Code == FLUSH_OUTPUT) {
-        while (Private->CrntShiftState > 0) {
-            /* Get Rid of what is left in DWord, and flush it. */
-            if (EGifBufferedOutput(GifFile, Private->Buf,
-                Private->CrntShiftDWord & 0xff) == GIF_ERROR)
-                    retval = GIF_ERROR;
-            Private->CrntShiftDWord >>= 8;
-            Private->CrntShiftState -= 8;
-        }
-        Private->CrntShiftState = 0;                       /* For next time. */
-        if (EGifBufferedOutput(GifFile, Private->Buf,
-            FLUSH_OUTPUT) == GIF_ERROR)
-                retval = GIF_ERROR;
-    }
-    else {
-        Private->CrntShiftDWord |= ((long) Code) << Private->CrntShiftState;
-        Private->CrntShiftState += Private->RunningBits;
-        while (Private->CrntShiftState >= 8) {
-            /* Dump out full bytes: */
-            if (EGifBufferedOutput(GifFile, Private->Buf,
-                Private->CrntShiftDWord & 0xff) == GIF_ERROR)
-                    retval = GIF_ERROR;
-            Private->CrntShiftDWord >>= 8;
-            Private->CrntShiftState -= 8;
-        }
-    }
 
-    /* If code cannt fit into RunningBits bits, must raise its size. Note */
-    /* however that codes above 4095 are used for special signaling.      */
-    if (Private->RunningCode >= Private->MaxCode1 && Code <= 4095) {
-       Private->MaxCode1 = 1 << ++Private->RunningBits;
-    }
 
-    return retval;
-}
+/* ------------------------------------------------------------------
+   GL2GIF public routine
+   ------------------------------------------------------------------ */
+
+#define FS_SCALE   1024
+#define MAXCOL2    32767
+
+void create_gif(FILE *outfile, int width, int height, 
+		int dither, int sort, int interlace, 
+		int transparency, int bg_r, int bg_g, int bg_b){
+
+  int i,j,k,transparent,rows,cols;
+  pixel transcolor;
+  colorhist_vector chv, colormap;
+  int BitsPerPixel, usehash;
+  unsigned char *RedBuffer, *GreenBuffer, *BlueBuffer;
+  pixval maxval=MAXCOL2, newmaxval;
+  colorhash_table cht;
+  register pixel* pP;
+  register int col, row, limitcol, ind;
+  int newcolors=255;
+  long *thisrerr, *nextrerr, *thisgerr, *nextgerr;
+  long *thisberr, *nextberr, *temperr;
+  register long sr=0, sg=0, sb=0, err=0;
+  int fs_direction;
+
+  /* This is stupid, but I couldn't figure out how to pack the data
+   directly from OpenGL frame buffer into the approproate format into
+   unsigned long pixel[][]. */
+
+  glPixelStorei(GL_PACK_ALIGNMENT,1);
+  glPixelStorei(GL_UNPACK_ALIGNMENT,1);
+  RedBuffer = (unsigned char *)Malloc(height*width*sizeof(unsigned char));
+  GreenBuffer = (unsigned char *)Malloc(height*width*sizeof(unsigned char));
+  BlueBuffer = (unsigned char *)Malloc(height*width*sizeof(unsigned char));
+  glReadPixels(0,0,width,height,GL_RED,GL_UNSIGNED_BYTE,RedBuffer);
+  glReadPixels(0,0,width,height,GL_GREEN,GL_UNSIGNED_BYTE,GreenBuffer);
+  glReadPixels(0,0,width,height,GL_BLUE,GL_UNSIGNED_BYTE,BlueBuffer);
 
-/******************************************************************************
-*   This routines buffers the given characters until 255 characters are ready *
-* to be output. If Code is equal to -1 the buffer is flushed (EOF).           *
-*   The buffer is Dumped with first byte as its size, as GIF format requires. *
-*   Returns GIF_OK if written succesfully.                                    *
-******************************************************************************/
-static int EGifBufferedOutput(GifFileType *GifFile, GifByteType *Buf, int c)
-{
-    if (c == FLUSH_OUTPUT) {
-        /* Flush everything out. */
-        if (Buf[0] != 0 && WRITE(GifFile, Buf, Buf[0]+1) != (unsigned)(Buf[0] + 1))
-        {
-            _GifError = E_GIF_ERR_WRITE_FAILED;
-            return GIF_ERROR;
-        }
-        /* Mark end of compressed data, by an empty block (see GIF doc): */
-        Buf[0] = 0;
-        if (WRITE(GifFile, Buf, 1) != 1)
-        {
-            _GifError = E_GIF_ERR_WRITE_FAILED;
-            return GIF_ERROR;
-        }
-    }
-    else {
-        if (Buf[0] == 255) {
-            /* Dump out this buffer - it is full: */
-            if (WRITE(GifFile, Buf, Buf[0] + 1) != (unsigned)(Buf[0] + 1))
-            {
-                _GifError = E_GIF_ERR_WRITE_FAILED;
-                return GIF_ERROR;
-            }
-            Buf[0] = 0;
-        }
-        Buf[++Buf[0]] = c;
-    }
+  static_pixels = (pixel**)Malloc(height*sizeof(pixel*));
+  for(i = 0 ; i<height ; i++)
+    static_pixels[i] = (pixel*)Malloc(3*width*sizeof(pixel));
 
-    return GIF_OK;
-}
+  for(i = 0 ; i<height ; i++)
+    for(j = 0 ; j<width ; j++)
+      PPM_ASSIGN(static_pixels[height-1-i][j], 
+		 RedBuffer[i*width+j],
+		 GreenBuffer[i*width+j],
+		 BlueBuffer[i*width+j]);
 
-static void QuitGifError(GifFileType *GifFile)
-{
-  PrintGifError();
-  if (GifFile != NULL) EGifCloseFile(GifFile);
-}
+  Free(RedBuffer);
+  Free(GreenBuffer);
+  Free(BlueBuffer);
 
-static void SaveGif(FILE *fp,
-                    GifByteType *OutputBuffer,
-                    ColorMapObject *OutputColorMap,
-                    int ExpColorMapSize, int Width, int Height){
-  int i;
-  GifFileType *GifFile;
-  GifByteType *Ptr;
+  /* Try to compute color histogram */
 
-  if ((GifFile = EGifOpenFileHandle(fp, 1)) == NULL){
-    QuitGifError(GifFile);
-    return;
-  }
+  chv = ppm_computecolorhist( static_pixels, width, height, MAX_GIFCOLORS, 
+			      &static_nbcolors );
 
-  if (EGifPutScreenDesc(GifFile, Width, Height, ExpColorMapSize, 0, OutputColorMap) == GIF_ERROR){
-    QuitGifError(GifFile);
-    return;
-  }
 
-  if (EGifPutImageDesc(GifFile, 0, 0, Width, Height, FALSE, NULL) == GIF_ERROR){
-    QuitGifError(GifFile);
-    return;
-  }
+  /* Fuck, there are more than 256 colors in the picture: we need to quantize */
 
-  Ptr = &OutputBuffer[(Height-1)*Width] ;
-  for (i = 0; i < Height; i++) {
-    if (EGifPutLine(GifFile, Ptr, Width) == GIF_ERROR){
-      QuitGifError(GifFile);
-      return;
+  if ( chv == (colorhist_vector) 0 ){
+
+    Msg(DEBUG, "GIF: Too many colors in image");
+    
+    rows = height ;
+    cols = width ;
+
+    while(1){
+      Msg(DEBUG, "GIF: making histogram..." );
+      chv = ppm_computecolorhist(static_pixels, width, height, MAXCOL2, 
+				 &static_nbcolors );
+      if ( chv != (colorhist_vector) 0 )
+	break;
+      Msg(DEBUG, "GIF: still too many colors!" );
+      newmaxval = maxval / 2;
+      Msg(DEBUG, "GIF: scaling colors from maxval=%d to maxval=%d to improve clustering...",
+	  maxval, newmaxval );
+      for ( row = 0; row < rows; ++row )
+	for ( col = 0, pP = static_pixels[row]; col < cols; ++col, ++pP )
+	  PPM_DEPTH( *pP, *pP, maxval, newmaxval );
+      maxval = newmaxval;
     }
-    Ptr -= Width;
-  }
+    Msg(DEBUG, "GIF: %d colors found", static_nbcolors );
+    Msg(DEBUG, "GIF: choosing %d colors...", newcolors );
+    colormap = mediancut( chv, static_nbcolors, rows * cols, maxval, newcolors );
+
+    cht = ppm_alloccolorhash( );
+
+    ppm_freecolorhist( chv );
+
+    /* map the colors in the image to their closest match in the new colormap */
+    Msg(DEBUG, "GIF: mapping image to new colors..." );
+    usehash = 1;
+
+    if ( dither ){
+      Msg(DEBUG, "GIF: Floyd-Steinberg dithering is selected..." );
+      /* Initialize Floyd-Steinberg error vectors. */
+      thisrerr = (long*) Malloc( (cols + 2)* sizeof(long) );
+      nextrerr = (long*) Malloc( (cols + 2)* sizeof(long) );
+      thisgerr = (long*) Malloc( (cols + 2)* sizeof(long) );
+      nextgerr = (long*) Malloc( (cols + 2)* sizeof(long) );
+      thisberr = (long*) Malloc( (cols + 2)* sizeof(long) );
+      nextberr = (long*) Malloc( (cols + 2)* sizeof(long) );
+      /* srand( (int) ( time( 0 ) ^ getpid( ) ) ); */
+      for ( col = 0; col < cols + 2; ++col ){
+	thisrerr[col] = rand( ) % ( FS_SCALE * 2 ) - FS_SCALE;
+	thisgerr[col] = rand( ) % ( FS_SCALE * 2 ) - FS_SCALE;
+	thisberr[col] = rand( ) % ( FS_SCALE * 2 ) - FS_SCALE;
+	/* (random errors in [-1 .. 1]) */
+      }
+      fs_direction = 1;
+    }
+    for ( row = 0; row < rows; ++row ){
+
+      if ( dither )
+	for ( col = 0; col < cols + 2; ++col )
+	  nextrerr[col] = nextgerr[col] = nextberr[col] = 0;
+
+      if ( ( ! dither ) || fs_direction ){
+	col = 0;
+	limitcol = cols;
+	pP = static_pixels[row];
+      }
+      else{
+	col = cols - 1;
+	limitcol = -1;
+	pP = &(static_pixels[row][col]);
+      }
+
+      do{
+
+	if ( dither ){
+	  /* Use Floyd-Steinberg errors to adjust actual color. */
+	  sr = PPM_GETR(*pP) + thisrerr[col + 1] / FS_SCALE;
+	  sg = PPM_GETG(*pP) + thisgerr[col + 1] / FS_SCALE;
+	  sb = PPM_GETB(*pP) + thisberr[col + 1] / FS_SCALE;
+	  if ( sr < 0 ) sr = 0;
+	  else if ( sr > (long)maxval ) sr = maxval;
+	  if ( sg < 0 ) sg = 0;
+	  else if ( sg > (long)maxval ) sg = maxval;
+	  if ( sb < 0 ) sb = 0;
+	  else if ( sb > (long)maxval ) sb = maxval;
+	  PPM_ASSIGN( *pP, sr, sg, sb );
+	}
+
+	/* Check hash table to see if we have already matched this color. */
+	ind = ppm_lookupcolor( cht, pP );
+	if ( ind == -1 ){ /* No; search colormap for closest match. */
+	  register int i, r1, g1, b1, r2, g2, b2;
+	  register long dist, newdist;
+	  r1 = PPM_GETR( *pP );
+	  g1 = PPM_GETG( *pP );
+	  b1 = PPM_GETB( *pP );
+	  dist = 2000000000;
+	  for ( i = 0; i < newcolors; ++i ){
+	    r2 = PPM_GETR( colormap[i].color );
+	    g2 = PPM_GETG( colormap[i].color );
+	    b2 = PPM_GETB( colormap[i].color );
+	    newdist =
+	      ( r1 - r2 ) * ( r1 - r2 ) +
+	      ( g1 - g2 ) * ( g1 - g2 ) +
+	      ( b1 - b2 ) * ( b1 - b2 );
+	    if ( newdist < dist ){
+	      ind = i;
+	      dist = newdist;
+	    }
+	  }
+	  if ( usehash ){
+	    if ( ppm_addtocolorhash( cht, pP, ind ) < 0 ){
+	      Msg(WARNING, "GIF: Out of memory adding to hash table, proceeding without it");
+	      usehash = 0;
+	    }
+	  }
+	}
+	
+	if ( dither ){
+	  /* Propagate Floyd-Steinberg error terms. */
+	  if ( fs_direction ){
+	    err = ( sr - (long) PPM_GETR( colormap[ind].color ) ) * FS_SCALE;
+	    thisrerr[col + 2] += ( err * 7 ) / 16;
+	    nextrerr[col    ] += ( err * 3 ) / 16;
+	    nextrerr[col + 1] += ( err * 5 ) / 16;
+	    nextrerr[col + 2] += ( err     ) / 16;
+	    err = ( sg - (long) PPM_GETG( colormap[ind].color ) ) * FS_SCALE;
+	    thisgerr[col + 2] += ( err * 7 ) / 16;
+	    nextgerr[col    ] += ( err * 3 ) / 16;
+	    nextgerr[col + 1] += ( err * 5 ) / 16;
+	    nextgerr[col + 2] += ( err     ) / 16;
+	    err = ( sb - (long) PPM_GETB( colormap[ind].color ) ) * FS_SCALE;
+	    thisberr[col + 2] += ( err * 7 ) / 16;
+	    nextberr[col    ] += ( err * 3 ) / 16;
+	    nextberr[col + 1] += ( err * 5 ) / 16;
+	    nextberr[col + 2] += ( err     ) / 16;
+	  }
+	  else{
+	    err = ( sr - (long) PPM_GETR( colormap[ind].color ) ) * FS_SCALE;
+	    thisrerr[col    ] += ( err * 7 ) / 16;
+	    nextrerr[col + 2] += ( err * 3 ) / 16;
+	    nextrerr[col + 1] += ( err * 5 ) / 16;
+	    nextrerr[col    ] += ( err     ) / 16;
+	    err = ( sg - (long) PPM_GETG( colormap[ind].color ) ) * FS_SCALE;
+	    thisgerr[col    ] += ( err * 7 ) / 16;
+	    nextgerr[col + 2] += ( err * 3 ) / 16;
+	    nextgerr[col + 1] += ( err * 5 ) / 16;
+	    nextgerr[col    ] += ( err     ) / 16;
+	    err = ( sb - (long) PPM_GETB( colormap[ind].color ) ) * FS_SCALE;
+	    thisberr[col    ] += ( err * 7 ) / 16;
+	    nextberr[col + 2] += ( err * 3 ) / 16;
+	    nextberr[col + 1] += ( err * 5 ) / 16;
+	    nextberr[col    ] += ( err     ) / 16;
+	  }
+	}
+	
+	*pP = colormap[ind].color;
+
+	if ( ( ! dither ) || fs_direction ){
+	  ++col;
+	  ++pP;
+	}
+	else{
+	  --col;
+	  --pP;
+	}
+      }
+      while ( col != limitcol );
+      
+      if ( dither ){
+	temperr = thisrerr;
+	thisrerr = nextrerr;
+	nextrerr = temperr;
+	temperr = thisgerr;
+	thisgerr = nextgerr;
+	nextgerr = temperr;
+	temperr = thisberr;
+	thisberr = nextberr;
+	nextberr = temperr;
+	fs_direction = ! fs_direction;
+      }
 
-  if (EGifCloseFile(GifFile) == GIF_ERROR)
-    QuitGifError(GifFile);
-}
+    }
 
-void create_gif(FILE *fp, int width, int height){
-  GifByteType *RedBuffer, *GreenBuffer, *BlueBuffer, *OutputBuffer = NULL;
-  ColorMapObject *OutputColorMap = NULL;
+    if(cht) ppm_freecolorhash(cht);
+    if(dither){
+      Free(thisrerr);
+      Free(nextrerr);
+      Free(thisgerr);
+      Free(nextgerr);
+      Free(thisberr);
+      Free(nextberr);
+    }
+    chv = ppm_computecolorhist( static_pixels, width, height, MAX_GIFCOLORS,
+				&static_nbcolors );
 
-  _GifError = 0;
-  ExpNumOfColors = 8;
-  ColorMapSize = 256;
-  
-  RedBuffer = (unsigned char *)malloc(height*width*sizeof(unsigned char));
-  GreenBuffer = (unsigned char *)malloc(height*width*sizeof(unsigned char));
-  BlueBuffer = (unsigned char *)malloc(height*width*sizeof(unsigned char));
+  }
+
+  /* We now have a colormap of maximum 256 colors */
 
-  if(!RedBuffer || !GreenBuffer || !BlueBuffer){
-    fprintf(stderr, "Error: Failed to allocate memory for RGB Buffers\n");
-    return;
+  for ( i = 0; i < static_nbcolors; ++i ){
+    static_red[i] = PPM_GETR( chv[i].color );
+    static_green[i] = PPM_GETG( chv[i].color );
+    static_blue[i] = PPM_GETB( chv[i].color );
   }
 
-  glReadPixels(0,0,width,height,GL_RED,GL_UNSIGNED_BYTE,RedBuffer);
-  glReadPixels(0,0,width,height,GL_GREEN,GL_UNSIGNED_BYTE,GreenBuffer);
-  glReadPixels(0,0,width,height,GL_BLUE,GL_UNSIGNED_BYTE,BlueBuffer);
-  
-  if (!(OutputColorMap = MakeMapObject(ColorMapSize, NULL))){
-    fprintf(stderr, "Warning: Failed to allocate memory for ColorMap\n");
-    return;
+  /* Sort the colormap */
+  for (i=0 ; i<static_nbcolors ; i++)
+    static_permi[i] = i;
+  if (sort) {
+    Msg(DEBUG, "GIF: sorting colormap");
+    for (i=0 ; i<static_nbcolors ; i++)
+      for (j=i+1 ; j<static_nbcolors ; j++)
+	if (((static_red[i]*MAX_GIFCOLORS)+static_green[i])*MAX_GIFCOLORS+static_blue[i] >
+	    ((static_red[j]*MAX_GIFCOLORS)+static_green[j])*MAX_GIFCOLORS+static_blue[j]) {
+	  k = static_permi[i]; static_permi[i] = static_permi[j]; static_permi[j] = k;
+	  k = static_red[i]; static_red[i] = static_red[j]; static_red[j] = k;
+	  k = static_green[i]; static_green[i] = static_green[j]; static_green[j] = k;
+	  k = static_blue[i]; static_blue[i] = static_blue[j]; static_blue[j] = k; 
+	} 
   }
+  for (i=0 ; i<static_nbcolors ; i++)
+    static_perm[static_permi[i]]=i;
+  
+  BitsPerPixel = colorstobpp( static_nbcolors );
 
-  if(!(OutputBuffer = (GifByteType *) malloc(width * height * sizeof(GifByteType)))){
-    fprintf(stderr, "Error: Failed to allocate memory for Output Buffer\n");
-    return;
+  /* And make a hash table for fast lookup. */
+  static_cht = ppm_colorhisttocolorhash( chv, static_nbcolors );
+  ppm_freecolorhist( chv );
+  
+  /* figure out the transparent colour index */
+  if (transparency) {
+    PPM_ASSIGN(transcolor, bg_r, bg_g, bg_b);
+    transparent = ppm_lookupcolor( static_cht, &transcolor );
+    if (transparent == -1)
+      transparent = closestcolor( transcolor );
+    else
+      transparent = static_perm[transparent];
   }
+  else
+    transparent = -1 ;
 
-  if (QuantizeBuffer(width, height, &ColorMapSize,
-                     RedBuffer, GreenBuffer, BlueBuffer,
-                     OutputBuffer, OutputColorMap->Colors) == GIF_ERROR)
-    fprintf(stderr, "Warning: Quantize Buffer Failed\n");
+  /* All set, let's do it. */
+  GIFEncode(outfile, width, height, interlace, 0, transparent, BitsPerPixel,
+	    static_red, static_green, static_blue, GetPixel );
+
+  for(i = 0 ; i<height ; i++)
+    Free(static_pixels[i]);
+  Free(static_pixels);
 
-  free(RedBuffer);
-  free(GreenBuffer);
-  free(BlueBuffer);
-  
-  SaveGif(fp, OutputBuffer, OutputColorMap, ExpNumOfColors, width, height);
 }
 
diff --git a/Graphics/gl2gif.h b/Graphics/gl2gif.h
index bbad10d3e3b8ec77e33a1a2f30aedd80629b7d71..73284befb1949cca7372cb8d926b8aceab19a557 100644
--- a/Graphics/gl2gif.h
+++ b/Graphics/gl2gif.h
@@ -1,150 +1,58 @@
 #ifndef _GL2GIF_H_
 #define _GL2GIF_H_
 
-#define GIF_ERROR       0
-#define GIF_OK          1
+#define MAX_GIFCOLORS  256
 
-#ifndef TRUE
-#define TRUE            1
-#define FALSE           0
-#endif
+/* New types */
+
+typedef unsigned int   pixval;
+typedef unsigned long  pixel;
+typedef int            code_int;
+typedef long int       count_int;
+
+/* PPM handling */
+
+#define PPM_MAXMAXVAL  1023
+
+#define PPM_GETR(p)    (((p) & 0x3ff00000) >> 20)
+#define PPM_GETG(p)    (((p) & 0xffc00) >> 10)
+#define PPM_GETB(p)    ((p) & 0x3ff)
+#define PPM_EQUAL(p,q) ((p) == (q))
+
+#define PPM_ASSIGN(p,red,grn,blu) \
+  (p) = ((pixel) (red) << 20) | ((pixel) (grn) << 10) | (pixel) (blu)
+
+#define PPM_LUMIN(p) ( 0.299 * PPM_GETR(p) + 0.587 * PPM_GETG(p) + 0.114 * PPM_GETB(p) )
+
+#define PPM_DEPTH(newp,p,oldmaxval,newmaxval) \
+  PPM_ASSIGN( (newp), \
+    ( (int) PPM_GETR(p) * (newmaxval) + (oldmaxval) / 2 ) / (oldmaxval), \
+    ( (int) PPM_GETG(p) * (newmaxval) + (oldmaxval) / 2 ) / (oldmaxval), \
+    ( (int) PPM_GETB(p) * (newmaxval) + (oldmaxval) / 2 ) / (oldmaxval) )
+
+/* Color histogram stuff */
+
+typedef struct colorhist_item* colorhist_vector;
+struct colorhist_item {
+  pixel color;
+  int value;
+};
+
+typedef struct colorhist_list_item* colorhist_list;
+struct colorhist_list_item {
+  struct colorhist_item ch;
+  colorhist_list next;
+};
+
+/* Color hash table stuff */
+
+typedef colorhist_list* colorhash_table;
+
+/* Public function */
+
+void create_gif(FILE *outfile, int width, int height, 
+		int dither, int sort, int interlace, 
+		int transparency, int r, int g, int b);
 
-#define VoidPtr void *
-
-typedef unsigned char   GifPixelType;
-typedef unsigned char   GifByteType;
-
-typedef struct GifColorType {
-  GifByteType Red, Green, Blue;
-} GifColorType;
-
-typedef struct ColorMapObject{
-  int   ColorCount;
-  int BitsPerPixel;
-  GifColorType *Colors;  /* on malloc(3) heap */
-} ColorMapObject;
-
-typedef struct GifImageDesc {
-  int Left, Top, Width, Height ; /* Current image dimensions. */
-  int Interlace;                 /* Sequential/Interlaced lines. */
-  ColorMapObject *ColorMap;      /* The local color map */
-} GifImageDesc;
-
-typedef struct GifFileType {
-  int SWidth, SHeight;            /* Screen dimensions. */
-  int SColorResolution;           /* How many colors can we generate? */
-  int SBackGroundColor;           /* I hope you understand this one... */
-  ColorMapObject *SColorMap;      /* NULL if not exists. */
-  int ImageCount;                 /* Number of current image */
-  GifImageDesc Image;             /* Block describing current image */
-  VoidPtr Private;                /* Don't mess with this! */
-} GifFileType;
-
-typedef enum {
-  UNDEFINED_RECORD_TYPE,
-  SCREEN_DESC_RECORD_TYPE,
-  IMAGE_DESC_RECORD_TYPE,       /* Begin with ',' */
-  TERMINATE_RECORD_TYPE         /* Begin with ';' */
-} GifRecordType;
-
-#define HT_SIZE                 8192       /* 12bits = 4096 or twice as big! */
-#define HT_KEY_MASK             0x1FFF                        /* 13bits keys */
-#define HT_KEY_NUM_BITS         13                            /* 13bits keys */
-#define HT_MAX_KEY              8191    /* 13bits - 1, maximal code possible */
-#define HT_MAX_CODE             4095    /* Biggest code possible in 12 bits. */
-
-/* The 32 bits of the long are divided into two parts for the key & code:   */
-/* 1. The code is 12 bits as our compression algorithm is limited to 12bits */
-/* 2. The key is 12 bits Prefix code + 8 bit new char or 20 bits.           */
-#define HT_GET_KEY(l)   (l >> 12)
-#define HT_GET_CODE(l)  (l & 0x0FFF)
-#define HT_PUT_KEY(l)   (l << 12)
-#define HT_PUT_CODE(l)  (l & 0x0FFF)
-
-typedef struct GifHashTableType {
-  unsigned long HTable[HT_SIZE];
-} GifHashTableType;
-
-#define LZ_MAX_CODE     4095            /* Biggest code possible in 12 bits. */
-#define LZ_BITS         12
-
-#define FLUSH_OUTPUT            4096    /* Impossible code, to signal flush. */
-#define FIRST_CODE              4097    /* Impossible code, to signal first. */
-#define NO_SUCH_CODE            4098    /* Impossible code, to signal empty. */
-
-#define FILE_STATE_WRITE    0x01
-#define FILE_STATE_SCREEN   0x02
-#define FILE_STATE_IMAGE    0x04
-#define FILE_STATE_READ     0x08
-
-#define IS_READABLE(Private)    (Private->FileState & FILE_STATE_READ)
-#define IS_WRITEABLE(Private)   (Private->FileState & FILE_STATE_WRITE)
-
-typedef struct GifFilePrivateType {
-  int FileState;
-  int   FileHandle;                          /* Where all this data goes to! */
-  int   BitsPerPixel;       /* Bits per pixel (Codes uses at least this + 1). */
-  int   ClearCode;                                     /* The CLEAR LZ code. */
-  int   EOFCode;                                         /* The EOF LZ code. */
-  int   RunningCode;                /* The next code algorithm can generate. */
-  int   RunningBits;/* The number of bits required to represent RunningCode. */
-  int   MaxCode1;  /* 1 bigger than max. possible code, in RunningBits bits. */
-  int   LastCode;                       /* The code before the current code. */
-  int   CrntCode;                                 /* Current algorithm code. */
-  int   StackPtr;                        /* For character stack (see below). */
-  int   CrntShiftState;                 /* Number of bits in CrntShiftDWord. */
-  unsigned long CrntShiftDWord;     /* For bytes decomposition into codes. */
-  unsigned long PixelCount;                    /* Number of pixels in image. */
-  FILE *File;                                             /* File as stream. */
-  GifByteType Buf[256];        /* Compressed input is buffered here. */
-  GifByteType Stack[LZ_MAX_CODE];        /* Decoded pixels are stacked here. */
-  GifByteType Suffix[LZ_MAX_CODE+1];           /* So we can trace the codes. */
-  int Prefix[LZ_MAX_CODE+1];
-  GifHashTableType *HashTable;
-} GifFilePrivateType;
-
-
-#define E_GIF_ERR_OPEN_FAILED   1               /* And EGif possible errors. */
-#define E_GIF_ERR_WRITE_FAILED  2
-#define E_GIF_ERR_HAS_SCRN_DSCR 3
-#define E_GIF_ERR_HAS_IMAG_DSCR 4
-#define E_GIF_ERR_NO_COLOR_MAP  5
-#define E_GIF_ERR_DATA_TOO_BIG  6
-#define E_GIF_ERR_NOT_ENOUGH_MEM 7
-#define E_GIF_ERR_DISK_IS_FULL  8
-#define E_GIF_ERR_CLOSE_FAILED  9
-#define E_GIF_ERR_NOT_WRITEABLE 10
-
-/* Provate functions */
-
-GifHashTableType *_InitHashTable(void);
-void _ClearHashTable(GifHashTableType *HashTable);
-void _InsertHashTable(GifHashTableType *HashTable, unsigned long Key, int Code);
-int _ExistsHashTable(GifHashTableType *HashTable, unsigned long Key);
-
-GifFileType *EGifOpenFileHandle(int GifFileHandle);
-void EGifSetGifVersion(char *Version);
-int EGifPutScreenDesc(GifFileType *GifFile,
-                      int GifWidth, int GifHeight, int GifColorRes, int GifBackGround,
-                      ColorMapObject *GifColorMap);
-int EGifPutImageDesc(GifFileType *GifFile,
-                     int GifLeft, int GifTop, int Width, int GifHeight, int GifInterlace,
-                     ColorMapObject *GifColorMap);
-int EGifPutLine(GifFileType *GifFile, GifPixelType *GifLine, int GifLineLen);
-int EGifCloseFile(GifFileType *GifFile);
-
-int QuantizeBuffer(int Width, int Height, int *ColorMapSize,
-                   GifByteType *RedInput, GifByteType *GreenInput, GifByteType *BlueInput,
-                   GifByteType *OutputBuffer, GifColorType *OutputColorMap);
-
-extern void PrintGifError(void);
-extern int GifLastError(void);
-extern ColorMapObject *MakeMapObject(int ColorCount, GifColorType *ColorMap);
-extern void FreeMapObject(ColorMapObject *Object);
-extern int BitSize(int n);
-
-/* Public functions */
-
-void create_gif(FILE *fp, int width, int height);
 
 #endif