From aa62f975d88ec284fbc7ea165607603b99f2d714 Mon Sep 17 00:00:00 2001
From: "Mirar (Pontus Hagland)" <pike@sort.mirar.org>
Date: Tue, 10 Feb 1998 14:27:57 +0100
Subject: [PATCH] _decode bugfixes and _encode added

Rev: src/modules/Image/encodings/gif.c:1.31
---
 src/modules/Image/encodings/gif.c | 291 ++++++++++++++++++++++++------
 1 file changed, 238 insertions(+), 53 deletions(-)

diff --git a/src/modules/Image/encodings/gif.c b/src/modules/Image/encodings/gif.c
index bebbb87077..fafa9432c2 100644
--- a/src/modules/Image/encodings/gif.c
+++ b/src/modules/Image/encodings/gif.c
@@ -1,9 +1,9 @@
-/* $Id: gif.c,v 1.30 1998/01/25 08:27:14 hubbe Exp $ */
+/* $Id: gif.c,v 1.31 1998/02/10 13:27:57 mirar Exp $ */
 
 /*
 **! module Image
 **! note
-**!	$Id: gif.c,v 1.30 1998/01/25 08:27:14 hubbe Exp $
+**!	$Id: gif.c,v 1.31 1998/02/10 13:27:57 mirar Exp $
 **! submodule GIF
 **!
 **!	This submodule keep the GIF encode/decode capabilities
@@ -31,7 +31,7 @@
 
 #include "stralloc.h"
 #include "global.h"
-RCSID("$Id: gif.c,v 1.30 1998/01/25 08:27:14 hubbe Exp $");
+RCSID("$Id: gif.c,v 1.31 1998/02/10 13:27:57 mirar Exp $");
 #include "pike_macros.h"
 #include "object.h"
 #include "constants.h"
@@ -68,47 +68,6 @@ enum
    GIF_ERROR_TOO_MUCH_DATA
 };
 
-/*
-
-goal:
-
-object decode(string data);
-   Decode GIF data to one (!) image object.
-
-object decode_alpha(string data);
-   Decode GIF alpha channel to an image object.
-   black marks transparent, white marks full opaque.
-
-advanced:
-
-string netscape_loop_block(void|int number_of_loops);
-
-string _function_block(int function,string data);
-
-array __decode(string data);
-:  int xsize, int ysize, int numcol, void|string colortable, 
-:  ({ int aspectx, int aspecty, int background }),
-:
-:  (n of these:)
-:  ({ GIF.EXTENSION, int extension, string data })
-:  ({ GIF.RENDER, int x, int y, int xsize, int ysize, int bpp, 
-:     int interlace, void|string colortable, int lzwmin, string lzwdata })
-
-array _decode(string data);
-:  int xsize, int ysize, int numcol, 0|object colortable, 
-:  ({ int aspectx, int aspecty, array(int) background }),
-:
-:  (n of these:)
-:  ({ GIF.RENDER, int x, int y, 
-:     object image, 0|object alpha, object colortable, 
-:     int transparency, int transparency_index,
-:     int user_input, int disposal, int delay })
-:  ({ GIF.NETSCAPE_LOOP, int n })
-
-string _encode(array data);
-
- */
-
 #if 0
 #include <sys/resource.h>
 #define CHRONO(X) chrono(X);
@@ -247,7 +206,7 @@ void image_gif_header_block(INT32 args)
       if (sp[7-args].type!=T_INT ||
 	  sp[8-args].type!=T_INT ||
 	  sp[9-args].type!=T_INT)
-	 error("Image.GIF.render_block(): illegal argument 8..10 (expected int)\n");
+	 error("Image.GIF.header_block(): illegal argument 8..10 (expected int)\n");
       alphacolor.r=(unsigned char)(sp[7-args].u.integer);
       alphacolor.g=(unsigned char)(sp[8-args].u.integer);
       alphacolor.b=(unsigned char)(sp[9-args].u.integer);
@@ -536,10 +495,15 @@ CHRONO("gif _render_block begun");
 CHRONO("gif _render_block push of packed data begin");
 
    for (i=0;;)
-      if (lzw.outpos-i>=255)
+      if (lzw.outpos-i==0)
+      {
+	 push_string(make_shared_binary_string("\0",1));
+	 numstrings++;
+      }
+      else if (lzw.outpos-i>=255)
       {
 	 ps=begin_shared_string(256);
-	 ps->str[0]=255;
+	 *((unsigned char*)(ps->str))=255;
 	 MEMCPY(ps->str+1,lzw.out+i,255);
 	 push_string(end_shared_string(ps));
 	 numstrings++;
@@ -812,9 +776,12 @@ CHRONO("gif render_block begin");
 	          alphaidx=sp[n-args].u.integer;
 	          alpha=0;
 	          alphaentry=0;
-	          transparency=1;
-	          if (alphaidx!=-1 && numcolors<=alphaidx)
-		     error("Image.GIF.render_block(): illegal index to transparent color\n");
+	          if (alphaidx!=-1)
+		  {
+		     transparency=1;
+		     if (numcolors<=alphaidx || alphaidx<0)
+			error("Image.GIF.render_block(): illegal index to transparent color\n");
+		  }
 	          n=6;
 	       }
 	    }
