ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | |
e4ebc4 | 1997-05-28 | Mirar (Pontus Hagland) | | $Id: togif.c,v 1.13 1997/05/28 21:00:48 mirar Exp $
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | |
*/
|
e3cb4b | 1997-04-03 | Mirar (Pontus Hagland) | |
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | #include "global.h"
#include <math.h>
#include <ctype.h>
#include "stralloc.h"
#include "global.h"
#include "threads.h"
|
e4ebc4 | 1997-05-28 | Mirar (Pontus Hagland) | | #include "types.h"
|
bb55f8 | 1997-03-16 | Fredrik Hübinette (Hubbe) | | #include "pike_macros.h"
|
ab6aec | 1997-02-11 | Fredrik 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"
#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
#include <sys/resource.h>
#define CHRONO(X) chrono(X)
static void chrono(char *x)
{
struct rusage r;
static struct rusage rold;
getrusage(RUSAGE_SELF,&r);
fprintf(stderr,"%s: %ld.%06ld - %ld.%06ld\n",x,
r.ru_utime.tv_sec,r.ru_utime.tv_usec,
((r.ru_utime.tv_usec-rold.ru_utime.tv_usec<0)?-1:0)
+r.ru_utime.tv_sec-rold.ru_utime.tv_sec,
((r.ru_utime.tv_usec-rold.ru_utime.tv_usec<0)?1000000:0)
+ r.ru_utime.tv_usec-rold.ru_utime.tv_usec
);
rold=r;
}
#else
#define CHRONO(X)
#endif
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)<(b)?(b):(a))
#define testrange(x) max(min((x),255),0)
static void buf_word( unsigned short w, dynamic_buffer *buf )
{
low_my_putchar( w&0xff, buf );
low_my_putchar( (w>>8)&0xff, buf );
}
|
c56c66 | 1997-03-18 | Mirar (Pontus Hagland) | | #define WEIGHT_NEXT(X) (((X)*8)/20)
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | #define WEIGHT_DOWNNEXT(X) (((X)*3)/20)
|
c56c66 | 1997-03-18 | Mirar (Pontus Hagland) | | #define WEIGHT_DOWN(X) (((X)*3)/20)
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | #define WEIGHT_DOWNBACK(X) (((X)*0)/20)
static int floyd_steinberg_add(rgbl_group *errl,
rgbl_group *errlfwd,
rgbl_group *errlback,
rgbl_group *err,
rgb_group rgb,
|
c56c66 | 1997-03-18 | Mirar (Pontus Hagland) | | struct colortable *ct,
int closest)
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | {
rgb_group rgb2,rgb3;
rgbl_group cerr;
int c;
rgb2.r=testrange((long)rgb.r+err->r/FS_SCALE);
rgb2.g=testrange((long)rgb.g+err->g/FS_SCALE);
rgb2.b=testrange((long)rgb.b+err->b/FS_SCALE);
#ifdef FS_DEBUG
fprintf(stderr,"%g,%g,%g+%g,%g,%g=%g,%g,%g ",
1.0*rgb.r, 1.0*rgb.g, 1.0*rgb.b,
err->r*1.0/FS_SCALE, err->g*1.0/FS_SCALE, err->b*1.0/FS_SCALE,
rgb2.r*1.0, rgb2.g*1.0, rgb2.b*1.0);
#endif
|
c56c66 | 1997-03-18 | Mirar (Pontus Hagland) | | if (closest)
|
0a71e0 | 1997-03-18 | Mirar (Pontus Hagland) | | c=colortable_rgb_nearest(ct,rgb2);
|
c56c66 | 1997-03-18 | Mirar (Pontus Hagland) | | else
c=colortable_rgb(ct,rgb2);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | rgb3=ct->clut[c];
cerr.r=(long)rgb.r*FS_SCALE-(long)rgb3.r*FS_SCALE+err->r;
cerr.g=(long)rgb.g*FS_SCALE-(long)rgb3.g*FS_SCALE+err->g;
cerr.b=(long)rgb.b*FS_SCALE-(long)rgb3.b*FS_SCALE+err->b;
#ifdef FS_DEBUG
fprintf(stderr,"got %g,%g,%g err %g,%g,%g ",
1.0*rgb3.r,
1.0*rgb3.g,
1.0*rgb3.b,
1.0*cerr.r,
1.0*cerr.g,
1.0*cerr.b);
#endif
errl->r+=WEIGHT_DOWN(cerr.r);
errl->g+=WEIGHT_DOWN(cerr.g);
errl->b+=WEIGHT_DOWN(cerr.b);
if (errlback)
{
errlback->r+=WEIGHT_DOWNBACK(cerr.r);
errlback->g+=WEIGHT_DOWNBACK(cerr.g);
errlback->b+=WEIGHT_DOWNBACK(cerr.b);
#ifdef FS_DEBUG
fprintf(stderr,"errlback=>%g ",errlback->g*1.0/FS_SCALE);
#endif
}
if (errlfwd)
{
err->r=WEIGHT_NEXT(cerr.r);
err->g=WEIGHT_NEXT(cerr.g);
err->b=WEIGHT_NEXT(cerr.b);
err->r+=errlfwd->r;
err->g+=errlfwd->g;
err->b+=errlfwd->b;
errlfwd->r=WEIGHT_DOWNNEXT(cerr.r);
errlfwd->g=WEIGHT_DOWNNEXT(cerr.g);
errlfwd->b=WEIGHT_DOWNNEXT(cerr.b);
#ifdef FS_DEBUG
fprintf(stderr,"errlfwd=>%g ",errlfwd->g*1.0/FS_SCALE);
#endif
}
#ifdef FS_DEBUG
fprintf(stderr,"errl=>%g ",errl->g*1.0/FS_SCALE);
fprintf(stderr,"err=>%g\n",err->g*1.0/FS_SCALE);
#endif
return c;
}
void image_floyd_steinberg(rgb_group *rgb,int xsize,
rgbl_group *errl,
int way,int *res,
|
c56c66 | 1997-03-18 | Mirar (Pontus Hagland) | | struct colortable *ct,
int closest)
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | {
rgbl_group err;
int x;
if (way)
{
err.r=errl[xsize-1].r;
err.g=errl[xsize-1].g;
err.b=errl[xsize-1].b;
for (x=xsize-1; x>=0; x--)
res[x]=floyd_steinberg_add(errl+x,
(x==0)?NULL:errl+x-1,
(x==xsize-1)?NULL:errl+x+1,
|
c56c66 | 1997-03-18 | Mirar (Pontus Hagland) | | &err,rgb[x],ct,closest);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | }
else
{
err.r=errl->r;
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,
|
c56c66 | 1997-03-18 | Mirar (Pontus Hagland) | | &err,rgb[x],ct,closest);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | }
}
|
e4ebc4 | 1997-05-28 | Mirar (Pontus Hagland) | |
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);
low_my_putchar( 0, &buf );
low_my_putchar( 0, &buf );
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 );
low_my_putchar( 0xf9, &buf );
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 );
buf_word(0,&buf);
buf_word(0,&buf);
buf_word(img->xsize,&buf);
buf_word(img->ysize,&buf);
low_my_putchar(0x00, &buf);
low_my_putchar( bpp, &buf );
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 );
low_my_binary_strcat( (char *) lzw.out+i, wr, &buf );
}
low_my_putchar( 0, &buf );
CHRONO("image_encode_gif wrote ok");
lzw_quit(&lzw);
low_my_putchar( ';', &buf );
CHRONO("image_encode_gif done");
THREADS_DISALLOW();
return low_free_buf(&buf);
}
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | #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;
INT32 mod;
INT32 leftofs,topofs,width,height;
int interlaced,transparent;
unsigned long arenalen,pos;
if (src[0]!='G'
||src[1]!='I'
||src[2]!='F'
||len<12)
return 0;
dest->xsize=src[6]+(src[7]<<8);
dest->ysize=src[8]+(src[9]<<8);
if (! (arena=malloc(arenalen=STD_ARENA_SIZE)) ) return 0;
dest->img=malloc(dest->xsize*dest->ysize*sizeof(rgb_group));
if (!dest->img) { free(arena); return 0; }
bpp=(src[10]&7)+1;
THREADS_ALLOW();
if (src[10]&128)
{
global_palette=(rgb_group*)(src+13);
src+=3*(1<<bpp);
len-=3*(1<<bpp);
rgb=dest->img;
i=dest->xsize*dest->ysize;
}
else
global_palette=NULL;
MEMSET(dest->img,0,sizeof(rgb_group)*dest->xsize*dest->ysize);
src+=13; len-=13;
do
{
switch (*src)
{
case '!':
if (len<7) break;
if (src[1]==0xf9)
transparent=src[6];
len-=src[3]+1;
src+=src[3]+1;
continue;
case ',':
if (len<10) len-=10;
leftofs=src[1]+(src[2]<<8);
topofs=src[3]+(src[4]<<8);
width=src[5]+(src[6]<<8);
height=src[7]+(src[8]<<8);
interlaced=src[9]&64;
if (src[9]&128)
{
palette=(rgb_group*)(src+10);
src+=((src[9]&7)+1)*3;
}
else
palette=global_palette;
src+=11;
len-=11;
pos=0;
if (len<3) break;
bpp=src[-1];
while (len>1)
{
if (!(i=*src)) break;
if (pos+i>arenalen)
{
arena=realloc(arena,arenalen*=2);
if (!arena) return 1;
}
MEMCPY(arena+pos,src+1,min(i,len-1));
pos+=min(i,len-1);
len-=i+1;
src+=i+1;
}
if (leftofs+width<=dest->xsize && topofs+height<=dest->ysize)
{
tmpstore=malloc(width*height);
if (!tmpstore) break;
i=lzw_unpack(tmpstore,width*height,arena,pos,bpp);
if (i!=(unsigned long)(width*height))
MEMSET(tmpstore+i,0,width*height-i);
rgb=dest->img+leftofs+topofs*dest->ysize;
mod=width-dest->xsize;
j=height;
q=tmpstore;
if (palette)
while (j--)
{
i=width;
while (i--) *(rgb++)=palette[*(q++)];
rgb+=mod;
}
free(tmpstore);
}
continue;
case ';':
break;
default:
break;
}
}
while (0);
THREADS_DISALLOW();
if (arena) free(arena);
return 1;
}
|
e3cb4b | 1997-04-03 | Mirar (Pontus Hagland) | | |
15b566 | 1997-05-05 | Mirar (Pontus Hagland) | | **! bugs
**! yes, it does -- it may even do segment overrides...
|
e3cb4b | 1997-04-03 | Mirar (Pontus Hagland) | | */
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | 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;
|
e4ebc4 | 1997-05-28 | Mirar (Pontus Hagland) | | image_decode_gif(THIS,NULL,sp[-args].u.string->str,sp[-args].u.string->len);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | |
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;
if (args-args_start<3) return;
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;
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;
}
|
e3cb4b | 1997-04-03 | Mirar (Pontus Hagland) | |
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | void image_togif(INT32 args)
{
rgb_group *transparent=NULL;
|
e4ebc4 | 1997-05-28 | Mirar (Pontus Hagland) | | 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)));
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | |
|
e4ebc4 | 1997-05-28 | Mirar (Pontus Hagland) | | if (args>=3+!!ct)
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | {
|
e4ebc4 | 1997-05-28 | Mirar (Pontus Hagland) | | getrgb(THIS,!!ct,args,"image->togif() (transparency)");
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | transparent=&(THIS->rgb);
}
|
e4ebc4 | 1997-05-28 | Mirar (Pontus Hagland) | | pop_n_elems(args);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | if (!THIS->img) { error("no image\n"); return; }
if (!ct) ct=colortable_quant(THIS,256);
|
e4ebc4 | 1997-05-28 | Mirar (Pontus Hagland) | | push_string( image_encode_gif( THIS,ct, transparent, 0, 0) );
colortable_free(ct);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | }
void image_togif_fs(INT32 args)
{
rgb_group *transparent=NULL;
|
e4ebc4 | 1997-05-28 | Mirar (Pontus Hagland) | | 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)));
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | |
|
e4ebc4 | 1997-05-28 | Mirar (Pontus Hagland) | | if (args>=3+!!ct)
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | {
|
e4ebc4 | 1997-05-28 | Mirar (Pontus Hagland) | | getrgb(THIS,!!ct,args,"image->togif() (transparency)");
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | transparent=&(THIS->rgb);
}
|
e4ebc4 | 1997-05-28 | Mirar (Pontus Hagland) | | pop_n_elems(args);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | if (!THIS->img) { error("no image\n"); return; }
|
e4ebc4 | 1997-05-28 | Mirar (Pontus Hagland) | | if (!ct)
ct=colortable_quant(THIS,256);
push_string( image_encode_gif( THIS,ct, transparent, 1, closest) );
colortable_free(ct);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | }
|
e3cb4b | 1997-04-03 | Mirar (Pontus Hagland) | |
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | void image_gif_begin(INT32 args)
{
dynamic_buffer buf;
long i;
int colors,bpp;
struct colortable *ct=NULL;
if (args)
if (sp[-args].type==T_INT && sp[-args].u.integer!=0)
ct=colortable_quant(THIS,max(256,min(2,sp[-args].u.integer)));
else if (sp[-args].type==T_ARRAY)
ct=colortable_from_array(sp[-args].u.array,"image->gif_begin()\n");
pop_n_elems(args);
buf.s.str=NULL;
initialize_buf(&buf);
if (ct)
{
colors=4; bpp=2;
while (colors<ct->numcol) { colors<<=1; bpp++; }
}
else
{
colors=256; bpp=8;
}
low_my_binary_strcat("GIF89a",6,&buf);
buf_word((unsigned short)THIS->xsize,&buf);
buf_word((unsigned short)THIS->ysize,&buf);
low_my_putchar( (char)((0x80*!!ct) | 0x70 | (bpp-1) ), &buf);
low_my_putchar( 0, &buf );
low_my_putchar( 0, &buf );
if (!!ct)
{
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);
}
}
push_string(low_free_buf(&buf));
}
void image_gif_end(INT32 args)
{
pop_n_elems(args);
push_string(make_shared_binary_string(";",1));
}
|
e3cb4b | 1997-04-03 | Mirar (Pontus Hagland) | |
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | void image_gif_netscape_loop(INT32 args)
{
unsigned short loops=0;
char buf[30];
if (args)
if (sp[-args].type!=T_INT)
error("Illegal argument to image->gif_netscape_loop()\n");
else
loops=sp[-args].u.integer;
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));
}
|
e4ebc4 | 1997-05-28 | Mirar (Pontus Hagland) | | static void img_gif_add(INT32 args,int fs,int lm)
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | {
INT32 x=0,y=0,i;
struct lzw lzw;
rgb_group *rgb;
struct colortable *ct=NULL;
dynamic_buffer buf;
int colors,bpp;
|
4a1607 | 1997-03-18 | Mirar (Pontus Hagland) | | int closest=0;
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | |
CHRONO("gif add init");
buf.s.str=NULL;
initialize_buf(&buf);
if (args==0) x=y=0;
|
e3cb4b | 1997-04-03 | Mirar (Pontus Hagland) | | else if (args<2
|| sp[-args].type!=T_INT
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | || 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)
|
c56c66 | 1997-03-18 | Mirar (Pontus Hagland) | | {
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | ct=colortable_from_array(sp[2-args].u.array,"image->gif_add()\n");
|
c56c66 | 1997-03-18 | Mirar (Pontus Hagland) | | closest=1;
}
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | else if (args>3 && sp[2-args].type==T_INT)
ct=colortable_quant(THIS,max(256,min(2,sp[2-args].u.integer)));
if (args>2+!!ct)
{
unsigned short delay=0;
if (sp[2+!!ct-args].type==T_INT)
delay=sp[2+!!ct-args].u.integer;
else if (sp[2+!!ct-args].type==T_FLOAT)
delay=(unsigned short)(sp[2+!!ct-args].u.float_number*100);
else
error("Illegal argument %d to image->gif_add()\n",3+!!ct);
low_my_putchar( '!', &buf );
low_my_putchar( 0xf9, &buf );
low_my_putchar( 4, &buf );
low_my_putchar( 0, &buf );
buf_word( delay, &buf );
low_my_putchar( 0, &buf );
low_my_putchar( 0, &buf );
}
|
a369b8 | 1997-05-08 | Per Hedbor | | if(!ct)
ct=colortable_quant(THIS,256);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | |
colors=4; bpp=2;
while (colors<ct->numcol) { colors<<=1; bpp++; }
low_my_putchar( ',', &buf );
buf_word(x,&buf);
buf_word(y,&buf);
buf_word(THIS->xsize,&buf);
buf_word(THIS->ysize,&buf);
low_my_putchar((0x80*lm)|(bpp-1), &buf);
if (lm)
{
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);
}
}
low_my_putchar( bpp, &buf );
i=THIS->xsize*THIS->ysize;
rgb=THIS->img;
CHRONO("begin pack");
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)*THIS->xsize);
cres=(int*)xalloc(sizeof(int)*THIS->xsize);
for (i=0; i<THIS->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=THIS->ysize;
while (i--)
{
|
c56c66 | 1997-03-18 | Mirar (Pontus Hagland) | | image_floyd_steinberg(rgb,THIS->xsize,errb,w=!w,cres,ct,closest);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | for (j=0; j<THIS->xsize; j++)
lzw_add(&lzw,cres[j]);
rgb+=THIS->xsize;
}
free(errb);
free(cres);
}
lzw_write_last(&lzw);
CHRONO("end pack");
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 );
low_my_binary_strcat( (char *) lzw.out+i, wr, &buf );
}
low_my_putchar( 0, &buf );
lzw_quit(&lzw);
|
e4ebc4 | 1997-05-28 | Mirar (Pontus Hagland) | | colortable_free(ct);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | THREADS_DISALLOW();
CHRONO("done");
pop_n_elems(args);
push_string(low_free_buf(&buf));
}
|
e3cb4b | 1997-04-03 | Mirar (Pontus Hagland) | | |
068c06 | 1997-04-30 | Mirar (Pontus Hagland) | | **! at the given position.
**!
**! The "fs" versions uses floyd-steinberg dithering, and the "nomap"
**! versions have no local colormap.
**!
**! Example:
**! <pre>
**! object img1 = Image(200,200);
**! object img2 = Image(200,200);
**! // load img1 and img2 with stuff
**! write(img1->gif_begin()+
**! img1->gif_netscape_loop()+
**! img1->gif_add(0,0,100)+
**! img2->gif_add(0,0,100)+
**! img1->gif_end());
**! // voila, a gif animation...
|
6262d0 | 1997-05-05 | Fredrik Hübinette (Hubbe) | | **! </pre>
|
068c06 | 1997-04-30 | Mirar (Pontus Hagland) | | **!
**! note
**! I (Mirar) recommend reading about the GIF file format before
**! experementing with these.
**! returns the GIF data chunk as a string
|
e3cb4b | 1997-04-03 | Mirar (Pontus Hagland) | | **!
**! arg int x
**! arg int y
**! the location of this subimage
**! arg int delay_cs
**! frame delay in centiseconds
**! 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}),...}).
|
068c06 | 1997-04-30 | Mirar (Pontus Hagland) | | **! see also: gif_add, gif_end, gif_netscape_loop, togif */
|
e3cb4b | 1997-04-03 | Mirar (Pontus Hagland) | |
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | void image_gif_add(INT32 args)
{
|
e4ebc4 | 1997-05-28 | Mirar (Pontus Hagland) | | img_gif_add(args,0,1);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | }
void image_gif_add_fs(INT32 args)
{
|
e4ebc4 | 1997-05-28 | Mirar (Pontus Hagland) | | img_gif_add(args,1,1);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | }
void image_gif_add_nomap(INT32 args)
{
|
e4ebc4 | 1997-05-28 | Mirar (Pontus Hagland) | | img_gif_add(args,0,0);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | }
void image_gif_add_fs_nomap(INT32 args)
{
|
e4ebc4 | 1997-05-28 | Mirar (Pontus Hagland) | | img_gif_add(args,1,0);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | }
|