From 7a49a14c1947386f7f72b12f79c364faa53a2a54 Mon Sep 17 00:00:00 2001
From: "Mirar (Pontus Hagland)" <pike@sort.mirar.org>
Date: Sat, 10 Apr 1999 04:02:08 +0200
Subject: [PATCH] heavy use of Image.color objects, a lot of bugfixes

Rev: src/modules/Image/colors.c:1.10
Rev: src/modules/Image/colortable.c:1.58
Rev: src/modules/Image/colortable.h:1.16
Rev: src/modules/Image/colortable_lookup.h:1.9
Rev: src/modules/Image/image.h:1.26
---
 src/modules/Image/colors.c            | 123 +++++++++------
 src/modules/Image/colortable.c        | 216 ++++++++++++++++----------
 src/modules/Image/colortable.h        |   4 +-
 src/modules/Image/colortable_lookup.h | 173 ++++++++-------------
 src/modules/Image/image.h             |  18 ++-
 5 files changed, 288 insertions(+), 246 deletions(-)

diff --git a/src/modules/Image/colors.c b/src/modules/Image/colors.c
index a01b181745..09bc9210a1 100644
--- a/src/modules/Image/colors.c
+++ b/src/modules/Image/colors.c
@@ -1,7 +1,7 @@
 /*
 **! module Image
 **! note
-**!	$Id: colors.c,v 1.9 1999/02/10 21:48:24 hubbe Exp $
+**!	$Id: colors.c,v 1.10 1999/04/10 02:02:01 mirar Exp $
 **! submodule color
 **!
 **!	This module keeps names and easy handling 
@@ -97,7 +97,7 @@
 #include "global.h"
 #include <config.h>
 
-RCSID("$Id: colors.c,v 1.9 1999/02/10 21:48:24 hubbe Exp $");
+RCSID("$Id: colors.c,v 1.10 1999/04/10 02:02:01 mirar Exp $");
 
 #include "config.h"
 
@@ -137,21 +137,15 @@ static struct pike_string *str_h;
 static struct pike_string *str_s;
 static struct pike_string *str_v;
 
-struct color_struct
-{
-   rgb_group rgb;
-   rgbl_group rgbl;
-   struct pike_string *name;
-};
+static struct pike_string *no_name;
 
 /* forward */
-static void image_make_rgb_color(INT32 args); 
-static void _image_make_rgb_color(INT32 r,INT32 g,INT32 b); 
 static void _image_make_rgbl_color(INT32 r,INT32 g,INT32 b); 
 static void _image_make_rgbf_color(float r,float g,float b);
 static void image_make_hsv_color(INT32 args); 
 static void image_make_cmyk_color(INT32 args);
 static void image_make_color(INT32 args);
+static void image_make_rgb_color(INT32 args);
 
 struct html_color
 {
@@ -215,10 +209,12 @@ static void make_colors(void)
    }
    f_aggregate(n);
    colortable=clone_object(image_colortable_program,1);
+   if (!colortable)
+      fatal("couldn't create colortable\n");
 
-   push_int(5);
-   push_int(5);
-   push_int(5);
+   push_int(12);
+   push_int(12);
+   push_int(12);
    push_int(1);
    safe_apply(colortable,"cubicles",4);
    pop_stack();
@@ -252,26 +248,38 @@ static void exit_color_struct(struct object *dummy)
    }
 }
 
