diff --git a/src/modules/Image/togif.c b/src/modules/Image/togif.c
index 89b9d8890a9051b9ec548a7f52c96eafc91ab90c..16cb3cc9d5ad9683fadc79b28d60ae3ffd81a73e 100644
--- a/src/modules/Image/togif.c
+++ b/src/modules/Image/togif.c
@@ -4,7 +4,7 @@ togif
 
 Pontus Hagland, law@infovav.se
 
-$Id: togif.c,v 1.13 1997/05/28 21:00:48 mirar Exp $ 
+$Id: togif.c,v 1.14 1997/05/29 17:03:27 mirar Exp $ 
 
 */
 
@@ -21,7 +21,6 @@ $Id: togif.c,v 1.13 1997/05/28 21:00:48 mirar Exp $
 #include "stralloc.h"
 #include "global.h"
 #include "threads.h"
-#include "types.h"
 #include "pike_macros.h"
 #include "object.h"
 #include "constants.h"
@@ -30,6 +29,7 @@ $Id: togif.c,v 1.13 1997/05/28 21:00:48 mirar Exp $
 #include "array.h"
 #include "error.h"
 #include "dynamic_buffer.h"
+#include "operators.h"
 
 #include "image.h"
 #include "lzw.h"
@@ -185,138 +185,6 @@ void image_floyd_steinberg(rgb_group *rgb,int xsize,
    }
 }
 		     
