ab6aec1997-02-11Fredrik Hübinette (Hubbe) /* togif
a7a3c91999-05-24Mirar (Pontus Hagland) $Id: togif.c,v 1.35 1999/05/24 15:09:21 mirar Exp $
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
844eae1997-11-07Mirar (Pontus Hagland) old GIF API compat stuff
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  */
e3cb4b1997-04-03Mirar (Pontus Hagland) /* **! module Image
4ce7411997-05-29Mirar (Pontus Hagland) **! note
a7a3c91999-05-24Mirar (Pontus Hagland) **! $Id: togif.c,v 1.35 1999/05/24 15:09:21 mirar Exp $
448c201999-04-13Mirar (Pontus Hagland) **! class Image
e3cb4b1997-04-03Mirar (Pontus Hagland) */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) #include "global.h" #include <math.h> #include <ctype.h> #include "stralloc.h" #include "global.h" #include "threads.h"
bb55f81997-03-16Fredrik Hübinette (Hubbe) #include "pike_macros.h"
ab6aec1997-02-11Fredrik Hübinette (Hubbe) #include "object.h" #include "constants.h" #include "interpret.h" #include "svalue.h" #include "array.h" #include "error.h" #include "dynamic_buffer.h"
c84ebd1997-05-29Mirar (Pontus Hagland) #include "operators.h"
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  #include "image.h"
7d98c81997-11-08Henrik Grubbström (Grubba) #include "colortable.h"
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) #ifdef THIS #undef THIS /* Needed for NT */ #endif
ab6aec1997-02-11Fredrik Hübinette (Hubbe) #define THIS ((struct image *)(fp->current_storage)) #define THISOBJ (fp->current_object)
844eae1997-11-07Mirar (Pontus Hagland) extern struct program *image_colortable_program;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
e3cb4b1997-04-03Mirar (Pontus Hagland) /*
a7a3c91999-05-24Mirar (Pontus Hagland) **< method string gif_begin() **< method string gif_begin(int num_colors) **< method string gif_begin(array(array(int)) colors) **< method string gif_end() **< method string gif_netscape_loop(int loops) **< method string togif() **< method string togif(int trans_r,int trans_g,int trans_b) **< method string togif(int num_colors,int trans_r,int trans_g,int trans_b) **< method string togif(array(array(int)) colors,int trans_r,int trans_g,int trans_b) **< method string togif_fs() **< method string togif_fs(int trans_r,int trans_g,int trans_b) **< method string togif_fs(int num_colors,int trans_r,int trans_g,int trans_b) **< method string togif_fs(array(array(int)) colors,int trans_r,int trans_g,int trans_b) **< method string gif_add() **< method string gif_add_fs() **< method string gif_add_nomap() **< method string gif_add_fs_nomap() **< method string gif_add*(int x,int y) **< method string gif_add*(int x,int y,int delay_cs) **< method string gif_add*(int x,int y,int num_colors,int delay_cs) **< method string gif_add*(int x,int y,array(array(int)) colors,int delay_cs) **< old GIF API compatibility function. Don't use **< in any new code. **< **< <table> **< <tr><td></td><td>is replaced by</td></tr> **< <tr><td>gif_begin</td><td><ref>Image.GIF.header_block</ref></td></tr> **< <tr><td>gif_end</td><td><ref>Image.GIF.end_block</ref></td></tr> **< <tr><td>gif_netscape_loop</td><td><ref>Image.GIF.netscape_loop_block</ref></td></tr> **< <tr><td>togif</td><td><ref>Image.GIF.encode</ref></td></tr> **< <tr><td>togif_fs</td><td><ref>Image.GIF.encode</ref>¹</td></tr> **< <tr><td>gif_add</td><td><ref>Image.GIF.render_block</ref>¹²</td></tr> **< <tr><td>gif_add_fs</td><td><ref>Image.GIF.render_block</ref>¹</td></tr> **< <tr><td>gif_add_nomap</td><td><ref>Image.GIF.render_block</ref>²</td></tr> **< <tr><td>gif_add_fs_nomap</td><td><ref>Image.GIF.render_block</ref>¹²</td></tr> **< </table> **< **< ¹ Use <ref>Image.Colortable</ref> to get whatever dithering **< you want. **< **< ² local map toggle is sent as an argument **< **< returns GIF data.
e3cb4b1997-04-03Mirar (Pontus Hagland) */
844eae1997-11-07Mirar (Pontus Hagland) extern void image_gif_header_block(INT32 args); extern void image_gif_end_block(INT32 args); extern void image_gif_netscape_loop_block(INT32 args);
87b4cb1997-11-11Mirar (Pontus Hagland) extern void image_gif_render_block(INT32 args);
844eae1997-11-07Mirar (Pontus Hagland) 
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void image_gif_begin(INT32 args) { if (args) {
844eae1997-11-07Mirar (Pontus Hagland)  struct object *o; if (sp[-args].type==T_INT)
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  {
844eae1997-11-07Mirar (Pontus Hagland)  int i=sp[-args].u.integer; pop_n_elems(args); push_int(THIS->xsize); push_int(THIS->ysize);
d6ac731998-04-20Henrik Grubbström (Grubba)  ref_push_object(THISOBJ);
844eae1997-11-07Mirar (Pontus Hagland)  push_int(i); o=clone_object(image_colortable_program,2);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  }
844eae1997-11-07Mirar (Pontus Hagland)  else
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  {
844eae1997-11-07Mirar (Pontus Hagland)  o=clone_object(image_colortable_program,args);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  }
844eae1997-11-07Mirar (Pontus Hagland)  push_int(THIS->xsize); push_int(THIS->ysize); push_object(o); image_gif_header_block(3); } else { push_int(THIS->xsize); push_int(THIS->ysize); push_int(256); image_gif_header_block(3);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } } void image_gif_end(INT32 args) {
844eae1997-11-07Mirar (Pontus Hagland)  image_gif_end_block(args);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) } void image_gif_netscape_loop(INT32 args) {
844eae1997-11-07Mirar (Pontus Hagland)  image_gif_netscape_loop_block(args);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) }
844eae1997-11-07Mirar (Pontus Hagland) static void img_gif_add(INT32 args,int fs,int lm, rgb_group *transparent) { INT32 x=0,y=0; int delay=0; struct object *ncto=NULL;
2c5da31997-11-26Mirar (Pontus Hagland)  struct svalue *msp=sp;
844eae1997-11-07Mirar (Pontus Hagland)  if (args==0) x=y=0; else if (args<2 || sp[-args].type!=T_INT || sp[1-args].type!=T_INT) error("Illegal argument(s) to image->gif_add()\n"); else { x=sp[-args].u.integer; y=sp[1-args].u.integer; } if (args>2 && sp[2-args].type==T_ARRAY) { struct svalue *sv=sp+2-args; push_svalue(sv);
2c5da31997-11-26Mirar (Pontus Hagland)  ncto=clone_object(image_colortable_program,1);
844eae1997-11-07Mirar (Pontus Hagland)  } else if (args>3 && sp[2-args].type==T_INT) { INT32 i=sp[2-args].u.integer;
d6ac731998-04-20Henrik Grubbström (Grubba)  ref_push_object(THISOBJ);
844eae1997-11-07Mirar (Pontus Hagland)  push_int(i); ncto=clone_object(image_colortable_program,2); } if (args>2+!!ncto) { if (sp[2+!!ncto-args].type==T_INT) delay=sp[2+!!ncto-args].u.integer; else if (sp[2+!!ncto-args].type==T_FLOAT) delay=(unsigned short)(sp[2+!!ncto-args].u.float_number*100); else error("Illegal argument %d to image->gif_add()\n",3+!!ncto); } if (!ncto) {
d6ac731998-04-20Henrik Grubbström (Grubba)  ref_push_object(THISOBJ);
7f2c551997-11-07Mirar (Pontus Hagland)  push_int(255);
844eae1997-11-07Mirar (Pontus Hagland)  ncto=clone_object(image_colortable_program,2); } if (fs) image_colortable_internal_floyd_steinberg(
f137f61997-11-11Henrik Grubbström (Grubba)  (struct neo_colortable *)get_storage(ncto,image_colortable_program));
844eae1997-11-07Mirar (Pontus Hagland)  pop_n_elems(args);
d6ac731998-04-20Henrik Grubbström (Grubba)  ref_push_object(THISOBJ);
844eae1997-11-07Mirar (Pontus Hagland)  push_object(ncto); push_int(x); push_int(y); push_int(lm); push_int(delay); if (transparent) { unsigned char trd;
f137f61997-11-11Henrik Grubbström (Grubba)  image_colortable_index_8bit_image((struct neo_colortable *) get_storage(ncto,
844eae1997-11-07Mirar (Pontus Hagland)  image_colortable_program), transparent,&trd,1,1); push_int(trd); image_gif_render_block(7); } else image_gif_render_block(6); }
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void image_gif_add(INT32 args) {
844eae1997-11-07Mirar (Pontus Hagland)  img_gif_add(args,0,1,NULL);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) } void image_gif_add_fs(INT32 args) {
844eae1997-11-07Mirar (Pontus Hagland)  img_gif_add(args,1,1,NULL);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) } void image_gif_add_nomap(INT32 args) {
844eae1997-11-07Mirar (Pontus Hagland)  img_gif_add(args,0,0,NULL);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) } void image_gif_add_fs_nomap(INT32 args) {
844eae1997-11-07Mirar (Pontus Hagland)  img_gif_add(args,1,0,NULL);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) }
c84ebd1997-05-29Mirar (Pontus Hagland) /*
a7a3c91999-05-24Mirar (Pontus Hagland) **< method string togif() **< method string togif(int trans_r,int trans_g,int trans_b) **< method string togif(int num_colors,int trans_r,int trans_g,int trans_b) **< method string togif(array(array(int)) colors,int trans_r,int trans_g,int trans_b) **< method string togif_fs() **< method string togif_fs(int trans_r,int trans_g,int trans_b) **< method string togif_fs(int num_colors,int trans_r,int trans_g,int trans_b) **< method string togif_fs(array(array(int)) colors,int trans_r,int trans_g,int trans_b) **< Makes GIF data. The togif_fs variant uses floyd-steinberg **< dithereing. **< returns the GIF data **< **< arg int num_colors **< number of colors to quantize to (default is 256) **< array array(array(int)) colors **< colors to map to (default is to quantize to 256), format is ({({r,g,b}),({r,g,b}),...}). **< arg int trans_r **< arg int trans_g **< arg int trans_b **< one color, that is to be transparent. **< see also: gif_begin, gif_add, gif_end, toppm, fromgif
c84ebd1997-05-29Mirar (Pontus Hagland) */
7f2c551997-11-07Mirar (Pontus Hagland) extern void _image_gif_encode(INT32 args,int fs);
c84ebd1997-05-29Mirar (Pontus Hagland)  static void img_encode_gif(rgb_group *transparent,int fs,INT32 args) {
7f2c551997-11-07Mirar (Pontus Hagland)  struct object *co=NULL; if (args) { if (sp[-args].type==T_OBJECT) {
d6ac731998-04-20Henrik Grubbström (Grubba)  add_ref(co=sp[-args].u.object);
7f2c551997-11-07Mirar (Pontus Hagland)  pop_n_elems(args); } else if (sp[-args].type==T_ARRAY) co=clone_object(image_colortable_program,args); else if (sp[-args].type==T_INT) { unsigned long numcolors=sp[-args].u.integer; pop_n_elems(args);
d6ac731998-04-20Henrik Grubbström (Grubba)  ref_push_object(THISOBJ);
7f2c551997-11-07Mirar (Pontus Hagland)  push_int(numcolors); co=clone_object(image_colortable_program,2); } else error("Illegal argument to img->togif()\n"); } else {
d6ac731998-04-20Henrik Grubbström (Grubba)  ref_push_object(THISOBJ);
7f2c551997-11-07Mirar (Pontus Hagland)  push_int(256); co=clone_object(image_colortable_program,2); }
d6ac731998-04-20Henrik Grubbström (Grubba)  ref_push_object(THISOBJ);
7f2c551997-11-07Mirar (Pontus Hagland)  push_object(co); if (transparent) { push_int(transparent->r); push_int(transparent->g); push_int(transparent->b); _image_gif_encode(5,fs); } else _image_gif_encode(2,fs);
844eae1997-11-07Mirar (Pontus Hagland) }
f6dbf61999-05-20Mirar (Pontus Hagland) static INLINE int getrgb(struct image *img, INT32 args_start,INT32 args,char *name)
844eae1997-11-07Mirar (Pontus Hagland) { INT32 i;
f6dbf61999-05-20Mirar (Pontus Hagland)  if (args-args_start<1) return 0; if (image_color_svalue(sp-args+args_start,&(img->rgb))) return 1; if (args-args_start<3) return 0;
844eae1997-11-07Mirar (Pontus Hagland)  for (i=0; i<3; i++) if (sp[-args+i+args_start].type!=T_INT) error("Illegal r,g,b argument to %s\n",name); img->rgb.r=(unsigned char)sp[-args+args_start].u.integer; img->rgb.g=(unsigned char)sp[1-args+args_start].u.integer; img->rgb.b=(unsigned char)sp[2-args+args_start].u.integer;
b56e5a1998-04-24Mirar (Pontus Hagland)  if (args-args_start>=4)
844eae1997-11-07Mirar (Pontus Hagland)  if (sp[3-args+args_start].type!=T_INT) error("Illegal alpha argument to %s\n",name); else
f6dbf61999-05-20Mirar (Pontus Hagland)  {
844eae1997-11-07Mirar (Pontus Hagland)  img->alpha=sp[3-args+args_start].u.integer;
f6dbf61999-05-20Mirar (Pontus Hagland)  return 4; }
b56e5a1998-04-24Mirar (Pontus Hagland)  else
f6dbf61999-05-20Mirar (Pontus Hagland)  {
844eae1997-11-07Mirar (Pontus Hagland)  img->alpha=0;
f6dbf61999-05-20Mirar (Pontus Hagland)  return 3; }
c84ebd1997-05-29Mirar (Pontus Hagland) } void image_togif(INT32 args) { rgb_group *transparent=NULL; if (args>=3) { getrgb(THIS,args>3,args,"image->togif() (transparency)"); transparent=&(THIS->rgb); } if (args==3) pop_n_elems(3); else if (args) pop_n_elems(args-1); if (!THIS->img) { error("no image\n"); return; } img_encode_gif(transparent, 0, args&&args!=3); } void image_togif_fs(INT32 args) { rgb_group *transparent=NULL; if (args>=3) { getrgb(THIS,args>3,args,"image->togif() (transparency)"); transparent=&(THIS->rgb); } if (args==3) pop_n_elems(3); else if (args) pop_n_elems(args-1); if (!THIS->img) { error("no image\n"); return; } img_encode_gif(transparent, 1, args&&args!=3); }