Branch: Tag:

1997-05-29

1997-05-29 17:03:27 by Mirar (Pontus Hagland) <pike@sort.mirar.org>

->togif now uses gif_begin, gif_add et al a maybe
bug-generating difference is that togif has no global, but a local
color palette. I don't know what this will screw up. Works fine with
netscape, xv and netpbm.

Rev: src/modules/Image/togif.c:1.14

4:      Pontus Hagland, law@infovav.se    - $Id: togif.c,v 1.13 1997/05/28 21:00:48 mirar Exp $ + $Id: togif.c,v 1.14 1997/05/29 17:03:27 mirar Exp $      */   
21:   #include "stralloc.h"   #include "global.h"   #include "threads.h" - #include "types.h" +    #include "pike_macros.h"   #include "object.h"   #include "constants.h"
30:   #include "array.h"   #include "error.h"   #include "dynamic_buffer.h" + #include "operators.h"      #include "image.h"   #include "lzw.h"
185:    }   }    -  - struct pike_string * -  image_encode_gif(struct image *img,struct colortable *ct, -  rgb_group *transparent,int fs,int closest) - { -  dynamic_buffer buf; -  long i; -  rgb_group *rgb; -  struct lzw lzw; -  int colors,bpp; -  - CHRONO("image_encode_gif begin"); -  -  buf.s.str=NULL; -  initialize_buf(&buf); -  -  colors=4; bpp=2; -  while (colors<ct->numcol) { colors<<=1; bpp++; } -  -  low_my_binary_strcat(transparent?"GIF89a":"GIF87a",6,&buf); -  buf_word((unsigned short)img->xsize,&buf); -  buf_word((unsigned short)img->ysize,&buf); -  low_my_putchar( (char)(0xf0|(bpp-1)), &buf); -  /* | global colormap | 3 bits color res | sort | 3 bits bpp */ -  /* color res is'nt cared of */ -  -  low_my_putchar( 0, &buf ); /* background color */ -  low_my_putchar( 0, &buf ); /* just zero */ -  -  for (i=0; i<ct->numcol; i++) -  { -  low_my_putchar(ct->clut[i].r,&buf); -  low_my_putchar(ct->clut[i].g,&buf); -  low_my_putchar(ct->clut[i].b,&buf); -  } -  -  for (; i<colors; i++) -  { -  low_my_putchar(0,&buf); -  low_my_putchar(0,&buf); -  low_my_putchar(0,&buf); -  } -  -  if (transparent) -  { -  i=colortable_rgb(ct,*transparent); -  -  low_my_putchar( '!', &buf ); /* extras */ -  low_my_putchar( 0xf9, &buf ); /* transparency */ -  low_my_putchar( 4, &buf ); -  low_my_putchar( 1, &buf ); -  low_my_putchar( 0, &buf ); -  low_my_putchar( 0, &buf ); -  low_my_putchar( i, &buf ); -  low_my_putchar( 0, &buf ); -  } -  -  -  low_my_putchar( ',', &buf ); /* image separator */ -  -  buf_word(0,&buf); /* leftofs */ -  buf_word(0,&buf); /* topofs */ -  buf_word(img->xsize,&buf); /* width */ -  buf_word(img->ysize,&buf); /* height */ -  -  low_my_putchar(0x00, &buf); -  /* not interlaced (interlaced == 0x40) */ -  /* no local colormap ( == 0x80) */ -  -  low_my_putchar( bpp, &buf ); /* bits per pixel , or min 2 */ -  -  i=img->xsize*img->ysize; -  rgb=img->img; -  - CHRONO("image_encode_gif header done"); -  - THREADS_ALLOW(); -  lzw_init(&lzw,bpp); -  if (!fs) -  while (i--) lzw_add(&lzw,colortable_rgb(ct,*(rgb++))); -  else -  { -  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); -  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, -  errb[i].b=(rand()%(FS_SCALE*2+1))-FS_SCALE; -  -  w=0; -  i=img->ysize; -  while (i--) -  { -  image_floyd_steinberg(rgb,img->xsize,errb,w=!w,cres,ct,closest); -  for (j=0; j<img->xsize; j++) -  lzw_add(&lzw,cres[j]); -  rgb+=img->xsize; -  } -  -  free(errb); -  free(cres); -  } -  -  lzw_write_last(&lzw); -  - CHRONO("lzw done"); -  -  for (i=0; i<(int)lzw.outpos; i+=254) -  { -  int wr; -  if (i+254>(int)lzw.outpos) wr=lzw.outpos-i; -  else wr=254; -  low_my_putchar( (unsigned char)wr, &buf ); /* bytes in chunk */ -  low_my_binary_strcat( (char *) lzw.out+i, wr, &buf ); -  } -  low_my_putchar( 0, &buf ); /* terminate stream */ -  - CHRONO("image_encode_gif wrote ok"); -  -  lzw_quit(&lzw); -  -  low_my_putchar( ';', &buf ); /* end gif file */ -  - CHRONO("image_encode_gif done"); - THREADS_DISALLOW(); -  -  return low_free_buf(&buf); - } -  +    #define STD_ARENA_SIZE 16384      int image_decode_gif(struct image *dest,struct image *dest_alpha,
474:    if (THIS->img) free(THIS->img);    THIS->img=NULL;    -  image_decode_gif(THIS,NULL,sp[-args].u.string->str,sp[-args].u.string->len); +  image_decode_gif(THIS,NULL, +  (unsigned char*)sp[-args].u.string->str, +  sp[-args].u.string->len);       pop_n_elems(args);    THISOBJ->refs++;
501:    img->alpha=0;   }    - /* - **! method string togif() - **! method string togif(int num_colors) - **! method string togif(array(array(int)) colors) - **! 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 num_colors) - **! method string togif_fs(array(array(int)) colors) - **! 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: togif_begin, togif_add, togif_end, toppm, fromgif - */ +     - void image_togif(INT32 args) - { -  rgb_group *transparent=NULL; -  struct colortable *ct=NULL; -  -  if (args>0 && sp[-args].type==T_ARRAY) -  ct=colortable_from_array(sp[-args].u.array,"image->togif()\n"); -  else if (args>0 && args!=3 && sp[-args].type==T_INT) -  ct=colortable_quant(THIS,min(256,max(2,sp[-args].u.integer))); -  -  if (args>=3+!!ct) -  { -  getrgb(THIS,!!ct,args,"image->togif() (transparency)"); -  transparent=&(THIS->rgb); -  } -  -  pop_n_elems(args); -  if (!THIS->img) { error("no image\n"); return; } -  -  if (!ct) ct=colortable_quant(THIS,256); -  push_string( image_encode_gif( THIS,ct, transparent, 0, 0) ); -  colortable_free(ct); - } -  -  - void image_togif_fs(INT32 args) - { -  rgb_group *transparent=NULL; -  struct colortable *ct=NULL; -  int closest=0; -  -  if (args>0 && sp[-args].type==T_ARRAY) -  { -  ct=colortable_from_array(sp[-args].u.array,"image->togif_fs()\n"); -  closest=1; -  } -  else if (args>0 && args!=3 && sp[-args].type==T_INT) -  ct=colortable_quant(THIS,min(256,max(2,sp[-args].u.integer))); -  -  if (args>=3+!!ct) -  { -  getrgb(THIS,!!ct,args,"image->togif() (transparency)"); -  transparent=&(THIS->rgb); -  } -  -  pop_n_elems(args); -  if (!THIS->img) { error("no image\n"); return; } -  -  if (!ct) -  ct=colortable_quant(THIS,256); -  push_string( image_encode_gif( THIS,ct, transparent, 1, closest) ); -  colortable_free(ct); - } -  +    /*   **! method string gif_begin()   **! method string gif_begin(int num_colors)
697:    push_string(make_shared_binary_string(buf,19));   }    - static void img_gif_add(INT32 args,int fs,int lm) + /* + **! method string gif_transparency(int color) + **! + **! returns a gif chunk that transparent a color in the next image chunk + **! + **! arg int color + **! index of color in the palette + **! note + **! Yes - i know this function is too hard to use. :/ + **! The palette _is_ unknown mostly... + **! see also: gif_add, gif_begin, gif_end + */ +  + void image_gif_transparency(INT32 args)   { -  +  unsigned short i=0; +  char buf[30]; +  if (args) +  if (sp[-args].type!=T_INT) +  error("Illegal argument to image->gif_transparency()\n"); +  else +  i=sp[-args].u.integer; +  else +  error("Too few arguments to image->gif_transparency()\n"); +  pop_n_elems(args); +  +  sprintf(buf,"%c%c%c%c%c%c%c%c",33,0xf9,4,1,0,0,i,0); +  +  push_string(make_shared_binary_string(buf,8)); + } +  + static struct colortable *img_gif_add(INT32 args,int fs,int lm) + {    INT32 x=0,y=0,i;    struct lzw lzw;    rgb_group *rgb;
839:       lzw_quit(&lzw);    -  colortable_free(ct); +     THREADS_DISALLOW();      CHRONO("done");       pop_n_elems(args);    push_string(low_free_buf(&buf)); -  +  +  return ct;   }      /*
920:      void image_gif_add(INT32 args)   { -  img_gif_add(args,0,1); +  colortable_free(img_gif_add(args,0,1));   }      void image_gif_add_fs(INT32 args)   { -  img_gif_add(args,1,1); +  colortable_free(img_gif_add(args,1,1));   }      void image_gif_add_nomap(INT32 args)   { -  img_gif_add(args,0,0); +  colortable_free(img_gif_add(args,0,0));   }      void image_gif_add_fs_nomap(INT32 args)   { -  img_gif_add(args,1,0); +  colortable_free(img_gif_add(args,1,0));   }    -  + /* + **! method string togif() + **! method string togif(int num_colors) + **! method string togif(array(array(int)) colors) + **! 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 num_colors) + **! method string togif_fs(array(array(int)) colors) + **! 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: togif_begin, togif_add, togif_end, toppm, fromgif + */ +  +  + static void img_encode_gif(rgb_group *transparent,int fs,INT32 args) + { +  struct colortable *ct; +  struct svalue sv; +  +  /* on stack is now: +  - eventual colortable instruction (number or array) */ +  +  /* (swap in) arguments to gif_add, x and y position */ +  push_int(0); if (args) { sv=sp[-1]; sp[-1]=sp[-2]; sp[-2]=sv; } +  push_int(0); if (args) { sv=sp[-1]; sp[-1]=sp[-2]; sp[-2]=sv; } +  +  ct=img_gif_add(args+2,fs,1); +  image_gif_begin(0); +  +  /* on stack is now: +  - gif image chunk with local palette +  - gif beginning */ +  +  /* swap them... */ +  sv=sp[-1]; sp[-1]=sp[-2]; sp[-2]=sv; +  +  if (transparent) +  { +  push_int(colortable_rgb(ct,*transparent)); +  image_gif_transparency(1); +  sv=sp[-1]; sp[-1]=sp[-2]; sp[-2]=sv; +  } +  colortable_free(ct); +  image_gif_end(0); +  +  /* on stack is now: +  - gif beginning +  - eventual transparency chunk +  - image with local palette +  - gif end chunk */ +  +  f_add(3+!!transparent); + /* f_aggregate(4);*/ + } +  + 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); + }