diff --git a/src/modules/image/blit.c b/src/modules/image/blit.c
index dcf1e2d292890110483fb8c0c47a0505759613a0..ea8cca41891c9956cb8cb8e07a93862126147e2a 100644
--- a/src/modules/image/blit.c
+++ b/src/modules/image/blit.c
@@ -1,4 +1,4 @@
-/* $Id: blit.c,v 1.6 1996/11/14 12:35:46 law Exp $ */
+/* $Id: blit.c,v 1.7 1996/11/22 20:28:14 law Exp $ */
 #include "global.h"
 
 #include <math.h>
@@ -28,7 +28,7 @@ struct program *image_program;
 #include <sys/resource.h>
 #define CHRONO(X) chrono(X)
 
-void chrono(char *x)
+static void chrono(char *x)
 {
    struct rusage r;
    static struct rusage rold;
@@ -138,11 +138,13 @@ void img_crop(struct image *dest,
 	      INT32 x2,INT32 y2)
 {
    rgb_group *new;
-   INT32 blitwidth;
-   INT32 blitheight;
+   INT32 xp,yp,xs,ys;
 
    if (dest->img) { free(dest->img); dest->img=NULL; }
 
+   if (x1>x2) x1^=x2,x2^=x1,x1^=x2;
+   if (y1>y2) y1^=y2,y2^=y1,y1^=y2;
+
    if (x1==0 && y1==0 &&
        img->xsize-1==x2 && img->ysize-1==y2)
    {
@@ -155,28 +157,33 @@ void img_crop(struct image *dest,
       return;
    }
 
-   if (x1>x2) x1^=x2,x2^=x1,x1^=x2;
-   if (y1>y2) y1^=y2,y2^=y1,y1^=y2;
-
    new=malloc( (x2-x1+1)*(y2-y1+1)*sizeof(rgb_group) +1);
    if (!new)
      error("Out of memory.\n");
 
    img_clear(new,THIS->rgb,(x2-x1+1)*(y2-y1+1));
 
-   blitwidth=min(x2,img->xsize-1)-max(x1,0)+1;
-   blitheight=min(y2,img->ysize-1)-max(y1,0)+1;
+   dest->xsize=x2-x1+1;
+   dest->ysize=y2-y1+1;
 
-   img_blit(new+max(0,-x1)+(x2-x1+1)*max(0,-y1),
-	    img->img+max(0,x1)+(img->xsize)*max(0,y1),
-	    blitwidth,
-	    blitheight,
-	    (x2-x1+1),
+   xp=max(0,-x1);
+   yp=max(0,-y1);
+   xs=max(0,x1);
+   ys=max(0,y1);
+
+   if (x1<0) x1=0; else if (x1>=img->xsize) x1=img->xsize-1;
+   if (y1<0) y1=0; else if (y1>=img->ysize) y1=img->ysize-1;
+   if (x2<0) x2=0; else if (x2>=img->xsize) x2=img->xsize-1;
+   if (y2<0) y2=0; else if (y2>=img->ysize) y2=img->ysize-1;
+
+   img_blit(new+xp+yp*dest->xsize,
+	    img->img+xs+(img->xsize)*ys,
+	    x2-x1+1,
+	    y2-y1+1,
+	    dest->xsize,
 	    img->xsize);
 
    dest->img=new;
-   dest->xsize=x2-x1+1;
-   dest->ysize=y2-y1+1;
 }
 
 void img_clone(struct image *newimg,struct image *img)
diff --git a/src/modules/image/font.c b/src/modules/image/font.c
index 29b12e990a0df8b69cb682071f405b1a5f7128f9..fe28d216cc9dcfd71273bb0ac1f856884b485df5 100644
--- a/src/modules/image/font.c
+++ b/src/modules/image/font.c
@@ -1,4 +1,4 @@
-/* $Id: font.c,v 1.7 1996/11/18 23:13:21 hubbe Exp $ */
+/* $Id: font.c,v 1.8 1996/11/22 20:28:15 law Exp $ */
 
 #include "global.h"
 
@@ -242,8 +242,6 @@ void font_load(INT32 args)
 		  pop_n_elems(args);
 		  THISOBJ->refs++;
 		  push_object(THISOBJ);   /* success */
-		  if (THIS->chars>32)
-		     THIS->charinfo[32].spacing=THIS->height/4;
 		  return;
 	       } /* wrong version */
 	    } /* wrong cookie */
diff --git a/src/modules/image/image.c b/src/modules/image/image.c
index 3bd57bd30be9de4e416a627d9c9cc57d09fd9381..5d386d7ba32ebd6ffffa1675cbb36a8406c90ee4 100644
--- a/src/modules/image/image.c
+++ b/src/modules/image/image.c
@@ -1,4 +1,4 @@
-/* $Id: image.c,v 1.25 1996/11/14 12:34:58 law Exp $ */
+/* $Id: image.c,v 1.26 1996/11/22 20:28:16 law Exp $ */
 
 #include "global.h"
 
@@ -7,7 +7,7 @@
 
 #include "stralloc.h"
 #include "global.h"
-RCSID("$Id: image.c,v 1.25 1996/11/14 12:34:58 law Exp $");
+RCSID("$Id: image.c,v 1.26 1996/11/22 20:28:16 law Exp $");
 #include "types.h"
 #include "macros.h"
 #include "object.h"
@@ -40,17 +40,25 @@ static INT32 circle_sin_table[CIRCLE_STEPS];
 
 /***************** init & exit *********************************/
 
-static void init_image_struct(struct object *o)
+static int obj_counter=0;
+
+static void init_image_struct(struct object *obj)
 {
   THIS->img=NULL;
   THIS->rgb.r=0;
   THIS->rgb.g=0;
   THIS->rgb.b=0;
+/*  fprintf(stderr,"init %lx (%d)\n",obj,++obj_counter);*/
 }
 
 static void exit_image_struct(struct object *obj)
 {
   if (THIS->img) { free(THIS->img); THIS->img=NULL; }
+/*
+  fprintf(stderr,"exit %lx (%d) %dx%d=%.1fKb\n",obj,--obj_counter,
+	  THIS->xsize,THIS->ysize,
+	  (THIS->xsize*THIS->ysize*3+sizeof(struct image))/1024.0);
+	  */
 }
 
 /***************** internals ***********************************/
diff --git a/src/modules/image/lzw.c b/src/modules/image/lzw.c
index 4aa32b16f2ed51bff9bd8eef3a0def7571f979cc..5c34c8cb37fe2f6779d6a0cf032d419a6f306741 100644
--- a/src/modules/image/lzw.c
+++ b/src/modules/image/lzw.c
@@ -1,4 +1,4 @@
-/* $Id: lzw.c,v 1.7 1996/11/14 12:35:00 law Exp $ */
+/* $Id: lzw.c,v 1.8 1996/11/22 20:28:17 law Exp $ */
 
 /*
 
@@ -215,6 +215,8 @@ void lzw_add(struct lzw *lzw,int c)
    lzw->current=c;
 }
 
+#undef UNPACK_DEBUG
+
 #ifdef GIF_LZW
 unsigned long lzw_unpack(unsigned char *dest,unsigned long destlen,
 			 unsigned char *src,unsigned long srclen,
@@ -232,9 +234,10 @@ unsigned long lzw_unpack(unsigned char *dest,unsigned long destlen,
 
    unsigned long wrote=0;
    int i,cbits,cbit,clear=(1<<bits),end=(1<<bits)+1;
-   lzwcode_t current,last,used;
+   lzwcode_t current,last,used,nextlast;
    unsigned long store;
    unsigned char *srcend=src+srclen,*destend=dest+destlen;
+   unsigned char first=0;
 
    code=malloc(sizeof(struct lzwuc)*4096);
    if (!code) return 0;
@@ -265,13 +268,17 @@ unsigned long lzw_unpack(unsigned char *dest,unsigned long destlen,
 	 {
 	    store=(store>>8)|((*(src++))<<24);
 	    cbit+=8;
-	    if (src==srcend) return wrote;
+	    if (src==srcend) { free(code); return wrote; }
 	 }
 	 store=(store>>8)|((*(src++))<<24);
 	 cbit+=8;
 	 current=(store>>(32-(cbit)))&mask[cbits];
 	 cbit-=cbits;
       }
+
+#ifdef UNPACK_DEBUG
+      fprintf(stderr,"%03x ",current);
+#endif
       
       if (current==clear) /* clear tree */
       {
@@ -287,14 +294,30 @@ unsigned long lzw_unpack(unsigned char *dest,unsigned long destlen,
       }
       else if (current==end) /* end of data */
 	 break;
+      else if (last==LZWCNULL)
+      {
+	 last=current;
+	 if (last>end) break;
+	 *(dest++)=(unsigned char)current;
+	 wrote++;
+	 first=current;
+      }
       else
       {
 	 lzwcode_t n;
 	 unsigned char *dest2;
 
-	 if (current>=used /* wrong code, cancel */
-	    || code[current].len+dest>destend) /* no space, cancel */
+	 if (code[current].len+dest>destend) /* no space, cancel */
 	    break; 
+
+	 nextlast=current;
+
+	 if (current>=used)
+	 {
+	    *(dest++)=(unsigned char)first;
+	    wrote++;
+	    current=last;
+	 }
 	 
 	 dest+=code[current].len;
 	 wrote+=code[current].len;
@@ -320,18 +343,26 @@ unsigned long lzw_unpack(unsigned char *dest,unsigned long destlen,
 	 fprintf(stderr,"\n");
 */
 
-	 if (last!=LZWCNULL)
+	 if (used<4096)
 	 {
 	    code[used].c=code[n].c;
 	    code[used].parent=last;
 	    code[used].len=code[last].len+1;
 	    used++;
-	    if (used>=(1<<cbits)) cbits++;
+
+	    if (used>=(1<<cbits)) 
+	    {
+	       cbits++;
+#ifdef UNPACK_DEBUG
+	       fprintf(stderr,"[%d bits]",cbits);
+#endif
+	    }
 	 }
-	 
-	 last=current;
+
+	 last=nextlast;
       }
    }
+   free(code);
    return wrote;
 }
 #endif
diff --git a/src/modules/image/quant.c b/src/modules/image/quant.c
index bccd3730eef2c39d9620bd9cf4763338b2db2497..90a1a4baf4a6e8b14874b34b4498f62c8f1377db 100644
--- a/src/modules/image/quant.c
+++ b/src/modules/image/quant.c
@@ -1,4 +1,4 @@
-/* $Id: quant.c,v 1.12 1996/11/14 12:35:04 law Exp $ */
+/* $Id: quant.c,v 1.13 1996/11/22 20:28:18 law Exp $ */
 
 /*
 
@@ -548,6 +548,7 @@ struct colortable *colortable_from_array(struct array *arr,char *from)
      if (s2.type!=T_INT) tbl->tbl[i].rgb.g=0; else tbl->tbl[i].rgb.g=s2.u.integer;
      array_index(&s2,s.u.array,2);
      if (s2.type!=T_INT) tbl->tbl[i].rgb.b=0; else tbl->tbl[i].rgb.b=s2.u.integer;
+     tbl->tbl[i].count=1;
   }
   free_svalue(&s);
   free_svalue(&s2);
diff --git a/src/modules/image/togif.c b/src/modules/image/togif.c
index 8646a7569d0b31dd91a1309b44c455bfd88c053e..1f1c1ed49b3eabbaeccbd1ced5facba1d2088bc6 100644
--- a/src/modules/image/togif.c
+++ b/src/modules/image/togif.c
@@ -1,4 +1,4 @@
-/* $Id: togif.c,v 1.12 1996/11/16 05:17:12 hubbe Exp $ */
+/* $Id: togif.c,v 1.13 1996/11/22 20:28:19 law Exp $ */
 /*
 
 togif 
@@ -32,6 +32,30 @@ Pontus Hagland, law@infovav.se
 #define THIS ((struct image *)(fp->current_storage))
 #define THISOBJ (fp->current_object)
 
+#if 0
+#include <sys/resource.h>
+#define CHRONO(X) chrono(X)
+
+static void chrono(char *x)
+{
+   struct rusage r;
+   static struct rusage rold;
+   getrusage(RUSAGE_SELF,&r);
+   fprintf(stderr,"%s: %ld.%06ld - %ld.%06ld\n",x,
+	   r.ru_utime.tv_sec,r.ru_utime.tv_usec,
+
+	   ((r.ru_utime.tv_usec-rold.ru_utime.tv_usec<0)?-1:0)
+	   +r.ru_utime.tv_sec-rold.ru_utime.tv_sec,
+           ((r.ru_utime.tv_usec-rold.ru_utime.tv_usec<0)?1000000:0)
+           + r.ru_utime.tv_usec-rold.ru_utime.tv_usec
+	   );
+
+   rold=r;
+}
+#else
+#define CHRONO(X)
+#endif
+
 
 #define min(a,b) ((a)<(b)?(a):(b))
 #define max(a,b) ((a)<(b)?(b):(a))
@@ -363,7 +387,7 @@ int image_decode_gif(struct image *dest,struct image *dest_alpha,
 	       if (!tmpstore) break;
 	       i=lzw_unpack(tmpstore,width*height,arena,pos,bpp);
 	       if (i!=(unsigned long)(width*height))
-		  MEMSET(arena+i,0,width*height-i);
+		  MEMSET(tmpstore+i,0,width*height-i);
 	       rgb=dest->img+leftofs+topofs*dest->ysize;
 	       mod=width-dest->xsize;
 	       j=height;
@@ -432,35 +456,45 @@ static INLINE void getrgb(struct image *img,
 void image_togif(INT32 args)
 {
    rgb_group *transparent=NULL;
-   struct colortable *ct;
+   struct colortable *ct=NULL;
 
-   if (args>=3)
+   if (args>0 && sp[-args].type==T_ARRAY)
+      ct=colortable_from_array(sp[-args].u.array,"image->togif()\n");
+
+   if (args>=3+!!ct)
    {
-      getrgb(THIS,0,args,"image->togif() (transparency)");
+      getrgb(THIS,!!ct,args,"image->togif() (transparency)");
       transparent=&(THIS->rgb);
    }
 
    pop_n_elems(args);
    if (!THIS->img) { error("no image\n");  return; }
-   ct=colortable_quant(THIS,256);
+
+   if (!ct) ct=colortable_quant(THIS,256);
    push_string( image_encode_gif( THIS,ct, transparent, 0) );
    colortable_free(ct);
 }
 
+
 void image_togif_fs(INT32 args)
 {
    rgb_group *transparent=NULL;
-   struct colortable *ct;
+   struct colortable *ct=NULL;
 
-   if (args>=3)
+   if (args>0 && sp[-args].type==T_ARRAY)
+      ct=colortable_from_array(sp[-args].u.array,"image->togif()\n");
+
+   if (args>=3+!!ct)
    {
-      getrgb(THIS,0,args,"image->togif_fs() (transparency)");
+      getrgb(THIS,!!ct,args,"image->togif() (transparency)");
       transparent=&(THIS->rgb);
    }
 
    pop_n_elems(args);
    if (!THIS->img) { error("no image\n");  return; }
-   ct=colortable_quant(THIS,256);
+
+   if (!ct)
+      ct=colortable_quant(THIS,256);
    push_string( image_encode_gif( THIS,ct, transparent, 1) );
    colortable_free(ct);
 }
@@ -517,9 +551,11 @@ static void img_gif_add(INT32 args,int fs)
    INT32 x,y,i;
    struct lzw lzw;
    rgb_group *rgb;
-   struct colortable *ct;
+   struct colortable *ct=NULL;
    dynamic_buffer buf;
 
+CHRONO("gif add init");
+
    buf.s.str=NULL;
    initialize_buf(&buf);
 
@@ -533,13 +569,16 @@ static void img_gif_add(INT32 args,int fs)
       y=sp[1-args].u.integer;
    }
 
-   if (args>2)
+   if (args>2 && sp[2-args].type==T_ARRAY)
+      ct=colortable_from_array(sp[2-args].u.array,"image->gif_add()\n");
+
+   if (args>2+!!ct)
    {
       unsigned short delay;
-      if (sp[2-args].type==T_INT) 
-	 delay=sp[2-args].u.integer;
-      else if (sp[2-args].type==T_FLOAT) 
-	 delay=(unsigned short)(sp[2-args].u.float_number*100);
+      if (sp[2+!!ct-args].type==T_INT) 
+	 delay=sp[2+!!ct-args].u.integer;
+      else if (sp[2+!!ct-args].type==T_FLOAT) 
+	 delay=(unsigned short)(sp[2+!!ct-args].u.float_number*100);
       else 
 	 error("Illegal argument 3 to image->gif_add()\n");
 
@@ -552,7 +591,7 @@ static void img_gif_add(INT32 args,int fs)
       low_my_putchar( 0, &buf ); /* terminate block */
    }
 