+void _img_nct_map_to_flat_cubicles(rgb_group *s,
+				   rgb_group *d,
+				   int n,
+				   struct neo_colortable *nct,
+				   struct nct_dither *dith,
+				   int rowlen);
+
 static void try_find_name(struct color_struct *this)
 {
    rgb_group d;
+   static struct nct_dither dith = { NCTD_NONE,NULL,NULL,NULL,NULL };
 
    if (!colors)
+   {
+      fprintf(stderr,"make colors\n");
       make_colors();
+   }
 
    if (this->name) 
-   {
-      free_string(this->name);
-      this->name=NULL;
-   }
+      fatal("try_find_name called twice\n");
 
    if (this->rgbl.r!=COLOR_TO_COLORL(this->rgb.r) ||
        this->rgbl.g!=COLOR_TO_COLORL(this->rgb.g) ||
        this->rgbl.b!=COLOR_TO_COLORL(this->rgb.b))
+   {
+      copy_shared_string(this->name,no_name);
       return; 
+   }
 
-   image_colortable_map_image((struct neo_colortable*)colortable->storage,
-			      &(this->rgb),&d,1,1);
+   _img_nct_map_to_flat_cubicles(&(this->rgb),&d,1,
+				 (struct neo_colortable*)colortable->storage,
+				 &dith,1);
    
    if (d.r==this->rgb.r &&
        d.g==this->rgb.g &&
@@ -286,8 +294,10 @@ static void try_find_name(struct color_struct *this)
       {
 	 copy_shared_string(this->name,
 			    colornames->item[d2].u.string);
+	 return;
       }
    }
+   copy_shared_string(this->name,no_name);
 }
 
 /*
@@ -329,6 +339,15 @@ static void image_color_rgb(INT32 args)
    f_aggregate(3);
 }
 
+static void image_color_rgbf(INT32 args)
+{
+   pop_n_elems(args);
+   push_float(COLORL_TO_FLOAT(THIS->rgbl.r));
+   push_float(COLORL_TO_FLOAT(THIS->rgbl.g));
+   push_float(COLORL_TO_FLOAT(THIS->rgbl.b));
+   f_aggregate(3);
+}
+
 static void image_color_greylevel(INT32 args)
 {
    INT32 r,g,b;
@@ -554,10 +573,12 @@ static void image_color_html(INT32 args)
 static void image_color_name(INT32 args)
 {
    pop_n_elems(args);
-   if (THIS->name)
-      ref_push_string(THIS->name);
-   else
+   if (!THIS->name) try_find_name(THIS);
+
+   if (THIS->name==no_name)
       image_color_hex(0);
+   else
+      ref_push_string(THIS->name);
 }
 
 /*
@@ -718,7 +739,9 @@ static void image_color_equal(INT32 args)
    }
    else if (sp[-1].type==T_STRING)
    {
-      if (sp[-1].u.string==THIS->name)
+      if (!THIS->name)
+	 try_find_name(THIS);
+      if (sp[-1].u.string==THIS->name && THIS->name!=no_name)
       {
 	 pop_stack();
 	 push_int(1);
@@ -873,13 +896,12 @@ static void image_color_mult(INT32 args)
 			 (int)(THIS->rgb.b*x));
 }
 
-static int image_color_arg(INT32 args,rgb_group *rgb)
+int image_color_svalue(struct svalue *v,rgb_group *rgb)
 {
-   if (!args) return 0;
-   if (sp[-args].type==T_OBJECT)
+   if (v->type==T_OBJECT)
    {
       struct color_struct *cs=(struct color_struct*)
-	 get_storage(sp[-args].u.object,image_color_program);
+	 get_storage(v->u.object,image_color_program);
 
       if (cs) 
       {
@@ -887,30 +909,27 @@ static int image_color_arg(INT32 args,rgb_group *rgb)
 	 return 1;
       }
    }
-   else if (sp[-args].type==T_ARRAY)
+   else if (v->type==T_ARRAY)
    {
-      int n=sp[-args].u.array->size;
-      add_ref(sp[-args].u.array);
-      push_array_items(sp[-args].u.array);
-      image_make_color(n);
-      if (sp[-1].type==T_OBJECT)
+      if (v->u.array->size==3 &&
+	  v->u.array->item[0].type==T_INT &&
+	  v->u.array->item[1].type==T_INT &&
+	  v->u.array->item[2].type==T_INT)
       {
-	 struct color_struct *cs=(struct color_struct*)
-	    get_storage(sp[-args].u.object,image_color_program);
-	 *rgb=cs->rgb;
-	 pop_stack();
+	 rgb->r=(COLORTYPE)(v->u.array->item[0].u.integer);
+	 rgb->g=(COLORTYPE)(v->u.array->item[1].u.integer);
+	 rgb->b=(COLORTYPE)(v->u.array->item[2].u.integer);
 	 return 1;
       }
-      pop_stack();
    }
-   else if (sp[-args].type==T_STRING)
+   else if (v->type==T_STRING)
    {
-      push_svalue(sp-args);
+      push_svalue(v);
       image_make_color(1);
       if (sp[-1].type==T_OBJECT)
       {
 	 struct color_struct *cs=(struct color_struct*)
-	    get_storage(sp[-args].u.object,image_color_program);
+	    get_storage(v->u.object,image_color_program);
 	 *rgb=cs->rgb;
 	 pop_stack();
 	 return 1;
@@ -920,6 +939,13 @@ static int image_color_arg(INT32 args,rgb_group *rgb)
    return 0;
 }
 
+int image_color_arg(INT32 args,rgb_group *rgb)
+{
+   if (args<=0) return 0;
+   return image_color_svalue(sp-args,rgb);
+}
+
+
 static void image_color_add(INT32 args)
 {
    rgb_group rgb;
@@ -1193,8 +1219,6 @@ static void _image_make_rgbl_color(INT32 r,INT32 g,INT32 b)
    cs->rgbl.g=(INT32)g;
    cs->rgbl.b=(INT32)b;
    RGBL_TO_RGB(cs->rgb,cs->rgbl);
-
-   try_find_name(cs);
 }
 
 static void _image_make_rgbf_color(float r,float g,float b)
@@ -1204,7 +1228,7 @@ static void _image_make_rgbf_color(float r,float g,float b)
 #undef FOO
 }
 
-static void _image_make_rgb_color(INT32 r,INT32 g,INT32 b)
+void _image_make_rgb_color(INT32 r,INT32 g,INT32 b)
 {
    struct color_struct *cs;
 
@@ -1221,8 +1245,6 @@ static void _image_make_rgb_color(INT32 r,INT32 g,INT32 b)
    cs->rgb.g=(COLORTYPE)g;
    cs->rgb.b=(COLORTYPE)b;
    RGB_TO_RGBL(cs->rgbl,cs->rgb);
-
-   try_find_name(cs);
 }
 
 static void image_make_rgb_color(INT32 args)
@@ -1390,6 +1412,8 @@ void init_image_colors(void)
    str_s=make_shared_string("s");
    str_v=make_shared_string("v");
 
+   no_name=make_shared_string("");
+
    start_new_program();
 
    ADD_STORAGE(struct color_struct);
@@ -1414,15 +1438,11 @@ void init_image_colors(void)
    /* function(:string) */
   ADD_FUNCTION("html",image_color_html,tFunc(,tStr),/* opt */0);
 
-   /* function(:array(int)) */
   ADD_FUNCTION("rgb",image_color_rgb,tFunc(,tArr(tInt)),/* opt */0);
-   /* function(:array(int)) */
+  ADD_FUNCTION("rgbf",image_color_rgbf,tFunc(,tArr(tFlt)),/* opt */0);
   ADD_FUNCTION("hsv",image_color_hsv,tFunc(,tArr(tInt)),/* opt */0);
-   /* function(:array(float)) */
   ADD_FUNCTION("hsvf",image_color_hsvf,tFunc(,tArr(tFlt)),/* opt */0);
