pike.git
/
src
/
modules
/
Image
/
togif.c
version
»
Context lines:
10
20
40
80
file
none
3
pike.git/src/modules/Image/togif.c:1:
/* togif 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 $
*/ /* **! module Image **! class image */ #include "global.h" #include <math.h> #include <ctype.h> #include "stralloc.h" #include "global.h" #include "threads.h"
-
#include "types.h"
+
#include "pike_macros.h" #include "object.h" #include "constants.h" #include "interpret.h" #include "svalue.h" #include "array.h" #include "error.h" #include "dynamic_buffer.h"
-
+
#include "operators.h"
#include "image.h" #include "lzw.h" #define INITIAL_BUF_LEN 8192 #define THIS ((struct image *)(fp->current_storage)) #define THISOBJ (fp->current_object) #if 0
pike.git/src/modules/Image/togif.c:178:
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:467:
*/ 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:494:
img->rgb.b=(unsigned char)sp[2-args+args_start].u.integer; if (args-args_start>=4) if (sp[3-args+args_start].type!=T_INT) error("Illegal alpha argument to %s\n",name); else img->alpha=sp[3-args+args_start].u.integer; else 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) **! method string gif_begin(array(array(int)) colors) **! Makes GIF header. With no argument, there is no **! global colortable (palette). **! returns the GIF data **! **! arg int num_colors **! number of colors to quantize to (default is 256)
pike.git/src/modules/Image/togif.c:690:
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
+
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; struct colortable *ct=NULL; dynamic_buffer buf; int colors,bpp; int closest=0; CHRONO("gif add init");
pike.git/src/modules/Image/togif.c:832:
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:913:
**! 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)
)
;
}
-
+
/*
+
**! 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);
+
}