diff --git a/src/modules/Image/colortable.c b/src/modules/Image/colortable.c
index 056302ef62ce018a6e400101ed3971210e1c5feb..bcbc5053b921d8a9911f2f689d3db83ed1158894 100644
--- a/src/modules/Image/colortable.c
+++ b/src/modules/Image/colortable.c
@@ -1,11 +1,11 @@
 #include <config.h>
 
-/* $Id: colortable.c,v 1.38 1998/01/25 11:26:54 mirar Exp $ */
+/* $Id: colortable.c,v 1.39 1998/02/10 13:27:04 mirar Exp $ */
 
 /*
 **! module Image
 **! note
-**!	$Id: colortable.c,v 1.38 1998/01/25 11:26:54 mirar Exp $
+**!	$Id: colortable.c,v 1.39 1998/02/10 13:27:04 mirar Exp $
 **! class colortable
 **!
 **!	This object keeps colortable information,
@@ -21,7 +21,7 @@
 #undef COLORTABLE_REDUCE_DEBUG
 
 #include "global.h"
-RCSID("$Id: colortable.c,v 1.38 1998/01/25 11:26:54 mirar Exp $");
+RCSID("$Id: colortable.c,v 1.39 1998/02/10 13:27:04 mirar Exp $");
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -381,8 +381,13 @@ static int reduce_recurse(struct nct_flat_entry *src,
 
    if (!tot) /* all needed */
    {
-      memcpy(dest,src,sizeof(struct nct_flat_entry)*src_size);
-      return src_size;
+      *dest=*src;
+      for (i=n=1; i<src_size; i++)
+	 if (src[i].color.r!=dest[n-1].color.r ||
+	     src[i].color.g!=dest[n-1].color.g ||
+	     src[i].color.b!=dest[n-1].color.b)
+	    dest[n++]=src[i];
+      return n;
    }
 
    tot=0;
@@ -489,12 +494,40 @@ static int reduce_recurse(struct nct_flat_entry *src,
 	 newpos2.b=position.b+space.b;
          break;
    }
+   
 
 #ifdef COLORTABLE_REDUCE_DEBUG
    fprintf(stderr,"COLORTABLE%*s left=%d right=%d\n",level,"",left,right);
 #endif
 
    if (left==0) left++;
+   while (left &&
+	  src[left].color.r==src[left-1].color.r &&
+	  src[left].color.g==src[left-1].color.g &&
+	  src[left].color.b==src[left-1].color.b) 
+      left--;
+   
+   if (right==src_size-1 && !left) 
+   {
+#ifdef COLORTABLE_REDUCE_DEBUG
+      fprintf(stderr,"got all in one color: %02x%02x%02x %02x%02x%02x\n",
+	      src[left].color.r,
+	      src[left].color.g,
+	      src[left].color.b,
+	      src[right].color.r,
+	      src[right].color.g,
+	      src[right].color.b);
+#endif
+
+      *dest=*src;
+      while (dest->weight!=WEIGHT_NEEDED && left<=right) 
+      {
+	 if (src[left].weight==WEIGHT_NEEDED) dest->weight=WEIGHT_NEEDED;
+	 else dest->weight+=src[left].weight;
+	 left++;
+      }
+      return 1;
+   }
 
    i=target_size/2;
    if (src_size-left<target_size-i) i+=(target_size-i)-(src_size-left);
@@ -967,7 +1000,7 @@ static struct nct_cube _img_get_cube_from_args(INT32 args)
        sp[-args].type!=T_INT ||
        sp[1-args].type!=T_INT ||
        sp[2-args].type!=T_INT)
-      error("Illegal argument(s) 1, 2 or 3\n");
+      error("Image.colortable->create (get cube from args): Illegal argument(s) 1, 2 or 3\n");
 
    cube.r=sp[-args].u.integer;
    cube.g=sp[1-args].u.integer;
@@ -2130,15 +2163,25 @@ void image_colortable_create(INT32 args)
 **!
 **! arg int colors
 **!	target number of colors
+**!
+**! note
+**!	this algorithm assumes all colors are different to 
+**!     begin with (!)
 **/
 
 void image_colortable_reduce(INT32 args)
 {
    struct object *o;
    struct neo_colortable *nct;
+   int numcolors;
 
-   if (!args) error("Missing argument to Image.colortable->reduce\n");
-   if (sp[-args].type!=T_INT) error("Illegal argument to Image.colortable->reduce\n");
+   if (args) 
+      if (sp[-args].type!=T_INT)
+	 error("Illegal argument to Image.colortable->reduce\n");
+      else
+	 numcolors=sp[-args].u.integer;
+   else
+      numcolors=1293791; /* a lot */
    
    o=clone_object(THISOBJ->prog,0);
    nct=(struct neo_colortable*)get_storage(o,image_colortable_program);
@@ -2157,7 +2200,7 @@ void image_colortable_reduce(INT32 args)
 
    if (sp[-args].u.integer<1) sp[-args].u.integer=1;
 
-   nct->u.flat=_img_reduce_number_of_colors(nct->u.flat,sp[-args].u.integer,
+   nct->u.flat=_img_reduce_number_of_colors(nct->u.flat,numcolors,
 					    nct->spacefactor);
 
    pop_n_elems(args);
@@ -3810,6 +3853,54 @@ void image_colortable_ordered(INT32 args)
    push_object(THISOBJ); THISOBJ->refs++;
 }
 
+/*
+**! method object image()
+**!	cast the colortable to an image object
+**!
+**!	each pixel in the image object is an entry in the colortable
+**!
+**! returns the resulting image object
+**/
+
+void image_colortable_image(INT32 args)
+{
+   struct object *o;
+   struct image *img;
+   struct nct_flat flat;
+   int i;
+   rgb_group *dest;
+
+   pop_n_elems(args);
+   push_int(image_colortable_size(THIS));
+   push_int(1);
+   o=clone_object(image_program,2);
+   push_object(o);
+
+   if (THIS->type==NCT_NONE)
+      return;
+
+   img=(struct image*)get_storage(o,image_program);
+   dest=img->img;
+   
+   if (THIS->type==NCT_CUBE)
+      flat=_img_nct_cube_to_flat(THIS->u.cube);
+   else
+      flat=THIS->u.flat;
+
+   /* sort in number order? */
+
+   for (i=0; i<flat.numentries; i++)
+   {
+      dest->r=flat.entries[i].color.r;
+      dest->g=flat.entries[i].color.g;
+      dest->g=flat.entries[i].color.b;
+      dest++;
+   }
+
+   if (THIS->type==NCT_CUBE)
+      free(flat.entries);
+}
+
 /***************** global init etc *****************************/
 
 void init_colortable_programs(void)
@@ -3881,6 +3972,9 @@ void init_colortable_programs(void)
 		"function(:object)"
 		"|function(int,int,int:object)",0);
 
+   add_function("image",image_colortable_image,
+		"function(:object)",0);
+
    /* tuning image */
    add_function("spacefactors",image_colortable_spacefactors,
 		"function(int,int,int:object)",0);