diff --git a/src/modules/image/image.c b/src/modules/image/image.c
index 49e975eafb9121c40b29dda8d6b05b9fe8a5fba0..ee608296658ded1514ed41a6990d2f243ff4095c 100644
--- a/src/modules/image/image.c
+++ b/src/modules/image/image.c
@@ -1,4 +1,4 @@
-/* $Id: image.c,v 1.32 1996/12/05 22:53:25 law Exp $ */
+/* $Id: image.c,v 1.33 1996/12/05 23:50:51 law Exp $ */
 
 #include "global.h"
 
@@ -7,7 +7,7 @@
 
 #include "stralloc.h"
 #include "global.h"
-RCSID("$Id: image.c,v 1.32 1996/12/05 22:53:25 law Exp $");
+RCSID("$Id: image.c,v 1.33 1996/12/05 23:50:51 law Exp $");
 #include "types.h"
 #include "macros.h"
 #include "object.h"
@@ -1411,6 +1411,38 @@ static void image_map_closest(INT32 args)
    ct=colortable_from_array(sp[-args].u.array,"image->map_closest()\n");
    pop_n_elems(args);
 
+   i=THIS->xsize*THIS->ysize;
+   s=THIS->img;
+   d=((struct image*)(o->storage))->img;
+   while (i--)
+   {
+      *d=ct->clut[colortable_rgb_nearest(ct,*s)];
+      d++; *s++;
+   }
+
+   colortable_free(ct);
+   push_object(o);
+}
+
+static void image_map_fast(INT32 args)
+{
+   struct colortable *ct;
+   long i;
+   rgb_group *d,*s;
+   struct object *o;
+
+   if (!THIS->img) error("no image\n");
+   if (args<1
+       || sp[-args].type!=T_ARRAY)
+      error("illegal argument to image->map_closest()\n");
+
+   push_int(THIS->xsize);
+   push_int(THIS->ysize);
+   o=clone(image_program,2);
+      
+   ct=colortable_from_array(sp[-args].u.array,"image->map_closest()\n");
+   pop_n_elems(args);
+
    i=THIS->xsize*THIS->ysize;
    s=THIS->img;
    d=((struct image*)(o->storage))->img;
@@ -1631,6 +1663,8 @@ void init_image_programs()
 
    add_function("map_closest",image_map_closest,
                 "function(:object)",0);
+   add_function("map_fast",image_map_fast,
+                "function(:object)",0);
    add_function("map_fs",image_map_fs,
                 "function(:object)",0);
    add_function("select_colors",image_select_colors,
diff --git a/src/modules/image/image.h b/src/modules/image/image.h
index 3a1b0382432037fcc0da72830d1520a2350ceba7..c37001dc2847f855ccd298b38f44020b748360b0 100644
--- a/src/modules/image/image.h
+++ b/src/modules/image/image.h
@@ -1,4 +1,4 @@
-/* $Id: image.h,v 1.15 1996/12/05 22:53:26 law Exp $ */
+/* $Id: image.h,v 1.16 1996/12/05 23:50:52 law Exp $ */
 
 #define MAX_NUMCOL 32768
 
@@ -61,6 +61,7 @@ struct colortable
 
 struct colortable *colortable_quant(struct image *img,int numcol);
 int colortable_rgb(struct colortable *ct,rgb_group rgb);
+int colortable_rgb_nearest(struct colortable *ct,rgb_group rgb);
 void colortable_free(struct colortable *ct);
 struct colortable *colortable_from_array(struct array *arr,char *from);
 
diff --git a/src/modules/image/matrix.c b/src/modules/image/matrix.c
index 3c442ac7c3c6efe7aca7e17ced1e761232e04a29..54c90ac0bd08426adf9af0d2ead42e47af89dae5 100644
--- a/src/modules/image/matrix.c
+++ b/src/modules/image/matrix.c
@@ -1,4 +1,4 @@
-/* $Id: matrix.c,v 1.7 1996/12/03 22:40:46 law Exp $ */
+/* $Id: matrix.c,v 1.8 1996/12/05 23:50:53 law Exp $ */
 
 #include "global.h"
 
@@ -133,7 +133,10 @@ static INLINE void scale_add_line(rgbd_group *new,INT32 yn,INT32 newx,
 	    scale_add_pixel(new,(INT32)xn,img,x,xndxd);
 	 if (dx>=1.0 && (xd=(INT32)(xn+dx)-(INT32)(xn))>1) 
             while (--xd)
+	    {
+	       new++;
                scale_add_pixel(new,(INT32)(xn+xd),img,x,py);
+	    }
 	 xndxd=py*decimals(xn+dx);
 	 new++;
 	 if (xndxd)
diff --git a/src/modules/image/quant.c b/src/modules/image/quant.c
index 751a6204fef07184f93941a480c8feb7a92f8af0..b50c912964bac35bd407b62d0cffcdaf7cfae40d 100644
--- a/src/modules/image/quant.c
+++ b/src/modules/image/quant.c
@@ -1,4 +1,4 @@
-/* $Id: quant.c,v 1.16 1996/12/05 22:53:27 law Exp $ */
+/* $Id: quant.c,v 1.17 1996/12/05 23:50:54 law Exp $ */
 
 /*
 
@@ -660,7 +660,7 @@ struct colortable *colortable_from_array(struct array *arr,char *from)
 
 int colortable_rgb(struct colortable *ct,rgb_group rgb)
 {
-   int i,best,di;
+   int i,best;
 
    if (ct->cache->index.r==rgb.r &&
        ct->cache->index.g==rgb.g &&
@@ -745,15 +745,67 @@ fprintf(stderr,"cache: %lu: %d,%d,%d\n",best,ct->clut[best].r,ct->clut[best].g,c
 
 #endif
 
-#if 0
+   /* place in cache */
+#if QUANT_SELECT_CACHE>1
+   MEMMOVE(ct->cache+1,ct->cache,
+	   (QUANT_SELECT_CACHE-1)*sizeof(struct rgb_cache));
+#endif
+   ct->cache[0].index=rgb;
+   ct->cache[0].value=best;
+
+#ifdef QUANT_DEBUG_RGB
+fprintf(stderr," -> %lu: %d,%d,%d\n",best,
+	ct->clut[best].r,ct->clut[best].g,ct->clut[best].b);
+#endif
+   return best;
+}
+
+int colortable_rgb_nearest(struct colortable *ct,rgb_group rgb)
+{
+   int i,best=0,di,di2;
+   rgb_group *prgb;
+
+   if (ct->cache->index.r==rgb.r &&
+       ct->cache->index.g==rgb.g &&
+       ct->cache->index.b==rgb.b) 
+      return ct->cache->value;
+
+#ifdef QUANT_DEBUG_RGB
+fprintf(stderr,"rgb: %d,%d,%d\n",rgb.r,rgb.g,rgb.b);
+#endif
+
+#if QUANT_SELECT_CACHE>1
+   for (i=1; i<QUANT_SELECT_CACHE; i++)
+      if (ct->cache[i].index.r==rgb.r &&
+	  ct->cache[i].index.g==rgb.g &&
+	  ct->cache[i].index.b==rgb.b) 
+      {
+	 best=ct->cache[i].value;
+
+	 MEMMOVE(ct->cache+1,ct->cache,
+		 i*sizeof(struct rgb_cache));
+	 ct->cache[0].index=rgb;
+	 ct->cache[0].value=best;
+
+#ifdef QUANT_DEBUG_RGB
+fprintf(stderr,"cache: %lu: %d,%d,%d\n",best,ct->clut[best].r,ct->clut[best].g,ct->clut[best].b);
+#endif
+	 return best;
+      }
+#endif
+
+   /* find node */
+
    di=1000000L;
    for (i=0; i<ct->numcol; i++)
-      if (DISTANCE(ct->clut[i],rgb)<di) 
+   {
+      prgb=ct->clut+i;
+      if ((di2=DISTANCE(*prgb,rgb))<di) 
       { 
 	 best=i; 
-	 di=DISTANCE(ct->clut[i],rgb);
+	 di=di2;
       }
-#endif
+   }
 
    /* place in cache */
 #if QUANT_SELECT_CACHE>1