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.
12
1997/05/28
19
:
41
:
33
mirar Exp $
+
$Id: togif.c,v 1.
13
1997/05/28
21
:
00
:
48
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 "image.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:334:
*/ 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,
-
(unsigned char*)
sp[-args].u.string->str,
-
sp[-args].u.string->len);
+
image_decode_gif(THIS,NULL,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:391:
**! 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>3)
+
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,
1
,args,"image->togif() (transparency)");
+
getrgb(THIS,
!!ct
,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);
-
img
_encode_gif(transparent, 0,
!!args
);
+
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>
3
)
+
if (args>
0 && sp[-args].type==T_ARRAY
)
{
-
getrgb(THIS,
1
,args,"image->togif() (transparency)");
+
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); }
-
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);
-
img
_encode_gif(transparent,
0
);
+
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 **!
pike.git/src/modules/Image/togif.c:565:
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)); }
-
/*
-
**!
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)
+
static
void
img_
gif_
add
(
INT32
args,
int
fs
,
int
lm
)
{
-
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:738:
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:820:
**! 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) {
-
colortable_free(
img_gif_add(args,0,1)
)
;
+
img_gif_add(args,0,1);
} void image_gif_add_fs(INT32 args) {
-
colortable_free(
img_gif_add(args,1,1)
)
;
+
img_gif_add(args,1,1);
} void image_gif_add_nomap(INT32 args) {
-
colortable_free(
img_gif_add(args,0,0)
)
;
+
img_gif_add(args,0,0);
} void image_gif_add_fs_nomap(INT32 args) {
-
colortable_free(
img_gif_add(args,1,0)
)
;
+
img_gif_add(args,1,0);
}