From b54bd6a0f22a730bab9ab4ba63621a24902baf95 Mon Sep 17 00:00:00 2001
From: "Mirar (Pontus Hagland)" <pike@sort.mirar.org>
Date: Sun, 13 Oct 1996 23:08:32 +0200
Subject: [PATCH] minor patches & warnings fixed in lzw.c

Rev: src/modules/image/image.c:1.15
Rev: src/modules/image/image.h:1.4
Rev: src/modules/image/lzw.c:1.4
Rev: src/modules/image/quant.c:1.7
Rev: src/modules/image/togif.c:1.7
---
 src/modules/image/image.c | 89 +++++++++++++++++++++++++++++++++------
 src/modules/image/image.h |  7 +++
 src/modules/image/lzw.c   |  4 +-
 src/modules/image/quant.c | 63 ++++++++++++++++++++++++++-
 src/modules/image/togif.c | 14 +++---
 5 files changed, 153 insertions(+), 24 deletions(-)

diff --git a/src/modules/image/image.c b/src/modules/image/image.c
index ea81055763..714e038642 100644
--- a/src/modules/image/image.c
+++ b/src/modules/image/image.c
@@ -1743,7 +1743,7 @@ void image_modify_by_intensity(INT32 args)
    push_object(o);
 }
 
-static void image_quant(INT32 args)
+static void image_map_closest(INT32 args)
 {
    struct colortable *ct;
    long i;
@@ -1751,18 +1751,13 @@ static void image_quant(INT32 args)
    int colors;
 
    if (!THIS->img) error("no image\n");
-   if (args>=1)
-      if (sp[-args].type==T_INT) 
-	 colors=sp[-args].u.integer;
-      else
-	 error("Illegal argument to image->quant()\n");
-   else
-      colors=256;
+   if (args<1
+       || sp[-args].type!=T_ARRAY)
+      error("illegal argument to image->map_closest()\n");
       
+   ct=colortable_from_array(sp[-args].u.array,"image->map_closest()\n");
    pop_n_elems(args);
 
-   ct=colortable_quant(THIS,colors);
-
    i=THIS->xsize*THIS->ysize;
    rgb=THIS->img;
    while (i--)
@@ -1772,9 +1767,75 @@ static void image_quant(INT32 args)
    }
 
    colortable_free(ct);
