diff --git a/src/modules/image/image.c b/src/modules/image/image.c index 2041a5bf4e1ae1414329807979d6b306074c1cd1..ccf795823b9918141ea9feaed0610d61e970b035 100644 --- a/src/modules/image/image.c +++ b/src/modules/image/image.c @@ -1,4 +1,4 @@ -/* $Id: image.c,v 1.27 1996/11/23 07:24:03 law Exp $ */ +/* $Id: image.c,v 1.28 1996/11/30 13:14:35 law Exp $ */ #include "global.h" @@ -7,7 +7,7 @@ #include "stralloc.h" #include "global.h" -RCSID("$Id: image.c,v 1.27 1996/11/23 07:24:03 law Exp $"); +RCSID("$Id: image.c,v 1.28 1996/11/30 13:14:35 law Exp $"); #include "types.h" #include "macros.h" #include "object.h" @@ -436,6 +436,58 @@ void image_copy(INT32 args) push_object(o); } +static void image_change_color(INT32 args) + +{ + /* ->change_color([int from-r,g,b,] int to-r,g,b); */ + rgb_group from,to,*s,*d; + INT32 left; + struct object *o; + struct image *img; + + if (!THIS->img) error("no image\n"); + if (args<3) error("too few arguments to image->change_color()\n"); + + if (args<6) + { + to=THIS->rgb; + getrgb(THIS,0,args,"image->change_color()"); + from=THIS->rgb; + } + else + { + getrgb(THIS,0,args,"image->change_color()"); + from=THIS->rgb; + getrgb(THIS,3,args,"image->change_color()"); + to=THIS->rgb; + } + + o=clone(image_program,0); + img=(struct image*)(o->storage); + *img=*THIS; + + if (!(img->img=malloc(sizeof(rgb_group)*img->xsize*img->ysize +1))) + { + free_object(o); + error("out of memory\n"); + } + + left=THIS->xsize*THIS->ysize; + s=THIS->img; + d=img->img; + while (left--) + { + if (s->r==from.r && s->g==from.g && s->b==from.b) + *d=to; + else + *d=*s; + d++; s++; + } + + pop_n_elems(args); + push_object(o); +} + static INLINE int try_autocrop_vertical(INT32 x,INT32 y,INT32 y2, INT32 rgb_set,rgb_group *rgb) { @@ -1096,7 +1148,7 @@ void image_select_from(INT32 args) { struct object *o; struct image *img; - INT32 low_limit; + INT32 low_limit=0; if (!THIS->img) error("no image\n"); @@ -1490,6 +1542,10 @@ void init_image_programs() "function(:object)",0); add_function("scale",image_scale, "function(int|float,int|float|void:object)",0); + add_function("translate",image_translate, + "function(int|float,int|float:object)",0); + add_function("translate_expand",image_translate_expand, + "function(int|float,int|float:object)",0); add_function("paste",image_paste, "function(object,int|void,int|void:object)",0); @@ -1519,6 +1575,8 @@ void init_image_programs() "function("RGB_TYPE":object)",0); add_function("color",image_color, "function("RGB_TYPE":object)",0); + add_function("change_color",image_change_color, + "function(int,int,int,"RGB_TYPE":object)",0); add_function("invert",image_invert, "function("RGB_TYPE":object)",0); add_function("threshold",image_threshold, diff --git a/src/modules/image/image.h b/src/modules/image/image.h index 9c2eedbe7d07bc471b7ad17e452d46e065f731a1..486179a6be1c3005d16be53e2263f096e2a7010f 100644 --- a/src/modules/image/image.h +++ b/src/modules/image/image.h @@ -1,4 +1,4 @@ -/* $Id: image.h,v 1.10 1996/11/23 07:24:04 law Exp $ */ +/* $Id: image.h,v 1.11 1996/11/30 13:14:37 law Exp $ */ #define MAX_NUMCOL 32768 #define QUANT_MAP_BITS 4 @@ -104,6 +104,8 @@ void image_paste_alpha_color(INT32 args); /* matrix.c */ void image_scale(INT32 args); +void image_translate(INT32 args); +void image_translate_expand(INT32 args); void image_skewx(INT32 args); void image_skewy(INT32 args); void image_skewx_expand(INT32 args); diff --git a/src/modules/image/matrix.c b/src/modules/image/matrix.c index 434755a6d3cf78cff0cdbc29c7779e7afcb52dae..0275b8cb77fa8d8a352e540f62c29eb27c8ebc26 100644 --- a/src/modules/image/matrix.c +++ b/src/modules/image/matrix.c @@ -1,4 +1,4 @@ -/* $Id: matrix.c,v 1.4 1996/11/23 07:24:05 law Exp $ */ +/* $Id: matrix.c,v 1.5 1996/11/30 13:14:39 law Exp $ */ #include "global.h" @@ -25,20 +25,25 @@ struct program *image_program; #define min(a,b) ((a)<(b)?(a):(b)) #define max(a,b) ((a)<(b)?(b):(a)) -#undef MATRIX_CHRONO -#ifdef MATRIX_CHRONO +#if 0 #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; getrusage(RUSAGE_SELF,&r); - fprintf(stderr,"%s: %ld.%06ld %ld.%06ld %ld.%06ld\n",x, + fprintf(stderr,"%s: %ld.%06ld - %ld.%06ld\n",x, r.ru_utime.tv_sec,r.ru_utime.tv_usec, - r.ru_stime.tv_sec,r.ru_stime.tv_usec, - r.ru_stime.tv_sec+r.ru_utime.tv_sec, - r.ru_stime.tv_usec+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) @@ -105,30 +110,42 @@ static INLINE int getrgbl(rgbl_group *rgb,INT32 args_start,INT32 args,char *name #define decimals(x) ((x)-(int)(x)) #define testrange(x) max(min((x),255),0) #define _scale_add_rgb(dest,src,factor) \ - ((dest).r=testrange((dest).r+(int)((src).r*(factor)+0.5)), \ - (dest).g=testrange((dest).g+(int)((src).g*(factor)+0.5)), \ - (dest).b=testrange((dest).b+(int)((src).b*(factor)+0.5))) -#define scale_add_pixel(dest,dx,dy,dxw,src,sx,sy,sxw,factor) \ - _scale_add_rgb(dest[(dx)+(dy)*(dxw)],src[(sx)+(sy)*(sxw)],factor) + ((dest)->r+=(src)->r*(factor), \ + (dest)->g+=(src)->g*(factor), \ + (dest)->b+=(src)->b*(factor)) +#define scale_add_pixel(dest,dx,src,sx,factor) \ + _scale_add_rgb(dest,src,factor) -static INLINE void scale_add_line(rgb_group *new,INT32 yn,INT32 newx, +typedef struct +{ + double r,g,b; +} rgbd_group; + +static INLINE void scale_add_line(rgbd_group *new,INT32 yn,INT32 newx, rgb_group *img,INT32 y,INT32 xsize, double py,double dx) { INT32 x,xd; - double xn; - for (x=0,xn=0; x<THIS->xsize; x++,xn+=dx) + double xn,xndxd; + new=new+yn*newx; + img=img+y*xsize; + for (x=0,xn=0; x<xsize; img++,x++,xn+=dx) { if ((INT32)xn<(INT32)(xn+dx)) { - scale_add_pixel(new,(INT32)xn,yn,newx,img,x,y,xsize,py*(1.0-decimals(xn))); - if ((xd=(INT32)(xn+dx)-(INT32)(xn))>1) + xndxd=py*(1.0-decimals(xn)); + if (xndxd) + scale_add_pixel(new,(INT32)xn,img,x,xndxd); + if (dx>=1.0 && (xd=(INT32)(xn+dx)-(INT32)(xn))>1) while (--xd) - scale_add_pixel(new,(INT32)xn+xd,yn,newx,img,x,y,xsize,py); - scale_add_pixel(new,(INT32)(xn+dx),yn,newx,img,x,y,xsize,py*decimals(xn+dx)); + scale_add_pixel(new,(INT32)(xn+xd),img,x,py); + xndxd=py*decimals(xn+dx); + new++; + if (xndxd) + scale_add_pixel(new,(INT32)(xn+dx),img,x,xndxd); } else - scale_add_pixel(new,(int)xn,yn,newx,img,x,y,xsize,py*dx); + scale_add_pixel(new,(int)xn,img,x,py*dx); } } @@ -136,17 +153,21 @@ void img_scale(struct image *dest, struct image *source, INT32 newx,INT32 newy) { - rgb_group *new; + rgbd_group *new,*s; + rgb_group *d; INT32 y,yd; double yn,dx,dy; +CHRONO("scale begin"); + if (dest->img) { free(dest->img); dest->img=NULL; } if (!THIS->img || newx<=0 || newy<=0) return; /* no way */ - new=malloc(newx*newy*sizeof(rgb_group) +1); + new=malloc(newx*newy*sizeof(rgbd_group) +1); if (!new) error("Out of memory!\n"); - MEMSET(new,0,newx*newy*sizeof(rgb_group)); + for (y=0; y<newx*newy; y++) + new[y].r=new[y].g=new[y].b=0.0; dx=((double)newx-0.000001)/source->xsize; dy=((double)newy-0.000001)/source->ysize; @@ -155,23 +176,41 @@ void img_scale(struct image *dest, { if ((INT32)yn<(INT32)(yn+dy)) { - scale_add_line(new,(INT32)(yn),newx,source->img,y,source->xsize, - (1.0-decimals(yn)),dx); + if (1.0-decimals(yn)) + scale_add_line(new,(INT32)(yn),newx,source->img,y,source->xsize, + (1.0-decimals(yn)),dx); if ((yd=(INT32)(yn+dy)-(INT32)(yn))>1) while (--yd) scale_add_line(new,(INT32)yn+yd,newx,source->img,y,source->xsize, 1.0,dx); - scale_add_line(new,(INT32)(yn+dy),newx,source->img,y,source->xsize, - (decimals(yn+dy)),dx); + if (decimals(yn+dy)) + scale_add_line(new,(INT32)(yn+dy),newx,source->img,y,source->xsize, + (decimals(yn+dy)),dx); } else scale_add_line(new,(INT32)yn,newx,source->img,y,source->xsize, dy,dx); } - dest->img=new; + dest->img=d=malloc(newx*newy*sizeof(rgb_group) +1); + if (!d) error("Out of memory!\n"); + +CHRONO("transfer begin"); + + s=new; + y=newx*newy; + while (y--) + { + d->r=min((int)(s->r+0.5),255); + d->g=min((int)(s->g+0.5),255); + d->b=min((int)(s->b+0.5),255); + d++; s++; + } + dest->xsize=newx; dest->ysize=newy; + +CHRONO("scale end"); } /* Special, faster, case for scale=1/2 */ @@ -787,3 +826,125 @@ void image_rotate_expand(INT32 args) img_rotate(args,1); } +void img_translate(INT32 args,int expand) +{ + float xt,yt; + int y,x; + struct object *o; + struct image *img; + rgb_group *s,*d; + + if (args<2) error("illegal number of arguments to image->translate()\n"); + + if (sp[-args].type==T_FLOAT) xt=sp[-args].u.float_number; + else if (sp[-args].type==T_INT) xt=sp[-args].u.integer; + else error("illegal argument 1 to image->translate()\n"); + + if (sp[1-args].type==T_FLOAT) yt=sp[1-args].u.float_number; + else if (sp[1-args].type==T_INT) yt=sp[1-args].u.integer; + else error("illegal argument 2 to image->translate()\n"); + + getrgb(THIS,2,args,"image->translate()\n"); + + xt-=floor(xt); + yt-=floor(yt); + + o=clone(image_program,0); + img=(struct image*)o->storage; + + img->xsize=THIS->xsize+(xt!=0); + img->ysize=THIS->ysize+(xt!=0); + + if (!(img->img=malloc(sizeof(rgb_group)*img->xsize*img->ysize+1))) + { + free_object(o); + error("Out of memory\n"); + } + + if (!xt) + { + memcpy(img->img,THIS->img,sizeof(rgb_group)*THIS->xsize*THIS->ysize); + } + else + { + float xn=1-xt; + + d=img->img; + s=THIS->img; + + for (y=0; y<img->ysize; y++) + { + x=THIS->xsize-1; + if (!expand) + d->r=ROUND(THIS->rgb.r*xt+s->r*xn), + d->g=ROUND(THIS->rgb.g*xt+s->g*xn), + d->b=ROUND(THIS->rgb.b*xt+s->b*xn); + else + d->r=s->r, d->g=s->g, d->b=s->b; + d++; s++; + while (x--) + { + d->r=ROUND(s->r*xn+s[1].r*xt), + d->g=ROUND(s->g*xn+s[1].g*xt), + d->b=ROUND(s->b*xn+s[1].b*xt); + d++; s++; + } + if (!expand) + d->r=ROUND(s->r*xn+THIS->rgb.r*xt), + d->g=ROUND(s->g*xn+THIS->rgb.g*xt), + d->b=ROUND(s->b*xn+THIS->rgb.b*xt); + else + d->r=s->r, d->g=s->g, d->b=s->b; + d++; + } + } + + if (yt) + { + float yn=1-yt; + int xsz=img->xsize; + + d=s=img->img; + + for (x=0; x<img->xsize; x++) + { + y=THIS->ysize-1; + if (!expand) + d->r=ROUND(THIS->rgb.r*yt+s->r*yn), + d->g=ROUND(THIS->rgb.g*yt+s->g*yn), + d->b=ROUND(THIS->rgb.b*yt+s->b*yn); + else + d->r=s->r, d->g=s->g, d->b=s->b; + d+=xsz; s+=xsz; + while (y--) + { + d->r=ROUND(s->r*yn+s[xsz].r*yt), + d->g=ROUND(s->g*yn+s[xsz].g*yt), + d->b=ROUND(s->b*yn+s[xsz].b*yt); + d+=xsz; s+=xsz; + } + if (!expand) + d->r=ROUND(s->r*yn+THIS->rgb.r*yt), + d->g=ROUND(s->g*yn+THIS->rgb.g*yt), + d->b=ROUND(s->b*yn+THIS->rgb.b*yt); + else + d->r=s->r, d->g=s->g, d->b=s->b; + d-=xsz*(img->ysize-1)-1; + s-=xsz*THIS->ysize-1; + } + } + + pop_n_elems(args); + push_object(o); +} + + +void image_translate_expand(INT32 args) +{ + img_translate(args,1); +} + +void image_translate(INT32 args) +{ + img_translate(args,0); +} diff --git a/src/modules/image/togif.c b/src/modules/image/togif.c index 9256516fa39a0875f29c08f047032f8d8a9a2e82..18b32ac4afa0174fbe6cf30bd4e35485575f6eec 100644 --- a/src/modules/image/togif.c +++ b/src/modules/image/togif.c @@ -1,4 +1,4 @@ -/* $Id: togif.c,v 1.17 1996/11/23 11:53:36 law Exp $ */ +/* $Id: togif.c,v 1.18 1996/11/30 13:14:41 law Exp $ */ /* togif @@ -599,7 +599,7 @@ void image_gif_netscape_loop(INT32 args) static void img_gif_add(INT32 args,int fs,int lm) { - INT32 x,y,i; + INT32 x=0,y=0,i; struct lzw lzw; rgb_group *rgb; struct colortable *ct=NULL; @@ -629,13 +629,15 @@ CHRONO("gif add init"); if (args>2+!!ct) { - unsigned short delay; + 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 3 to image->gif_add()\n"); + error("Illegal argument %d to image->gif_add()\n",3+!!ct); + +fprintf(stderr,"delay: %d\n",delay); low_my_putchar( '!', &buf ); /* extension block */ low_my_putchar( 0xf9, &buf ); /* graphics control */ @@ -646,11 +648,14 @@ CHRONO("gif add init"); low_my_putchar( 0, &buf ); /* terminate block */ } - if (!ct) ct=colortable_quant(THIS,256); + ct=colortable_quant(THIS,256); colors=4; bpp=2; while (colors<ct->numcol) { colors<<=1; bpp++; } + + + low_my_putchar( ',', &buf ); /* image separator */ buf_word(x,&buf); /* leftofs */