@@ -1372,6 +1339,7 @@ static void _decode_get_render(unsigned char **s,
 	 push_int(0);
 	 push_int(0);
 	 push_int(0);
+	 push_int(0);
 	 *len=0;
 	 f_aggregate(10);
 	 return;
@@ -1508,6 +1476,7 @@ static void image_gif___decode(INT32 args)
 	 f_aggregate(1);
 	 s+=len;
 	 len=0;
+	 n++;
 	 break;
       }
       if (*s==0x3b && len==1) break;
@@ -1549,7 +1518,7 @@ static void image_gif___decode(INT32 args)
 **!	
 **!     <pre>
 **!	({int xsize,int ysize,    // 0: size of image drawing area
-**!	  void|string colortable, // 2: opt. global colortable 
+**!	  void|object colortable, // 2: opt. global colortable 
 **!	  ({ int aspx, int aspy,  // 3 0: aspect ratio or 0, 0 if not set
 **!	     int background }),   //   2: index of background color
 **!	</pre>
@@ -1899,8 +1868,8 @@ static void image_gif__decode(INT32 args)
 
 	       if (b->item[6].type==T_STRING)
 	       {
-		  push_svalue(a->item+6);
-		  push_object(lcto=clone_object(image_colortable_program,1));
+		  push_svalue(b->item+6);
+		  lcto=clone_object(image_colortable_program,1);
 	       }
 	       else
 	       {
@@ -2098,6 +2067,215 @@ void image_gif_decode(INT32 args)
    push_object(o);
 }
 
+/*
+**! method _encode(array data)
+**!	Encodes GIF data; reverses _decode.
+**!
+**! arg array data
+**!	data as returned from _encode
+**!
+**! note
+**!	Some given values in the array are ignored.
+**!	This function does not give the _exact_ data back!
+*/
+
+void image_gif__encode_render(INT32 args)
+{
+   struct array *a;
+   int localp;
+
+   if (args<2 ||
+       sp[-args].type!=T_ARRAY ||
+       sp[1-args].type!=T_INT)
+      error("Image.GIF._encode_render: Illegal argument(s) (expected array, int)\n");
+
+   localp=sp[1-args].u.integer;
+   (a=sp[-args].u.array)->refs++;
+   pop_n_elems(args);
+
+   if (a->size<11)
+      error("Image.GIF._encode_render: Illegal size of array\n");
+
+   push_svalue(a->item+3); /* img */
+   push_svalue(a->item+5); /* colortable */
+   push_svalue(a->item+1); /* x */
+   push_svalue(a->item+2); /* y */
+   
+   push_int(localp);
+
+   if (a->item[4].type==T_OBJECT)
+   {
+      struct neo_colortable *nct;
+
+      nct=(struct neo_colortable*)
+	 get_storage(a->item[4].u.object,image_colortable_program);
+      if (!nct)
+	 error("Image.GIF._encode_render: Passed object is not colortable\n");
+      
+      if (nct->type!=NCT_FLAT)
+	 error("Image.GIF._encode_render: Passed colortable is not flat (sorry9\n");
+      push_svalue(a->item+4);
+      if (a->item[7].type==T_INT 
+	  && a->item[7].u.integer>=0 
+	  && a->item[7].u.integer<nct->u.flat.numentries)
+      {
+	 push_int(nct->u.flat.entries[a->item[7].u.integer].color.r);
+	 push_int(nct->u.flat.entries[a->item[7].u.integer].color.g);
+	 push_int(nct->u.flat.entries[a->item[7].u.integer].color.b);
+      }
+      else
+      {
+	 push_int(0);
+	 push_int(0);
+	 push_int(0);
+      }
+      
+   }
+
+   push_svalue(a->item+8); /* delay */
+
+   if (a->item[4].type!=T_OBJECT)
+      push_int(-1);
+
+   push_svalue(a->item+6); /* interlace */
+   push_svalue(a->item+9); /* user_input */
+   push_svalue(a->item+10); /* disposal */
+
+   image_gif_render_block( (a->item[4].type==T_OBJECT) ? 13 : 10 );
+
+   free_array(a);
+}
+
+void image_gif__encode_extension(INT32 args)
+{
+   struct array *a;
+   char buf[2];
+   int n,i;
+   struct pike_string *s,*d;
+
+   if (args<1 ||
+       sp[-args].type!=T_ARRAY)
+      error("Image.GIF._encode_extension: Illegal argument(s) (expected array)\n");
+
+   (a=sp[-args].u.array)->refs++;
+   pop_n_elems(args);
+
+   if (a->size<3)
+      error("Image.GIF._encode_extension: Illegal size of array\n");
+   if (a->item[1].type!=T_INT ||
+       a->item[2].type!=T_STRING)
+      error("Image.GIF._encode_extension: Illegal type in indices 1 or 2\n");
+
+   sprintf(buf,"%c%c",0x21,a->item[1].u.integer);
+   push_string(make_shared_binary_string(buf,2));
+
+   n=1;
+   s=a->item[2].u.string;
+   for (i=0;;)
+      if (s->len-i==0)
+      {
+	 push_string(make_shared_binary_string("\0",1));
+	 n++;
+      }
+      else if (s->len-i>=255)
+      {
+   	 d=begin_shared_string(256);
+	 *((unsigned char*)(d->str))=255;
+	 MEMCPY(d->str+1,s->str+i,255);
+	 push_string(end_shared_string(d));
+	 n++;
+	 if (n>32) /* shrink stack */
+	 {
+	    f_add(n);
+	    n=1;
+	 }
+	 i+=255;
+      }
+      else
+      {
+	 d=begin_shared_string(s->len-i+2);
+	 d->str[0]=s->len-i;
+	 MEMCPY(d->str+1,s->str+i,d->len-i);
+	 d->str[d->len-i+1]=0;
+	 push_string(end_shared_string(d));
+	 n++;
+	 break;
+      }
+
+   f_add(n);
+
+   free_array(a);
+}
+
+void image_gif__encode(INT32 args)
+{
+   struct array *a,*b;
+   INT32 pos;
+   int n;
+
+   if (args<1 ||
+       sp[-args].type!=T_ARRAY)
+      error("Image.GIF._encode: Illegal argument (expected array)");
+
+   (a=sp[-args].u.array)->refs++;
+   pos=0;
+   n=0;
+   pop_n_elems(args);
+
+   if (a->size<4) 
+      error("Image.GIF._encode: Given array too small\n");
+   
+   push_svalue(a->item+0); /* xsize */
+   push_svalue(a->item+1); /* ysize */
+   push_svalue(a->item+2); /* colortable or void */
+
+   if (a->item[3].type!=T_ARRAY 
+      || a->item[3].u.array->size<3)
+      error("Image.GIF._encode: Illegal type on array index 3 (expected array)\n");
+
+   push_svalue(a->item[3].u.array->item+2); /* bkgi */
+   push_int(0); /* GIF87a-flag */
+   push_svalue(a->item[3].u.array->item+0); /* aspectx */
+   push_svalue(a->item[3].u.array->item+1); /* aspecty */
+
+   image_gif_header_block(7); n++;
+
+   pos=4;
+
+   while (pos<a->size)
+   {
+      if (a->item[pos].type!=T_ARRAY)
+	 error("Image.GIF._encode: Illegal type on array index %d (expected array)\n",pos);
+      b=a->item[pos].u.array;
+
+      if (b->size<1
+	  || b->item[0].type!=T_INT)
+	 error("Image.GIF._encode: Illegal array on array index %d\n",pos);
+      
+      if (b->item[0].u.integer==GIF_RENDER)
+      {
+	 push_svalue(a->item+pos);
+	 push_int(is_equal(b->item+6,a->item+2));
+	 image_gif__encode_render(2);
+	 n++;
+      }
+      else if (b->item[0].u.integer==GIF_EXTENSION)
+      {
+	 push_svalue(a->item+pos);
+	 image_gif__encode_extension(1);
+	 n++;
+      }
+      else break; /* unknown, bail! */
+      pos++;
+   }
+
+   image_gif_end_block(0); n++;
+
+   free_array(a);
+
+   f_add(n); /* add the strings */
+}
+
 /** module *******************************************/
 
 struct program *image_gif_module_program=NULL;
@@ -2133,6 +2311,13 @@ void init_image_gif(void)
    add_function("decode",image_gif_decode,
 		"function(string|array:object)",0);
 
+   add_function("_encode",image_gif__encode,
+		"function(array:string)",0);
+   add_function("_encode_render",image_gif__encode_render,
+		"function(array:string)",0);
+   add_function("_encode_extension",image_gif__encode_extension,
+		"function(array:string)",0);
+
    /** constants **/
 
    add_integer_constant("RENDERER",GIF_RENDER,0);
-- 
GitLab