diff --git a/src/modules/image/blit.c b/src/modules/image/blit.c index dcf1e2d292890110483fb8c0c47a0505759613a0..ea8cca41891c9956cb8cb8e07a93862126147e2a 100644 --- a/src/modules/image/blit.c +++ b/src/modules/image/blit.c @@ -1,4 +1,4 @@ -/* $Id: blit.c,v 1.6 1996/11/14 12:35:46 law Exp $ */ +/* $Id: blit.c,v 1.7 1996/11/22 20:28:14 law Exp $ */ #include "global.h" #include <math.h> @@ -28,7 +28,7 @@ struct program *image_program; #include <sys/resource.h> #define CHRONO(X) chrono(X) -void chrono(char *x) +static void chrono(char *x) { struct rusage r; static struct rusage rold; @@ -138,11 +138,13 @@ void img_crop(struct image *dest, INT32 x2,INT32 y2) { rgb_group *new; - INT32 blitwidth; - INT32 blitheight; + INT32 xp,yp,xs,ys; if (dest->img) { free(dest->img); dest->img=NULL; } + if (x1>x2) x1^=x2,x2^=x1,x1^=x2; + if (y1>y2) y1^=y2,y2^=y1,y1^=y2; + if (x1==0 && y1==0 && img->xsize-1==x2 && img->ysize-1==y2) { @@ -155,28 +157,33 @@ void img_crop(struct image *dest, return; } - if (x1>x2) x1^=x2,x2^=x1,x1^=x2; - if (y1>y2) y1^=y2,y2^=y1,y1^=y2; - new=malloc( (x2-x1+1)*(y2-y1+1)*sizeof(rgb_group) +1); if (!new) error("Out of memory.\n"); img_clear(new,THIS->rgb,(x2-x1+1)*(y2-y1+1)); - blitwidth=min(x2,img->xsize-1)-max(x1,0)+1; - blitheight=min(y2,img->ysize-1)-max(y1,0)+1; + dest->xsize=x2-x1+1; + dest->ysize=y2-y1+1; - img_blit(new+max(0,-x1)+(x2-x1+1)*max(0,-y1), - img->img+max(0,x1)+(img->xsize)*max(0,y1), - blitwidth, - blitheight, - (x2-x1+1), + xp=max(0,-x1); + yp=max(0,-y1); + xs=max(0,x1); + ys=max(0,y1); + + if (x1<0) x1=0; else if (x1>=img->xsize) x1=img->xsize-1; + if (y1<0) y1=0; else if (y1>=img->ysize) y1=img->ysize-1; + if (x2<0) x2=0; else if (x2>=img->xsize) x2=img->xsize-1; + if (y2<0) y2=0; else if (y2>=img->ysize) y2=img->ysize-1; + + img_blit(new+xp+yp*dest->xsize, + img->img+xs+(img->xsize)*ys, + x2-x1+1, + y2-y1+1, + dest->xsize, img->xsize); dest->img=new; - dest->xsize=x2-x1+1; - dest->ysize=y2-y1+1; } void img_clone(struct image *newimg,struct image *img) diff --git a/src/modules/image/font.c b/src/modules/image/font.c index 29b12e990a0df8b69cb682071f405b1a5f7128f9..fe28d216cc9dcfd71273bb0ac1f856884b485df5 100644 --- a/src/modules/image/font.c +++ b/src/modules/image/font.c @@ -1,4 +1,4 @@ -/* $Id: font.c,v 1.7 1996/11/18 23:13:21 hubbe Exp $ */ +/* $Id: font.c,v 1.8 1996/11/22 20:28:15 law Exp $ */ #include "global.h" @@ -242,8 +242,6 @@ void font_load(INT32 args) pop_n_elems(args); THISOBJ->refs++; push_object(THISOBJ); /* success */ - if (THIS->chars>32) - THIS->charinfo[32].spacing=THIS->height/4; return; } /* wrong version */ } /* wrong cookie */ diff --git a/src/modules/image/image.c b/src/modules/image/image.c index 3bd57bd30be9de4e416a627d9c9cc57d09fd9381..5d386d7ba32ebd6ffffa1675cbb36a8406c90ee4 100644 --- a/src/modules/image/image.c +++ b/src/modules/image/image.c @@ -1,4 +1,4 @@ -/* $Id: image.c,v 1.25 1996/11/14 12:34:58 law Exp $ */ +/* $Id: image.c,v 1.26 1996/11/22 20:28:16 law Exp $ */ #include "global.h" @@ -7,7 +7,7 @@ #include "stralloc.h" #include "global.h" -RCSID("$Id: image.c,v 1.25 1996/11/14 12:34:58 law Exp $"); +RCSID("$Id: image.c,v 1.26 1996/11/22 20:28:16 law Exp $"); #include "types.h" #include "macros.h" #include "object.h" @@ -40,17 +40,25 @@ static INT32 circle_sin_table[CIRCLE_STEPS]; /***************** init & exit *********************************/ -static void init_image_struct(struct object *o) +static int obj_counter=0; + +static void init_image_struct(struct object *obj) { THIS->img=NULL; THIS->rgb.r=0; THIS->rgb.g=0; THIS->rgb.b=0; +/* fprintf(stderr,"init %lx (%d)\n",obj,++obj_counter);*/ } static void exit_image_struct(struct object *obj) { if (THIS->img) { free(THIS->img); THIS->img=NULL; } +/* + fprintf(stderr,"exit %lx (%d) %dx%d=%.1fKb\n",obj,--obj_counter, + THIS->xsize,THIS->ysize, + (THIS->xsize*THIS->ysize*3+sizeof(struct image))/1024.0); + */ } /***************** internals ***********************************/ diff --git a/src/modules/image/lzw.c b/src/modules/image/lzw.c index 4aa32b16f2ed51bff9bd8eef3a0def7571f979cc..5c34c8cb37fe2f6779d6a0cf032d419a6f306741 100644 --- a/src/modules/image/lzw.c +++ b/src/modules/image/lzw.c @@ -1,4 +1,4 @@ -/* $Id: lzw.c,v 1.7 1996/11/14 12:35:00 law Exp $ */ +/* $Id: lzw.c,v 1.8 1996/11/22 20:28:17 law Exp $ */ /* @@ -215,6 +215,8 @@ void lzw_add(struct lzw *lzw,int c) lzw->current=c; } +#undef UNPACK_DEBUG + #ifdef GIF_LZW unsigned long lzw_unpack(unsigned char *dest,unsigned long destlen, unsigned char *src,unsigned long srclen, @@ -232,9 +234,10 @@ unsigned long lzw_unpack(unsigned char *dest,unsigned long destlen, unsigned long wrote=0; int i,cbits,cbit,clear=(1<<bits),end=(1<<bits)+1; - lzwcode_t current,last,used; + lzwcode_t current,last,used,nextlast; unsigned long store; unsigned char *srcend=src+srclen,*destend=dest+destlen; + unsigned char first=0; code=malloc(sizeof(struct lzwuc)*4096); if (!code) return 0; @@ -265,13 +268,17 @@ unsigned long lzw_unpack(unsigned char *dest,unsigned long destlen, { store=(store>>8)|((*(src++))<<24); cbit+=8; - if (src==srcend) return wrote; + if (src==srcend) { free(code); return wrote; } } store=(store>>8)|((*(src++))<<24); cbit+=8; current=(store>>(32-(cbit)))&mask[cbits]; cbit-=cbits; } + +#ifdef UNPACK_DEBUG + fprintf(stderr,"%03x ",current); +#endif if (current==clear) /* clear tree */ { @@ -287,14 +294,30 @@ unsigned long lzw_unpack(unsigned char *dest,unsigned long destlen, } else if (current==end) /* end of data */ break; + else if (last==LZWCNULL) + { + last=current; + if (last>end) break; + *(dest++)=(unsigned char)current; + wrote++; + first=current; + } else { lzwcode_t n; unsigned char *dest2; - if (current>=used /* wrong code, cancel */ - || code[current].len+dest>destend) /* no space, cancel */ + if (code[current].len+dest>destend) /* no space, cancel */ break; + + nextlast=current; + + if (current>=used) + { + *(dest++)=(unsigned char)first; + wrote++; + current=last; + } dest+=code[current].len; wrote+=code[current].len; @@ -320,18 +343,26 @@ unsigned long lzw_unpack(unsigned char *dest,unsigned long destlen, fprintf(stderr,"\n"); */ - if (last!=LZWCNULL) + if (used<4096) { code[used].c=code[n].c; code[used].parent=last; code[used].len=code[last].len+1; used++; - if (used>=(1<<cbits)) cbits++; + + if (used>=(1<<cbits)) + { + cbits++; +#ifdef UNPACK_DEBUG + fprintf(stderr,"[%d bits]",cbits); +#endif + } } - - last=current; + + last=nextlast; } } + free(code); return wrote; } #endif diff --git a/src/modules/image/quant.c b/src/modules/image/quant.c index bccd3730eef2c39d9620bd9cf4763338b2db2497..90a1a4baf4a6e8b14874b34b4498f62c8f1377db 100644 --- a/src/modules/image/quant.c +++ b/src/modules/image/quant.c @@ -1,4 +1,4 @@ -/* $Id: quant.c,v 1.12 1996/11/14 12:35:04 law Exp $ */ +/* $Id: quant.c,v 1.13 1996/11/22 20:28:18 law Exp $ */ /* @@ -548,6 +548,7 @@ struct colortable *colortable_from_array(struct array *arr,char *from) if (s2.type!=T_INT) tbl->tbl[i].rgb.g=0; else tbl->tbl[i].rgb.g=s2.u.integer; array_index(&s2,s.u.array,2); if (s2.type!=T_INT) tbl->tbl[i].rgb.b=0; else tbl->tbl[i].rgb.b=s2.u.integer; + tbl->tbl[i].count=1; } free_svalue(&s); free_svalue(&s2); diff --git a/src/modules/image/togif.c b/src/modules/image/togif.c index 8646a7569d0b31dd91a1309b44c455bfd88c053e..1f1c1ed49b3eabbaeccbd1ced5facba1d2088bc6 100644 --- a/src/modules/image/togif.c +++ b/src/modules/image/togif.c @@ -1,4 +1,4 @@ -/* $Id: togif.c,v 1.12 1996/11/16 05:17:12 hubbe Exp $ */ +/* $Id: togif.c,v 1.13 1996/11/22 20:28:19 law Exp $ */ /* togif @@ -32,6 +32,30 @@ Pontus Hagland, law@infovav.se #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)) @@ -363,7 +387,7 @@ int image_decode_gif(struct image *dest,struct image *dest_alpha, if (!tmpstore) break; i=lzw_unpack(tmpstore,width*height,arena,pos,bpp); if (i!=(unsigned long)(width*height)) - MEMSET(arena+i,0,width*height-i); + MEMSET(tmpstore+i,0,width*height-i); rgb=dest->img+leftofs+topofs*dest->ysize; mod=width-dest->xsize; j=height; @@ -432,35 +456,45 @@ static INLINE void getrgb(struct image *img, void image_togif(INT32 args) { rgb_group *transparent=NULL; - struct colortable *ct; + 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"); + + if (args>=3+!!ct) { - getrgb(THIS,0,args,"image->togif() (transparency)"); + getrgb(THIS,!!ct,args,"image->togif() (transparency)"); transparent=&(THIS->rgb); } pop_n_elems(args); if (!THIS->img) { error("no image\n"); return; } - ct=colortable_quant(THIS,256); + + if (!ct) ct=colortable_quant(THIS,256); push_string( image_encode_gif( THIS,ct, transparent, 0) ); colortable_free(ct); } + void image_togif_fs(INT32 args) { rgb_group *transparent=NULL; - struct colortable *ct; + 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"); + + if (args>=3+!!ct) { - getrgb(THIS,0,args,"image->togif_fs() (transparency)"); + getrgb(THIS,!!ct,args,"image->togif() (transparency)"); transparent=&(THIS->rgb); } pop_n_elems(args); if (!THIS->img) { error("no image\n"); return; } - ct=colortable_quant(THIS,256); + + if (!ct) + ct=colortable_quant(THIS,256); push_string( image_encode_gif( THIS,ct, transparent, 1) ); colortable_free(ct); } @@ -517,9 +551,11 @@ static void img_gif_add(INT32 args,int fs) INT32 x,y,i; struct lzw lzw; rgb_group *rgb; - struct colortable *ct; + struct colortable *ct=NULL; dynamic_buffer buf; +CHRONO("gif add init"); + buf.s.str=NULL; initialize_buf(&buf); @@ -533,13 +569,16 @@ static void img_gif_add(INT32 args,int fs) y=sp[1-args].u.integer; } - if (args>2) + if (args>2 && sp[2-args].type==T_ARRAY) + ct=colortable_from_array(sp[2-args].u.array,"image->gif_add()\n"); + + if (args>2+!!ct) { unsigned short delay; - if (sp[2-args].type==T_INT) - delay=sp[2-args].u.integer; - else if (sp[2-args].type==T_FLOAT) - delay=(unsigned short)(sp[2-args].u.float_number*100); + 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 3 to image->gif_add()\n"); @@ -552,7 +591,7 @@ static void img_gif_add(INT32 args,int fs) low_my_putchar( 0, &buf ); /* terminate block */ } - ct=colortable_quant(THIS,256); + if (!ct) ct=colortable_quant(THIS,256); low_my_putchar( ',', &buf ); /* image separator */ @@ -566,18 +605,26 @@ static void img_gif_add(INT32 args,int fs) /* local colormap ( == 0x80) */ /* 8 bpp in map ( == 0x07) */ - for (i=0; i<256; i++) + 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<256; i++) + { + low_my_putchar(0,&buf); + low_my_putchar(0,&buf); + low_my_putchar(0,&buf); + } low_my_putchar( 8, &buf ); /* bits per pixel , or min 2 */ i=THIS->xsize*THIS->ysize; rgb=THIS->img; +CHRONO("begin pack"); + lzw_init(&lzw,8); if (!fs) while (i--) lzw_add(&lzw,colortable_rgb(ct,*(rgb++))); @@ -609,6 +656,8 @@ static void img_gif_add(INT32 args,int fs) lzw_write_last(&lzw); +CHRONO("end pack"); + for (i=0; i<(int)lzw.outpos; i+=254) { int wr; @@ -621,6 +670,10 @@ static void img_gif_add(INT32 args,int fs) lzw_quit(&lzw); + colortable_free(ct); + +CHRONO("done"); + pop_n_elems(args); push_string(low_free_buf(&buf)); }