-
-struct pike_string *
-   image_encode_gif(struct image *img,struct colortable *ct,
-		    rgb_group *transparent,int fs,int closest)
-{
-   dynamic_buffer buf;
-   long i;
-   rgb_group *rgb;
-   struct lzw lzw;
-   int colors,bpp;
-
-CHRONO("image_encode_gif begin");
-   
-   buf.s.str=NULL;
-   initialize_buf(&buf);
-
-   colors=4; bpp=2;
-   while (colors<ct->numcol) { colors<<=1; bpp++; }
-
-   low_my_binary_strcat(transparent?"GIF89a":"GIF87a",6,&buf);
-   buf_word((unsigned short)img->xsize,&buf);
-   buf_word((unsigned short)img->ysize,&buf);
-   low_my_putchar( (char)(0xf0|(bpp-1)), &buf);
-   /* | global colormap | 3 bits color res | sort | 3 bits bpp */
-   /* color res is'nt cared of */
-
-   low_my_putchar( 0, &buf ); /* background color */
-   low_my_putchar( 0, &buf ); /* just zero */
-
-   for (i=0; i<ct->numcol; i++)
-   {
-      low_my_putchar(ct->clut[i].r,&buf);
-      low_my_putchar(ct->clut[i].g,&buf);
-      low_my_putchar(ct->clut[i].b,&buf);
-   }
-
-   for (; i<colors; i++)
-   {
-      low_my_putchar(0,&buf);
-      low_my_putchar(0,&buf);
-      low_my_putchar(0,&buf);
-   }
-
-   if (transparent)
-   {
-      i=colortable_rgb(ct,*transparent);
-
-      low_my_putchar( '!', &buf );  /* extras */
-      low_my_putchar( 0xf9, &buf ); /* transparency */
-      low_my_putchar( 4, &buf );
-      low_my_putchar( 1, &buf );
-      low_my_putchar( 0, &buf );
-      low_my_putchar( 0, &buf );
-      low_my_putchar( i, &buf );
-      low_my_putchar( 0, &buf );
-   }
-
-
-   low_my_putchar( ',', &buf ); /* image separator */
-
-   buf_word(0,&buf); /* leftofs */
-   buf_word(0,&buf); /* topofs */
-   buf_word(img->xsize,&buf); /* width */
-   buf_word(img->ysize,&buf); /* height */
-
-   low_my_putchar(0x00, &buf); 
-      /* not interlaced (interlaced == 0x40) */
-      /* no local colormap ( == 0x80) */
-
-   low_my_putchar( bpp, &buf ); /* bits per pixel , or min 2 */
-   
-   i=img->xsize*img->ysize;
-   rgb=img->img;
-
-CHRONO("image_encode_gif header done");
-
-THREADS_ALLOW();
-   lzw_init(&lzw,bpp);
-   if (!fs)
-      while (i--) lzw_add(&lzw,colortable_rgb(ct,*(rgb++)));
-   else
-   {
-      rgbl_group *errb;
-      rgb_group corgb;
-      int w,*cres,j;
-      errb=(rgbl_group*)xalloc(sizeof(rgbl_group)*img->xsize);
-      cres=(int*)xalloc(sizeof(int)*img->xsize);
-      for (i=0; i<img->xsize; i++)
-	errb[i].r=(rand()%(FS_SCALE*2+1))-FS_SCALE,
-	errb[i].g=(rand()%(FS_SCALE*2+1))-FS_SCALE,
-	errb[i].b=(rand()%(FS_SCALE*2+1))-FS_SCALE;
-
-      w=0;
-      i=img->ysize;
-      while (i--)
-      {
-	 image_floyd_steinberg(rgb,img->xsize,errb,w=!w,cres,ct,closest);
-	 for (j=0; j<img->xsize; j++)
-	    lzw_add(&lzw,cres[j]);
-	 rgb+=img->xsize;
-      }
-
-      free(errb);
-      free(cres);
-   }
-
-   lzw_write_last(&lzw);
-
-CHRONO("lzw done");
-
-   for (i=0; i<(int)lzw.outpos; i+=254)
-   {
-      int wr;
-      if (i+254>(int)lzw.outpos) wr=lzw.outpos-i;
-      else wr=254;
-      low_my_putchar( (unsigned char)wr, &buf ); /* bytes in chunk */
-      low_my_binary_strcat( (char *) lzw.out+i, wr, &buf );
-   }
-   low_my_putchar( 0, &buf ); /* terminate stream */
-
-CHRONO("image_encode_gif wrote ok");
-
-   lzw_quit(&lzw);
-
-   low_my_putchar( ';', &buf ); /* end gif file */
-
-CHRONO("image_encode_gif done");
-THREADS_DISALLOW();
-
-   return low_free_buf(&buf);
-}
-
 #define STD_ARENA_SIZE 16384
 
 int image_decode_gif(struct image *dest,struct image *dest_alpha,
@@ -474,7 +342,9 @@ void image_fromgif(INT32 args)
    if (THIS->img) free(THIS->img);
    THIS->img=NULL;
 
-   image_decode_gif(THIS,NULL,sp[-args].u.string->str,sp[-args].u.string->len);
+   image_decode_gif(THIS,NULL,
+		    (unsigned char*)sp[-args].u.string->str,
+		    sp[-args].u.string->len);
 
    pop_n_elems(args);
    THISOBJ->refs++;
@@ -501,87 +371,6 @@ static INLINE void getrgb(struct image *img,
       img->alpha=0;
 }
 
-/*
-**! method string togif()
-**! method string togif(int num_colors)
-**! method string togif(array(array(int)) colors)
-**! method string togif(int trans_r,int trans_g,int trans_b)
-**! method string togif(int num_colors,int trans_r,int trans_g,int trans_b)
-**! method string togif(array(array(int)) colors,int trans_r,int trans_g,int trans_b)
-**! method string togif_fs()
-**! method string togif_fs(int num_colors)
-**! method string togif_fs(array(array(int)) colors)
-**! method string togif_fs(int trans_r,int trans_g,int trans_b)
-**! method string togif_fs(int num_colors,int trans_r,int trans_g,int trans_b)
-**! method string togif_fs(array(array(int)) colors,int trans_r,int trans_g,int trans_b)
-**!	Makes GIF data. The togif_fs variant uses floyd-steinberg 
-**!	dithereing.
-**! returns the GIF data
-**!
-**! arg int num_colors
-**!	number of colors to quantize to (default is 256) 
-**! array array(array(int)) colors
-**!	colors to map to (default is to quantize to 256), format is ({({r,g,b}),({r,g,b}),...}).
-**! arg int trans_r
-**! arg int trans_g
-**! arg int trans_b
-**!	one color, that is to be transparent.
-**! see also: togif_begin, togif_add, togif_end, toppm, fromgif
-*/
-
-void image_togif(INT32 args)
-{
-   rgb_group *transparent=NULL;
-   struct colortable *ct=NULL;
-
-   if (args>0 && sp[-args].type==T_ARRAY)
-      ct=colortable_from_array(sp[-args].u.array,"image->togif()\n");
-   else if (args>0 && args!=3 && sp[-args].type==T_INT)
-      ct=colortable_quant(THIS,min(256,max(2,sp[-args].u.integer)));
-
-   if (args>=3+!!ct)
-   {
-      getrgb(THIS,!!ct,args,"image->togif() (transparency)");
-      transparent=&(THIS->rgb);
-   }
-
-   pop_n_elems(args);
-   if (!THIS->img) { error("no image\n");  return; }
-
-   if (!ct) ct=colortable_quant(THIS,256);
-   push_string( image_encode_gif( THIS,ct, transparent, 0, 0) );
-   colortable_free(ct);
-}
-
-
-void image_togif_fs(INT32 args)
-{
-   rgb_group *transparent=NULL;
-   struct colortable *ct=NULL;
-   int closest=0;
-
-   if (args>0 && sp[-args].type==T_ARRAY)
-   {
-      ct=colortable_from_array(sp[-args].u.array,"image->togif_fs()\n");
-      closest=1;
-   }
-   else if (args>0 && args!=3 && sp[-args].type==T_INT)
-      ct=colortable_quant(THIS,min(256,max(2,sp[-args].u.integer)));
-
-   if (args>=3+!!ct)
-   {
-      getrgb(THIS,!!ct,args,"image->togif() (transparency)");
-      transparent=&(THIS->rgb);
-   }
-
-   pop_n_elems(args);
-   if (!THIS->img) { error("no image\n");  return; }
-
-   if (!ct)
-      ct=colortable_quant(THIS,256);
-   push_string( image_encode_gif( THIS,ct, transparent, 1, closest) );
-   colortable_free(ct);
-}
 
 /*
 **! method string gif_begin()
@@ -697,7 +486,38 @@ void image_gif_netscape_loop(INT32 args)
    push_string(make_shared_binary_string(buf,19));
 }
 
-static void img_gif_add(INT32 args,int fs,int lm)
+/*
+**! method string gif_transparency(int color)
+**!	
+**! returns a gif chunk that transparent a color in the next image chunk
+**!
+**! arg int color
+**!	index of color in the palette 
+**! note
+**!	Yes - i know this function is too hard to use. :/
+**!	The palette _is_ unknown mostly...
+**! see also: gif_add, gif_begin, gif_end
+*/
+
+void image_gif_transparency(INT32 args)
+{
+   unsigned short i=0;
+   char buf[30];
+   if (args)
+      if (sp[-args].type!=T_INT) 
+	 error("Illegal argument to image->gif_transparency()\n");
+      else
+	 i=sp[-args].u.integer;
+   else
+      error("Too few arguments to image->gif_transparency()\n");
+   pop_n_elems(args);
+
+   sprintf(buf,"%c%c%c%c%c%c%c%c",33,0xf9,4,1,0,0,i,0);
+
+   push_string(make_shared_binary_string(buf,8));
+}
+
+static struct colortable *img_gif_add(INT32 args,int fs,int lm)
 {
    INT32 x=0,y=0,i;
    struct lzw lzw;
@@ -839,13 +659,14 @@ CHRONO("end pack");
 
    lzw_quit(&lzw);
 
-   colortable_free(ct);
    THREADS_DISALLOW();
 
 CHRONO("done");
 
    pop_n_elems(args);
    push_string(low_free_buf(&buf));
+
+   return ct;
 }
 
 /*
@@ -920,21 +741,125 @@ CHRONO("done");
 
 void image_gif_add(INT32 args)
 {
-   img_gif_add(args,0,1);
+   colortable_free(img_gif_add(args,0,1));
 }
 
 void image_gif_add_fs(INT32 args)
 {
-   img_gif_add(args,1,1);
+   colortable_free(img_gif_add(args,1,1));
 }
 
 void image_gif_add_nomap(INT32 args)
 {
-   img_gif_add(args,0,0);
+   colortable_free(img_gif_add(args,0,0));
 }
 
 void image_gif_add_fs_nomap(INT32 args)
 {
-   img_gif_add(args,1,0);
+   colortable_free(img_gif_add(args,1,0));
 }
 
+/*
+**! method string togif()
+**! method string togif(int num_colors)
+**! method string togif(array(array(int)) colors)
+**! method string togif(int trans_r,int trans_g,int trans_b)
+**! method string togif(int num_colors,int trans_r,int trans_g,int trans_b)
+**! method string togif(array(array(int)) colors,int trans_r,int trans_g,int trans_b)
+**! method string togif_fs()
+**! method string togif_fs(int num_colors)
+**! method string togif_fs(array(array(int)) colors)
+**! method string togif_fs(int trans_r,int trans_g,int trans_b)
+**! method string togif_fs(int num_colors,int trans_r,int trans_g,int trans_b)
+**! method string togif_fs(array(array(int)) colors,int trans_r,int trans_g,int trans_b)
+**!	Makes GIF data. The togif_fs variant uses floyd-steinberg 
+**!	dithereing.
+**! returns the GIF data
+**!
+**! arg int num_colors
+**!	number of colors to quantize to (default is 256) 
+**! array array(array(int)) colors
+**!	colors to map to (default is to quantize to 256), format is ({({r,g,b}),({r,g,b}),...}).
+**! arg int trans_r
+**! arg int trans_g
+**! arg int trans_b
+**!	one color, that is to be transparent.
+**! see also: togif_begin, togif_add, togif_end, toppm, fromgif
+*/
+
+
+static void img_encode_gif(rgb_group *transparent,int fs,INT32 args)
+{
+  struct colortable *ct;
+  struct svalue sv;
+
+  /* on stack is now:
+     - eventual colortable instruction (number or array) */
+
+  /* (swap in) arguments to gif_add, x and y position */
+  push_int(0); if (args) { sv=sp[-1]; sp[-1]=sp[-2]; sp[-2]=sv; }
+  push_int(0); if (args) { sv=sp[-1]; sp[-1]=sp[-2]; sp[-2]=sv; }
+
+  ct=img_gif_add(args+2,fs,1);
+  image_gif_begin(0);
+
+  /* on stack is now:
+     - gif image chunk with local palette 
+     - gif beginning */
+
+  /* swap them... */
+  sv=sp[-1]; sp[-1]=sp[-2]; sp[-2]=sv;
+
+  if (transparent)
+  {
+     push_int(colortable_rgb(ct,*transparent));
+     image_gif_transparency(1);
+     sv=sp[-1]; sp[-1]=sp[-2]; sp[-2]=sv;
+  }
+  colortable_free(ct);
+  image_gif_end(0);
+
+  /* on stack is now: 
+     - gif beginning
+     - eventual transparency chunk
+     - image with local palette
+     - gif end chunk */
+  
+  f_add(3+!!transparent);
+/*  f_aggregate(4);*/
+}
+
+void image_togif(INT32 args)
+{
+   rgb_group *transparent=NULL;
+
+   if (args>=3)
+   {
+      getrgb(THIS,args>3,args,"image->togif() (transparency)");
+      transparent=&(THIS->rgb);
+   }
+   if (args==3) pop_n_elems(3);
+   else if (args) pop_n_elems(args-1);
+
+   if (!THIS->img) { error("no image\n");  return; }
+
+   img_encode_gif(transparent, 0, args&&args!=3);
+}
+
+
+void image_togif_fs(INT32 args)
+{
+   rgb_group *transparent=NULL;
+
+   if (args>=3)
+   {
+      getrgb(THIS,args>3,args,"image->togif() (transparency)");
+      transparent=&(THIS->rgb);
+   }
+   if (args==3) pop_n_elems(3);
+   else if (args) pop_n_elems(args-1);
+
+   if (!THIS->img) { error("no image\n");  return; }
+
+   img_encode_gif(transparent, 1, args&&args!=3);
+}