-   /* function(:array(float)) */
   ADD_FUNCTION("cmyk",image_color_cmyk,tFunc(,tArr(tFlt)),/* opt */0);
-   /* function(:int)|function(int,int,int:int) */
   ADD_FUNCTION("greylevel",image_color_greylevel,tOr(tFunc(,tInt),tFunc(tInt tInt tInt,tInt)),/* opt */0);
 
    /* color conversion methods */
@@ -1515,4 +1535,5 @@ void exit_image_colors(void)
    free_string(str_s);
    free_string(str_v);
 
+   free_string(no_name);
 }
diff --git a/src/modules/Image/colortable.c b/src/modules/Image/colortable.c
index 762d4df5f5..281a3ed813 100644
--- a/src/modules/Image/colortable.c
+++ b/src/modules/Image/colortable.c
@@ -1,12 +1,12 @@
 #include "global.h"
 #include <config.h>
 
-/* $Id: colortable.c,v 1.57 1999/04/09 16:17:34 mirar Exp $ */
+/* $Id: colortable.c,v 1.58 1999/04/10 02:02:03 mirar Exp $ */
 
 /*
 **! module Image
 **! note
-**!	$Id: colortable.c,v 1.57 1999/04/09 16:17:34 mirar Exp $
+**!	$Id: colortable.c,v 1.58 1999/04/10 02:02:03 mirar Exp $
 **! class colortable
 **!
 **!	This object keeps colortable information,
@@ -21,7 +21,7 @@
 #undef COLORTABLE_DEBUG
 #undef COLORTABLE_REDUCE_DEBUG
 
-RCSID("$Id: colortable.c,v 1.57 1999/04/09 16:17:34 mirar Exp $");
+RCSID("$Id: colortable.c,v 1.58 1999/04/10 02:02:03 mirar Exp $");
 
 #include <math.h> /* fabs() */
 
@@ -34,6 +34,7 @@ RCSID("$Id: colortable.c,v 1.57 1999/04/09 16:17:34 mirar Exp $");
 #include "interpret.h"
 #include "svalue.h"
 #include "array.h"
+#include "mapping.h"
 #include "threads.h"
 #include "builtin_functions.h"
 #include "../../error.h"
@@ -84,6 +85,10 @@ static INLINE int sq(int x) { return x*x; }
 #define THIS ((struct neo_colortable *)(fp->current_storage))
 #define THISOBJ (fp->current_object)
 
+static struct pike_string *s_array;
+static struct pike_string *s_string;
+static struct pike_string *s_mapping;
+
 /***************** init & exit *********************************/
 
 
@@ -873,7 +878,7 @@ static struct nct_flat _img_get_flat_from_array(struct array *arr)
 {
    struct svalue s,s2;
    struct nct_flat flat;
-   int i;
+   int i,n=0;
 
    flat.numentries=arr->size;
    flat.entries=(struct nct_flat_entry*)
@@ -882,32 +887,20 @@ static struct nct_flat _img_get_flat_from_array(struct array *arr)
    s2.type=s.type=T_INT;
    for (i=0; i<arr->size; i++)
    {
-      array_index(&s,arr,i);
-      if (s.type==T_INT && !s.u.integer)
-      {
-	 flat.entries[i].weight=0;
-	 flat.entries[i].no=-1;
-	 flat.entries[i].color.r=
-	 flat.entries[i].color.g=
-	 flat.entries[i].color.b=0;
+      if (arr->item[i].type==T_INT && !arr->item[i].u.integer)
 	 continue;
-      }
-      if (s.type!=T_ARRAY || s.u.array->size<3)
-      {
-	 free(flat.entries);
-	 error("Illegal type in colorlist, element %d\n",i);
-      }
-      array_index(&s2,s.u.array,0);
-      if (s2.type!=T_INT) flat.entries[i].color.r=0; else flat.entries[i].color.r=s2.u.integer;
-      array_index(&s2,s.u.array,1);
-      if (s2.type!=T_INT) flat.entries[i].color.g=0; else flat.entries[i].color.g=s2.u.integer;
-      array_index(&s2,s.u.array,2);
-      if (s2.type!=T_INT) flat.entries[i].color.b=0; else flat.entries[i].color.b=s2.u.integer;
-      flat.entries[i].weight=1;
-      flat.entries[i].no=i;
+
+      if (!image_color_svalue(arr->item+i,
+			      &(flat.entries[i].color)))
+	 bad_arg_error("colortable", 
+		       0,0, 1, "array of colors or 0", 0,
+		       "colortable(): bad element %d of colorlist\n",i);
+
+      flat.entries[n].weight=1;
+      flat.entries[n].no=i;
+      n++;
    }
-   free_svalue(&s);
-   free_svalue(&s2);
+   flat.numentries=n;
 
    return flat;
 }
@@ -1053,31 +1046,13 @@ static struct nct_cube _img_get_cube_from_args(INT32 args)
       int mdist;
       int c;
 
-      if (sp[ap-args].type!=T_ARRAY ||
-	  sp[1+ap-args].type!=T_ARRAY ||
-	  sp[2+ap-args].type!=T_INT)
+      if (!image_color_arg(-args,&low))
+	 SIMPLE_BAD_ARG_ERROR("colortable",1,"color");
+      if (!image_color_arg(1-args,&high))
+	 SIMPLE_BAD_ARG_ERROR("colortable",2,"color");
+      if (sp[2+ap-args].type!=T_INT)
 	 error("illegal argument(s) %d, %d or %d\n",ap,ap+1,ap+2);
 
