pike.git / src / modules / Image / togif.c

version» Context lines:

pike.git/src/modules/Image/togif.c:1:   /*      togif      Pontus Hagland, law@infovav.se    - $Id: togif.c,v 1.11 1997/05/19 22:50:28 hubbe Exp $ + $Id: togif.c,v 1.12 1997/05/28 19:41:33 mirar Exp $      */      /*   **! module Image   **! class image   */      #include "global.h"   
pike.git/src/modules/Image/togif.c:177:    err.g=errl->g;    err.b=errl->b;    for (x=0; x<xsize; x++)    res[x]=floyd_steinberg_add(errl+x,    (x==xsize-1)?NULL:errl+x+1,    (x==0)?NULL:errl+x-1,    &err,rgb[x],ct,closest);    }   }    -  - 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,    unsigned char *src,unsigned long len)   {    unsigned char *arena,*tmpstore,*q;    rgb_group *global_palette,*palette;    rgb_group *rgb;    int bpp;    unsigned long i,j;
pike.git/src/modules/Image/togif.c:466:   */      void image_fromgif(INT32 args)   {    if (sp[-args].type!=T_STRING)    error("Illegal argument to image->fromgif()\n");       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++;    push_object(THISOBJ);   }      static INLINE void getrgb(struct image *img,    INT32 args_start,INT32 args,char *name)   {    INT32 i;
pike.git/src/modules/Image/togif.c:521:   **! 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; +  image_gif_begin(0); +  ct=img_gif_add(args,fs,1); +  if (transparent) +  { +  struct svalue sv; +  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_sum(4); + } +    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) +  if (args>3)    { -  getrgb(THIS,!!ct,args,"image->togif() (transparency)"); +  getrgb(THIS,1,args,"image->togif() (transparency)");    transparent=&(THIS->rgb);    } -  +  if (args) pop_n_elems(args-1);    -  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); +  img_encode_gif(transparent, 0,!!args);   }         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) +  if (args>3)    { -  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)"); +  getrgb(THIS,1,args,"image->togif() (transparency)");    transparent=&(THIS->rgb);    } -  +  if (args) pop_n_elems(args-1);    -  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); +  if (!ct) ct=colortable_quant(THIS,256); +  img_encode_gif(transparent, 0);   }      /*   **! method string gif_begin()   **! method string gif_begin(int num_colors)   **! method string gif_begin(array(array(int)) colors)   **! Makes GIF header. With no argument, there is no   **! global colortable (palette).   **! returns the GIF data   **!
pike.git/src/modules/Image/togif.c:689:    else    loops=65535;    pop_n_elems(args);       sprintf(buf,"%c%c%cNETSCAPE2.0%c%c%c%c%c",    33,255,11,3,1,loops&255,(loops>>8)&255,0);       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 +  loops=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,19)); + } +  + static struct colortable *img_gif_add(INT32 args,int fs,int lm) + {    INT32 x=0,y=0,i;    struct lzw lzw;    rgb_group *rgb;    struct colortable *ct=NULL;    dynamic_buffer buf;    int colors,bpp;    int closest=0;      CHRONO("gif add init");   
pike.git/src/modules/Image/togif.c:831:    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 */       lzw_quit(&lzw);    -  colortable_free(ct); +     THREADS_DISALLOW();      CHRONO("done");       pop_n_elems(args);    push_string(low_free_buf(&buf)); -  +  +  return ct;   }      /*   **! method string gif_add()   **! 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,float delay_s)   **! method string gif_add(int x,int y,int num_colors,int delay_cs)   **! method string gif_add(int x,int y,int num_colors,float delay_s)   **! method string gif_add(int x,int y,array(array(int)) colors,int delay_cs)
pike.git/src/modules/Image/togif.c:912:   **! arg float delay_s   **! frame delay in seconds   **! arg int num_colors   **! number of colors to quantize to (default is 256)   **! arg array array(array(int)) colors   **! colors to map to, format is ({({r,g,b}),({r,g,b}),...}).   **! see also: gif_add, gif_end, gif_netscape_loop, togif */      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));   }