+   THISOBJ->refs++;
+   push_object(THISOBJ);
+}
+
+static void image_map_fs(INT32 args)
+{
+   struct colortable *ct;
+   INT32 i,j;
+   rgb_group *rgb;
+   int *res,w;
+   rgbl_group *errb;
+   
+   if (!THIS->img) error("no image\n");
+   if (args<1
+       || sp[-args].type!=T_ARRAY)
+      error("illegal argument to image->map_fs()\n");
+
+   res=(int*)xalloc(sizeof(int)*THIS->xsize);
+   errb=(rgbl_group*)xalloc(sizeof(rgbl_group)*THIS->xsize);
+      
+   ct=colortable_from_array(sp[-args].u.array,"image->map_closest()\n");
+   pop_n_elems(args);
+
+   for (i=0; i<THIS->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;
+
+   i=THIS->ysize;
+   rgb=THIS->img;
+   w=0;
+   while (i--)
+   {
+      image_floyd_steinberg(rgb,THIS->xsize,errb,w=!w,res,ct);
+      for (j=0; j<THIS->xsize; j++)
+	 *(rgb++)=ct->clut[res[j]];
+   }
+
+   free(errb);
+   free(res);
+   colortable_free(ct);
+   THISOBJ->refs++;
+   push_object(THISOBJ);
+}
+
+void image_select_colors(INT32 args)
+{
+   rgb_group *transparent=NULL;
+   struct colortable *ct;
+   int colors,i;
+
+   if (args<1
+      || sp[-args].type!=T_INT)
+      error("Illegal argument to image->select_colors()\n");
 
+   colors=sp[-args].u.integer;
    pop_n_elems(args);
-   push_int(0);
+   if (!THIS->img) { error("no image\n");  return; }
+
+   ct=colortable_quant(THIS,colors);
+   for (i=0; i<colors; i++)
+   {
+      push_int(ct->clut[i].r);
+      push_int(ct->clut[i].g);
+      push_int(ct->clut[i].b);
+      f_aggregate(3);
+   }
+   f_aggregate(colors);
+   colortable_free(ct);
 }
 
 static void image_ccw(INT32 args)
@@ -2003,8 +2064,12 @@ void init_image_programs()
    add_function("ysize",image_ysize,
 		"function(:int)",0);
 
-   add_function("quant",image_quant,
+   add_function("map_closest",image_map_closest,
+                "function(:object)",0);
+   add_function("map_fs",image_map_fs,
                 "function(:object)",0);
+   add_function("select_colors",image_select_colors,
+                "function(int:array(array(int)))",0);
 		
    set_init_callback(init_image_struct);
    set_exit_callback(exit_image_struct);
diff --git a/src/modules/image/image.h b/src/modules/image/image.h
index ef9b0a4376..fa3359b8d9 100644
--- a/src/modules/image/image.h
+++ b/src/modules/image/image.h
@@ -7,6 +7,8 @@
 
 #define COLOURTYPE unsigned char
 
+#define FS_SCALE 1024
+
 typedef struct 
 {
    COLOURTYPE r,g,b;
@@ -48,6 +50,7 @@ struct colortable
 struct colortable *colortable_quant(struct image *img,int numcol);
 int colortable_rgb(struct colortable *ct,rgb_group rgb);
 void colortable_free(struct colortable *ct);
+struct colortable *colortable_from_array(struct array *arr,char *from);
 
 /* encoding of a gif - from togif */
 
@@ -55,4 +58,8 @@ struct pike_string *
    image_encode_gif(struct image *img,struct colortable *ct,
 		    rgb_group *transparent,
 		    int floyd_steinberg);
+void image_floyd_steinberg(rgb_group *rgb,int xsize,
+			   rgbl_group *errl,
+			   int way,int *res,
+			   struct colortable *ct);
 
diff --git a/src/modules/image/lzw.c b/src/modules/image/lzw.c
index 035162a321..225fd40c75 100644
--- a/src/modules/image/lzw.c
+++ b/src/modules/image/lzw.c
@@ -20,7 +20,7 @@ static void lzw_output(struct lzw *lzw,lzwcode_t codeno);
 
 void lzw_init(struct lzw *lzw,int bits)
 {
-   int i;
+   unsigned long i;
 #ifdef GIF_LZW
    lzw->codes=(1L<<bits)+2;
 #else
@@ -186,7 +186,7 @@ void lzw_add(struct lzw *lzw,int c)
    l->c=c;
 
    lzw->codes++;
-   if (lzw->codes>(1L<<lzw->codebits)) lzw->codebits++;
+   if (lzw->codes>(unsigned long)(1L<<lzw->codebits)) lzw->codebits++;
 
    lzw->current=lzw->code+c;
 }
diff --git a/src/modules/image/quant.c b/src/modules/image/quant.c
index ec7ab286df..21884642a1 100644
--- a/src/modules/image/quant.c
+++ b/src/modules/image/quant.c
@@ -17,6 +17,7 @@ David K
 #include "types.h"
 #include "error.h"
 #include "global.h"
+#include "array.h"
 
 #include "image.h"
 
@@ -426,9 +427,8 @@ struct colortable *colortable_quant(struct image *img,int numcol)
 
   ct = malloc(sizeof(struct colortable)+sizeof(rgb_group)*numcol);
   if (!ct) error("Out of memory.\n");
-  ct->numcol=numcol;
-
   MEMSET(ct,0,sizeof(struct colortable)+sizeof(rgb_group)*numcol);
+  ct->numcol=numcol;
 
 #ifdef QUANT_DEBUG
   fprintf(stderr,"Moving colors into hashtable\n");
@@ -509,6 +509,65 @@ struct colortable *colortable_quant(struct image *img,int numcol)
   return ct;
 }
 
+
+struct colortable *colortable_from_array(struct array *arr,char *from)
+{
+  rgb_hashtbl *tbl;
+  INT32 i,j;
+  coltab *ct;
+  rgb_group black,white;
+  rgb_group *p;
+  INT32 entries=0;
+  struct svalue s,s2;
+
+#ifdef QUANT_DEBUG
+  fprintf(stderr,"ctfa called\n");
+#endif
+  CHRONO("ctfa");
+
+  white.r=white.g=white.b=255;
+  black.r=black.g=black.b=0;
+
+  tbl=img_rehash(NULL,arr->size);
+  
+  s2.type=s.type=T_INT;
+  for (i=0; i<arr->size; i++)
+  {
+     array_index(&s,arr,i);
+     if (s.type!=T_ARRAY || s.u.array->size<3)
+     {
+	free(tbl);
+	error("Illegal type in colorlist, element %d, %s\n",i,from);
+     }
+     array_index(&s2,s.u.array,0);
+     if (s2.type!=T_INT) tbl->tbl[i].rgb.r=0; else tbl->tbl[i].rgb.r=s2.u.integer;
+     array_index(&s2,s.u.array,1);
+     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;
+  }
+  free_svalue(&s);
+  free_svalue(&s2);
+
+  ct = malloc(sizeof(struct colortable)+sizeof(rgb_group)*arr->size);
+  if (!ct) { free(tbl); error("Out of memory.\n"); }
+  MEMSET(ct,0,sizeof(struct colortable)+sizeof(rgb_group)*arr->size);
+  ct->numcol=arr->size;
+
+  CHRONO("sort");
+  sort_tbl(tbl, 0, arr->size, 0, 0, arr->size, -1, ct, black, white);
+
+#ifdef QUANT_DEBUG
+  fprintf(stderr,"img_quant done, %d colors selected\n", arr->size);
+#endif
+  CHRONO("done");
+
+  free(tbl);
+  CHRONO("really done");
+  return ct;
+}
+
+
 #define sq(x) ((x)*(x))
 #define DISTANCE(A,B) \
    (sq((A).r-(B).r)+sq((A).g-(B).g)+sq((A).b-(B).b))
diff --git a/src/modules/image/togif.c b/src/modules/image/togif.c
index 30c82ee3bf..ecf69c5917 100644
--- a/src/modules/image/togif.c
+++ b/src/modules/image/togif.c
@@ -29,7 +29,6 @@ static void buf_word( unsigned short w, dynamic_buffer *buf )
    low_my_putchar( (w>>8)&0xff, buf );
 }
 
-#define FS_SCALE 1024
 #define WEIGHT_NEXT(X) (((X)*8)/20)
 #define WEIGHT_DOWNNEXT(X) (((X)*3)/20)
 #define WEIGHT_DOWN(X) (((X)*3)/20)
@@ -104,10 +103,10 @@ static int floyd_steinberg_add(rgbl_group *errl,
    return c;
 }
 
-static void floyd_steinberg(rgb_group *rgb,int xsize,
-			    rgbl_group *errl,
-			    int way,int *res,
-			    struct colortable *ct)
+void image_floyd_steinberg(rgb_group *rgb,int xsize,
+			   rgbl_group *errl,
+			   int way,int *res,
+			   struct colortable *ct)
 {
    rgbl_group err;
    int x;
@@ -205,12 +204,11 @@ struct pike_string *
       while (i--) lzw_add(&lzw,colortable_rgb(ct,*(rgb++)));
    else
    {
-      rgbl_group err,*errb;
+      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);
-      err.r=err.g=err.b=0;
       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,
@@ -220,7 +218,7 @@ struct pike_string *
       i=img->ysize;
       while (i--)
       {
-	 floyd_steinberg(rgb,img->xsize,errb,w=!w,cres,ct);
+	 image_floyd_steinberg(rgb,img->xsize,errb,w=!w,cres,ct);
 	 for (j=0; j<img->xsize; j++)
 	    lzw_add(&lzw,cres[j]);
 	 rgb+=img->xsize;
-- 
GitLab