-   ct=colortable_quant(THIS,256);
+   if (!ct) ct=colortable_quant(THIS,256);
 
    low_my_putchar( ',', &buf ); /* image separator */
 
@@ -566,18 +605,26 @@ static void img_gif_add(INT32 args,int fs)
       /* local colormap ( == 0x80) */
       /* 8 bpp in map ( == 0x07)   */
 
-   for (i=0; i<256; i++)
+   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<256; i++)
+   {
+      low_my_putchar(0,&buf);
+      low_my_putchar(0,&buf);
+      low_my_putchar(0,&buf);
+   }
 
    low_my_putchar( 8, &buf ); /* bits per pixel , or min 2 */
    
    i=THIS->xsize*THIS->ysize;
    rgb=THIS->img;
 
+CHRONO("begin pack");
+
    lzw_init(&lzw,8);
    if (!fs)
       while (i--) lzw_add(&lzw,colortable_rgb(ct,*(rgb++)));
@@ -609,6 +656,8 @@ static void img_gif_add(INT32 args,int fs)
 
    lzw_write_last(&lzw);
 
+CHRONO("end pack");
+
    for (i=0; i<(int)lzw.outpos; i+=254)
    {
       int wr;
@@ -621,6 +670,10 @@ static void img_gif_add(INT32 args,int fs)
 
    lzw_quit(&lzw);
 
+   colortable_free(ct);
+
+CHRONO("done");
+
    pop_n_elems(args);
    push_string(low_free_buf(&buf));
 }