-      if (sp[ap-args].u.array->size==3
-	  && sp[ap-args].u.array->item[0].type==T_INT
-	  && sp[ap-args].u.array->item[1].type==T_INT
-	  && sp[ap-args].u.array->item[2].type==T_INT)
-	 low.r=sp[ap-args].u.array->item[0].u.integer,
-	 low.g=sp[ap-args].u.array->item[1].u.integer,
-	 low.b=sp[ap-args].u.array->item[2].u.integer;
-      else
-	 low.r=low.g=low.b=0;
-
-      if (sp[1+ap-args].u.array->size==3
-	  && sp[1+ap-args].u.array->item[0].type==T_INT
-	  && sp[1+ap-args].u.array->item[1].type==T_INT
-	  && sp[1+ap-args].u.array->item[2].type==T_INT)
-	 high.r=sp[1+ap-args].u.array->item[0].u.integer,
-	 high.g=sp[1+ap-args].u.array->item[1].u.integer,
-	 high.b=sp[1+ap-args].u.array->item[2].u.integer;
-      else
-	 high.r=high.g=high.b=0;
-
       steps=isteps=sp[2+ap-args].u.integer;
       ap+=3;
 
@@ -1641,7 +1616,7 @@ static void dither_floyd_steinberg_newline(struct nct_dither *dith,
 					   rgb_group **drgb,
 					   unsigned char **d8bit,
 					   unsigned short **d16bit,
-					   long **d32bit,
+					   unsigned INT32 **d32bit,
 					   int *cd)
 {
    rgbd_group *er;
@@ -1703,7 +1678,7 @@ static void dither_floyd_steinberg_firstline(struct nct_dither *dith,
 					     rgb_group **drgb,
 					     unsigned char **d8bit,
 					     unsigned short **d16bit,
-					     long **d32bit,
+					     unsigned INT32 **d32bit,
 					     int *cd)
 {
    rgbd_group *er;
@@ -1774,7 +1749,7 @@ static void dither_ordered_newline(struct nct_dither *dith,
 				   rgb_group **drgb,
 				   unsigned char **d8bit,
 				   unsigned short **d16bit,
-				   long **d32bit,
+				   unsigned INT32 **d32bit,
 				   int *cd)
 {
    dith->u.ordered.row++;
@@ -1789,6 +1764,8 @@ static rgbl_group dither_ordered_encode(struct nct_dither *dith,
    int xs=dith->u.ordered.xs;
    int ys=dith->u.ordered.ys;
 
+   fprintf(stderr,"newline\n");
+
    i=(int)(s.r+dith->u.ordered.rdiff
 	          [((rowpos+dith->u.ordered.rx)%xs)+
 		   ((dith->u.ordered.row+dith->u.ordered.ry)%ys)*xs]); 
@@ -1808,7 +1785,7 @@ static rgbl_group dither_ordered_encode_same(struct nct_dither *dith,
                                              int rowpos,
                                              rgb_group s)
 {
-   rgbl_group rgb={1,2,3};
+   rgbl_group rgb;
    int i;
 
    i=(int)(dith->u.ordered.rdiff
@@ -1827,7 +1804,6 @@ static rgbl_group dither_ordered_encode_same(struct nct_dither *dith,
      rgb.b=s.b+i; rgb.b=rgb.b>255?255:rgb.b;
    }
    return rgb;
-   return rgb;
 }
 
 
@@ -1883,6 +1859,7 @@ int image_colortable_initiate_dither(struct neo_colortable *nct,
 	 return 1;
 
       case NCTD_ORDERED:
+	 fprintf(stderr,"init ordered\n");
 	 /* copy it all */
 	 dith->u.ordered=nct->du.ordered;
 
@@ -1962,6 +1939,9 @@ void image_colortable_free_dither(struct nct_dither *dith)
 **! method object add(object(Image.image) image,int number,array(array(int)) needed)
 **! method object add(int r,int g,int b)
 **! method object add(int r,int g,int b, array(int) from1,array(int) to1,int steps1, ..., array(int) fromn,array(int) ton,int stepsn)
+**
+**  developers note:
+**  method object add|create(string "rgbrgbrgb...")
 **!
 **!	<ref>create</ref> initiates a colortable object. 
 **!	Default is that no colors are in the colortable. 
@@ -2349,6 +2329,7 @@ void image_colortable_cast_to_array(struct neo_colortable *nct)
 {
    struct nct_flat flat;
    int i;
+   int n=0;
    
    if (nct->type==NCT_NONE)
    {
@@ -2364,18 +2345,46 @@ void image_colortable_cast_to_array(struct neo_colortable *nct)
    /* sort in number order? */
 
    for (i=0; i<flat.numentries; i++)
-      if (flat.entries[i].no==-1)
+      if (flat.entries[i].no!=-1)
       {
-	 push_int(0);
+	 _image_make_rgb_color(flat.entries[i].color.r,
+			       flat.entries[i].color.g,
+			       flat.entries[i].color.b);
+	 n++;
       }
-      else
+   f_aggregate(n);
+
+   if (nct->type==NCT_CUBE)
+      free(flat.entries);
+}
+
+void image_colortable_cast_to_mapping(struct neo_colortable *nct)
+{
+   struct nct_flat flat;
+   int i,n=0;
+   
+   if (nct->type==NCT_NONE)
+   {
+      f_aggregate(0);
+      return;
+   }
+
+   if (nct->type==NCT_CUBE)
+      flat=_img_nct_cube_to_flat(nct->u.cube);
+   else
+      flat=nct->u.flat;
+
+   for (i=0; i<flat.numentries; i++)
+      if (flat.entries[i].no!=-1)
       {
-	 push_int(flat.entries[i].color.r);
-	 push_int(flat.entries[i].color.g);
-	 push_int(flat.entries[i].color.b);
-	 f_aggregate(3);
+	 push_int(flat.entries[i].no);
+	 _image_make_rgb_color(flat.entries[i].color.r,
+			       flat.entries[i].color.g,
+			       flat.entries[i].color.b);
+	 n++;
       }
-   f_aggregate(flat.numentries);
+
+   f_aggregate_mapping(n*2);
 
    if (nct->type==NCT_CUBE)
       free(flat.entries);
@@ -2489,16 +2498,16 @@ void image_colortable_cast_to_string(struct neo_colortable *nct)
 
 /*
 **! method object cast(string to)
-**!	cast the colortable to an array
+**!	cast the colortable to an array or mapping,
+**!	the array consists of <ref>Image.color</ref> objects
+**!	and are not in index order. The mapping consists of
+**!	index:<ref>Image.color</ref> pairs, where index is 
+**!	the index (int) of that color.
 **!
-**!	example: <tt>(array)Image.colortable(img)</tt>
-**! returns the resulting array
+**!	example: <tt>(mapping)Image.colortable(img)</tt>
 **!
 **! arg string to
-**!	must be "array".
-**!
-**! bugs
-**!	ignores argument (ie <tt>(string)colortable</tt> gives an array)
+**!	must be "string", "array" or "mapping".
 **/
 
 void image_colortable_cast(INT32 args)
@@ -2507,16 +2516,21 @@ void image_colortable_cast(INT32 args)
        sp[-args].type!=T_STRING) 
       error("Illegal argument 1 to Image.colortable->cast\n");
 
-   if (sp[-args].u.string==make_shared_string("array"))
+   if (sp[-args].u.string==s_array)
    {
       pop_n_elems(args);
       image_colortable_cast_to_array(THIS);
    }
-   else if (sp[-args].u.string==make_shared_string("string"))
+   else if (sp[-args].u.string==s_string)
    {
       pop_n_elems(args);
       image_colortable_cast_to_string(THIS);
    }
+   else if (sp[-args].u.string==s_mapping)
+   {
+      pop_n_elems(args);
+      image_colortable_cast_to_mapping(THIS);
+   }
    else
    {
       error("Image.colortable->cast: can't cast to %s\n",
@@ -2718,6 +2732,8 @@ void image_colortable_cubicles(INT32 args)
       THIS->lu.cubicles.accur=CUBICLE_DEFAULT_ACCUR;
    }
 
+   THIS->lookup_mode=NCT_CUBICLES;
+
    pop_n_elems(args);
    ref_push_object(THISOBJ);
 }
@@ -3326,13 +3342,11 @@ void build_rigid(struct neo_colortable *nct)
 #define NCTLU_FLAT_FULL_NAME _img_nct_index_32bit_flat_full
 #define NCTLU_CUBE_NAME _img_nct_index_32bit_cube
 #define NCTLU_FLAT_RIGID_NAME _img_nct_index_32bit_flat_rigid
-#define NCTLU_LINE_ARGS (dith,&rowpos,&s,NULL,NULL,&d,NULL,&cd)
+#define NCTLU_LINE_ARGS (dith,&rowpos,&s,NULL,NULL,NULL,&d,&cd)
 #define NCTLU_RIGID_WRITE (d[0]=(unsigned INT32)(feprim[i].no))
 #define NCTLU_DITHER_RIGID_GOT (feprim[i].color)
 #define NCTLU_SELECT_FUNCTION image_colortable_index_32bit_function
 #define NCTLU_EXECUTE_FUNCTION image_colortable_index_32bit_image
-#define NCTLU_EXECUTE image_colortable_index_32bit
-#define NCTLU_EXECUTE_NAME "index"
 
 #define NCTLU_CUBE_FAST_WRITE(SRC) \
    *d=(unsigned INT32) \
@@ -3366,8 +3380,6 @@ void build_rigid(struct neo_colortable *nct)
 #undef NCTLU_DITHER_RIGID_GOT
 #undef NCTLU_SELECT_FUNCTION
 #undef NCTLU_EXECUTE_FUNCTION
-#undef NCTLU_EXECUTE
-#undef NCTLU_EXECUTE_NAME
 
 /* done instantiating from colortable_lookup.h */
 
@@ -3479,6 +3491,36 @@ void image_colortable_map(INT32 args)
    push_object(o);
 }
 
+void image_colortable_index_32bit(INT32 args)
+{
+   struct image *src=NULL;
+   struct pike_string *ps;
+
+   if (args<1)
+      SIMPLE_TOO_FEW_ARGS_ERROR("Colortable.index",1);
+   if (sp[-args].type!=T_OBJECT ||
+       ! (src=(struct image*)get_storage(sp[-args].u.object,image_program)))
+      SIMPLE_BAD_ARG_ERROR("Colortable.index",1,"image object");
+
+   if (!src->img) 
+      SIMPLE_BAD_ARG_ERROR("Colortable.index",1,"non-empty image object");
+
+   ps=begin_shared_string(src->xsize*src->ysize*4);
+   ps->size_shift=2;
+   ps->len/=4;
+
+   if (!image_colortable_index_32bit_image(THIS,src->img,
+					   (unsigned short *)ps->str,
+					   src->xsize*src->ysize,src->xsize))
+   {
+      free_string(end_shared_string(ps));
+      SIMPLE_BAD_ARG_ERROR("Colortable.index",1,"non-empty image object");
+   }
+
+   pop_n_elems(args);
+
+   push_string(ps);
+}
 
 /*
 **! method object spacefactors(int r,int g,int b)
@@ -4150,6 +4192,10 @@ void image_colortable_image(INT32 args)
 
 void init_colortable_programs(void)
 {
+   s_array=make_shared_string("array");
+   s_string=make_shared_string("string");
+   s_mapping=make_shared_string("mapping");
+
    start_new_program();
    ADD_STORAGE(struct neo_colortable);
 
@@ -4223,10 +4269,14 @@ void init_colortable_programs(void)
 
 void exit_colortable(void) 
 {
-  if(image_colortable_program)
-  {
-    free_program(image_colortable_program);
-    image_colortable_program=0;
-  }
+   free_string(s_array);
+   free_string(s_mapping);
+   free_string(s_string);
+
+   if(image_colortable_program)
+   {
+      free_program(image_colortable_program);
+      image_colortable_program=0;
+   }
 }
 
diff --git a/src/modules/Image/colortable.h b/src/modules/Image/colortable.h
index c2a3379017..9d52ebd730 100644
--- a/src/modules/Image/colortable.h
+++ b/src/modules/Image/colortable.h
@@ -1,7 +1,7 @@
 /*
 **! module Image
 **! note
-**!	$Id: colortable.h,v 1.15 1999/04/09 17:56:51 marcus Exp $
+**!	$Id: colortable.h,v 1.16 1999/04/10 02:02:05 mirar Exp $
 */
 
 #ifdef PIKE_IMAGE_COLORTABLE_H
@@ -153,7 +153,7 @@ typedef void nct_dither_line_function(struct nct_dither *dith,
 				      rgb_group **drgb,
 				      unsigned char **d8bit,
 				      unsigned short **d16bit,
-				      long **d32bit,
+				      unsigned INT32 **d32bit,
 				      int *cd);
 
 struct nct_dither
diff --git a/src/modules/Image/colortable_lookup.h b/src/modules/Image/colortable_lookup.h
index 25020eb088..3d1661fc42 100644
--- a/src/modules/Image/colortable_lookup.h
+++ b/src/modules/Image/colortable_lookup.h
@@ -1,21 +1,21 @@
-/* $Id: colortable_lookup.h,v 1.8 1999/04/09 16:17:37 mirar Exp $ */
+/* $Id: colortable_lookup.h,v 1.9 1999/04/10 02:02:07 mirar Exp $ */
 /* included w/ defines in colortable.c */
 
 /*
 **! module Image
 **! note
-**!	$Id: colortable_lookup.h,v 1.8 1999/04/09 16:17:37 mirar Exp $
+**!	$Id: colortable_lookup.h,v 1.9 1999/04/10 02:02:07 mirar Exp $
 **! class colortable
 */
 
 
 
-static void NCTLU_FLAT_CUBICLES_NAME(rgb_group *s,
-				     NCTLU_DESTINATION *d,
-				     int n,
-				     struct neo_colortable *nct,
-				     struct nct_dither *dith,
-				     int rowlen)
+void NCTLU_FLAT_CUBICLES_NAME(rgb_group *s,
+			      NCTLU_DESTINATION *d,
+			      int n,
+			      struct neo_colortable *nct,
+			      struct nct_dither *dith,
+			      int rowlen)
 {
    struct nctlu_cubicles *cubs;
    struct nctlu_cubicle *cub;
@@ -62,32 +62,28 @@ CHRONO("begin flat/cubicles");
 
    while (n--)
    {
-      int rgbr,rgbg,rgbb;
       int r,g,b;
       struct lookupcache *lc;
       int m;
       int *ci;
+      rgbl_group val;
 
       if (dither_encode)
       {
-	 rgbl_group val;
 	 val=(dither_encode)(dith,rowpos,*s);
-	 rgbr=val.r;
-	 rgbg=val.g;
-	 rgbb=val.b;
       }
       else
       {
-	 rgbr=s->r;
-	 rgbg=s->g;
-	 rgbb=s->b;
+	 val.r=s->r;
+	 val.g=s->g;
+	 val.b=s->b;
       }
 
-      lc=nct->lookupcachehash+COLORLOOKUPCACHEHASHVALUE(rgbr,rgbg,rgbb);
+      lc=nct->lookupcachehash+COLORLOOKUPCACHEHASHVALUE(val.r,val.g,val.b);
       if (lc->index!=-1 &&
-	  lc->src.r==rgbr &&
-	  lc->src.g==rgbg &&
-	  lc->src.b==rgbb)
+	  lc->src.r==val.r &&
+	  lc->src.g==val.g &&
+	  lc->src.b==val.b)
       {
 	 NCTLU_CACHE_HIT_WRITE;
 	 goto done_pixel;
@@ -95,9 +91,9 @@ CHRONO("begin flat/cubicles");
 
       lc->src=*s;
       
-      r=((rgbr*red+hred)>>8);
-      g=((rgbg*green+hgreen)>>8);
-      b=((rgbb*blue+hblue)>>8);
+      r=((val.r*red+hred)>>8);
+      g=((val.g*green+hgreen)>>8);
+      b=((val.b*blue+hblue)>>8);
 
       cub=cubs->cubicles+r+g*red+b*redgreen;
       
@@ -113,9 +109,9 @@ CHRONO("begin flat/cubicles");
       
       while (m--)
       {
-	 int dist=sf.r*SQ(fe[*ci].color.r-rgbr)+
-	          sf.g*SQ(fe[*ci].color.g-rgbg)+
-	          sf.b*SQ(fe[*ci].color.b-rgbb);
+	 int dist=sf.r*SQ(fe[*ci].color.r-val.r)+
+	          sf.g*SQ(fe[*ci].color.g-val.g)+
+	          sf.b*SQ(fe[*ci].color.b-val.b);
 	 
 	 if (dist<mindist)
 	 {
@@ -151,12 +147,12 @@ done_pixel:
 CHRONO("end flat/cubicles");
 }
 
-static void NCTLU_FLAT_FULL_NAME(rgb_group *s,
-				 NCTLU_DESTINATION *d,
-				 int n,
-				 struct neo_colortable *nct,
-				 struct nct_dither *dith,
-				 int rowlen)
+void NCTLU_FLAT_FULL_NAME(rgb_group *s,
+			  NCTLU_DESTINATION *d,
+			  int n,
+			  struct neo_colortable *nct,
+			  struct nct_dither *dith,
+			  int rowlen)
 {
    /* no need to build any data, we're using full scan */
 
@@ -258,12 +254,12 @@ done_pixel:
    CHRONO("end flat/full map");
 }
 
-static void NCTLU_FLAT_RIGID_NAME(rgb_group *s,
-				  NCTLU_DESTINATION *d,
-				  int n,
-				  struct neo_colortable *nct,
-				  struct nct_dither *dith,
-				  int rowlen)
+void NCTLU_FLAT_RIGID_NAME(rgb_group *s,
+			   NCTLU_DESTINATION *d,
+			   int n,
+			   struct neo_colortable *nct,
+			   struct nct_dither *dith,
+			   int rowlen)
 {
    rgbl_group sf=nct->spacefactor;
    int mprim=nct->u.flat.numentries;
@@ -338,12 +334,12 @@ static void NCTLU_FLAT_RIGID_NAME(rgb_group *s,
    CHRONO("end flat/rigid map");
 }
 
-static void NCTLU_CUBE_NAME(rgb_group *s,
-			    NCTLU_DESTINATION *d,
-			    int n,
-			    struct neo_colortable *nct,
-			    struct nct_dither *dith,
-			    int rowlen)
+void NCTLU_CUBE_NAME(rgb_group *s,
+		     NCTLU_DESTINATION *d,
+		     int n,
+		     struct neo_colortable *nct,
+		     struct nct_dither *dith,
+		     int rowlen)
 {
    int red,green,blue;
    int hred,hgreen,hblue;
@@ -384,7 +380,8 @@ static void NCTLU_CUBE_NAME(rgb_group *s,
 	 {
 	    rgb=dither_encode(dith,rowpos,*s);
 	    NCTLU_CUBE_FAST_WRITE(&rgb);
-	    NCTLU_CUBE_FAST_WRITE_DITHER_GOT(&rgb);
+	    if (dither_got)
+	       NCTLU_CUBE_FAST_WRITE_DITHER_GOT(&rgb);
 	    s+=cd; d+=cd; rowpos+=cd;
 	    if (++rowcount==rowlen)
 	    {
@@ -406,29 +403,25 @@ static void NCTLU_CUBE_NAME(rgb_group *s,
 	 int mindist;
 	 int i;
 	 int nc;
-	 int rgbr,rgbg,rgbb;
 	 struct lookupcache *lc;
+	 rgbl_group val;
 
 	 if (dither_encode)
 	 {
-	    rgbl_group val;
 	    val=dither_encode(dith,rowpos,*s);
-	    rgbr=val.r;
-	    rgbg=val.g;
-	    rgbb=val.b;
 	 }
 	 else
 	 {
-	    rgbr=s->r;
-	    rgbg=s->g;
-	    rgbb=s->b;
+	    val.r=s->r;
+	    val.g=s->g;
+	    val.b=s->b;
 	 }
 
-	 lc=nct->lookupcachehash+COLORLOOKUPCACHEHASHVALUE(rgbr,rgbg,rgbb);
+	 lc=nct->lookupcachehash+COLORLOOKUPCACHEHASHVALUE(val.r,val.g,val.b);
 	 if (lc->index!=-1 &&
-	     lc->src.r==rgbr &&
-	     lc->src.g==rgbg &&
-	     lc->src.b==rgbb)
+	     lc->src.r==val.r &&
+	     lc->src.g==val.g &&
+	     lc->src.b==val.b)
 	 {
 	    NCTLU_CACHE_HIT_WRITE;
 	    goto done_pixel;
@@ -438,21 +431,21 @@ static void NCTLU_CUBE_NAME(rgb_group *s,
 
 	 if (red && green && blue)
 	 {
-	    lc->dest.r=((int)(((rgbr*red+hred)>>8)*redf));
-	    lc->dest.g=((int)(((rgbg*green+hgreen)>>8)*greenf));
-	    lc->dest.b=((int)(((rgbb*blue+hblue)>>8)*bluef));
+	    lc->dest.r=((int)(((val.r*red+hred)>>8)*redf));
+	    lc->dest.g=((int)(((val.g*green+hgreen)>>8)*greenf));
+	    lc->dest.b=((int)(((val.b*blue+hblue)>>8)*bluef));
 
 	    lc->index=i=
-	       ((rgbr*red+hred)>>8)+
-	       (((rgbg*green+hgreen)>>8)+
-		((rgbb*blue+hblue)>>8)*green)*red;
+	       ((val.r*red+hred)>>8)+
+	       (((val.g*green+hgreen)>>8)+
+		((val.b*blue+hblue)>>8)*green)*red;
 
 	    NCTLU_CACHE_HIT_WRITE;
 
 	    mindist=
-	       sf.r*SQ(rgbr-lc->dest.r)+
-	       sf.g*SQ(rgbg-lc->dest.g)+
-	       sf.b*SQ(rgbb-lc->dest.b);
+	       sf.r*SQ(val.r-lc->dest.r)+
+	       sf.g*SQ(val.g-lc->dest.g)+
+	       sf.b*SQ(val.b-lc->dest.b);
 	 }
 	 else
 	 {
@@ -472,9 +465,9 @@ static void NCTLU_CUBE_NAME(rgb_group *s,
 
 	       i=(int)
 		  (( sc->steps *
-		     ( ((int)rgbr-(int)sc->low.r)*sc->vector.r +
-		       ((int)rgbg-(int)sc->low.g)*sc->vector.g +
-		       ((int)rgbb-(int)sc->low.b)*sc->vector.b ) ) *
+		     ( ((int)val.r-(int)sc->low.r)*sc->vector.r +
+		       ((int)val.g-(int)sc->low.g)*sc->vector.g +
+		       ((int)val.b-(int)sc->low.b)*sc->vector.b ) ) *
 		   sc->invsqvector);
 
 	       if (i<0) i=0; else if (i>=sc->steps) i=sc->steps-1;
@@ -485,8 +478,8 @@ static void NCTLU_CUBE_NAME(rgb_group *s,
 		  int drgbg=sc->low.g+(int)(sc->vector.g*f);
 		  int drgbb=sc->low.b+(int)(sc->vector.b*f);
 
-		  int ldist=sf.r*SQ(rgbr-drgbr)+
-		     sf.g*SQ(rgbg-drgbg)+sf.b*SQ(rgbb-drgbb);
+		  int ldist=sf.r*SQ(val.r-drgbr)+
+		     sf.g*SQ(val.g-drgbg)+sf.b*SQ(val.b-drgbb);
 
 		  if (ldist<mindist)
 		  {
@@ -508,7 +501,7 @@ done_pixel:
          if (dither_encode)
          {
             if (dither_got)
-               dither_got(dith,rowpos,*s,NCTLU_DITHER_GOT);
+	       dither_got(dith,rowpos,*s,NCTLU_DITHER_GOT);
 	    s+=cd; d+=cd; rowpos+=cd;
 	    if (++rowcount==rowlen)
 	    {
@@ -571,39 +564,3 @@ int NCTLU_EXECUTE_FUNCTION(struct neo_colortable *nct,
 
    return 1;
 }
-
-#ifdef NCTLU_EXECUTE
-
-void NCTLU_EXECUTE(INT32 args)
-{
-   struct image *src=NULL;
-   struct pike_string *ps;
-
-   if (args<1)
-      SIMPLE_TOO_FEW_ARGS_ERROR("Colortable."NCTLU_EXECUTE_NAME,1);
-   if (sp[-args].type!=T_OBJECT ||
-       ! (src=(struct image*)get_storage(sp[-args].u.object,image_program)))
-      SIMPLE_BAD_ARG_ERROR("Colortable."NCTLU_EXECUTE_NAME,1,"image object");
-
-   if (!src->img) 
-      SIMPLE_BAD_ARG_ERROR("Colortable."NCTLU_EXECUTE_NAME,1,"non-empty image object");
-
-   ps=begin_shared_string(src->xsize*src->ysize*sizeof(NCTLU_DESTINATION));
-   while ((1<<ps->size_shift)<sizeof(NCTLU_DESTINATION))
-      ps->size_shift++;
-   ps->len>>=ps->size_shift;
-
-   if (!NCTLU_EXECUTE_FUNCTION(THIS,src->img,
-			       (unsigned short *)ps->str,
-			       src->xsize*src->ysize,src->xsize))
-   {
-      free_string(end_shared_string(ps));
-      error("colortable->index_16bit(): called colortable is not initiated\n");
-   }
-
-   pop_n_elems(args);
-
-   push_string(ps);
-}
-
-#endif /* NCTLU_EXECUTE */
diff --git a/src/modules/Image/image.h b/src/modules/Image/image.h
index 70393fc8c8..f3ec2dc17c 100644
--- a/src/modules/Image/image.h
+++ b/src/modules/Image/image.h
@@ -1,7 +1,7 @@
 /*
 **! module Image
 **! note
-**!	$Id: image.h,v 1.25 1999/03/03 04:49:34 mirar Exp $
+**!	$Id: image.h,v 1.26 1999/04/10 02:02:08 mirar Exp $
 */
 
 #ifdef PIKE_IMAGE_IMAGE_H
@@ -23,7 +23,7 @@
 #define COLORBITS 8
 
 #define COLORL_TO_COLOR(X) ((COLORTYPE)((X)>>23))
-#define COLOR_TO_COLORL(X) (((INT32)(X))*0x00808080)
+#define COLOR_TO_COLORL(X) ((((INT32)(X))*0x0808080)+((X)>>1))
 #define COLOR_TO_FLOAT(X) (((float)(X))/(float)COLORMAX)
 #define COLORL_TO_FLOAT(X) (((float)(X))/(float)COLORLMAX)
 #define FLOAT_TO_COLOR(X) ((COLORTYPE)((X)*((float)COLORMAX+0.4)))
@@ -70,6 +70,13 @@ struct image
    unsigned char alpha;
 };
 
+struct color_struct
+{
+   rgb_group rgb;
+   rgbl_group rgbl;
+   struct pike_string *name;
+};
+
 /* COMPAT: encoding of a gif - from togif */
 
 void image_togif(INT32 args);
@@ -182,6 +189,12 @@ void image_polyfill(INT32 args);
 void image_orient(INT32 args);
 void image_orient4(INT32 args);
 
+/* color.c */
+
+int image_color_svalue(struct svalue *v,rgb_group *rgb_dest);
+int image_color_arg(int arg,rgb_group *rgb_dest);
+void _image_make_rgb_color(INT32 r,INT32 g,INT32 b); 
+
 /* search.c */
 
 void image_match_phase(INT32 args);
@@ -196,3 +209,4 @@ void image_phasevh(INT32 args);
 void image_apply_max(INT32 args);
 
 void image_make_ascii(INT32 args);
+
-- 
GitLab