diff --git a/.gitattributes b/.gitattributes index 8fb40028b833743fc07f8c8b2455b80675183f0b..1d8f8decfe869f7aea760f7634215670cf7ef64b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -37,6 +37,7 @@ testfont binary /src/modules/Gmp/mpz_glue.c foreign_ident /src/modules/Gz/zlibmod.c foreign_ident /src/modules/Image/blit.c foreign_ident +/src/modules/Image/blit_layer_include.h foreign_ident /src/modules/Image/dct.c foreign_ident /src/modules/Image/font.c foreign_ident /src/modules/Image/image.c foreign_ident diff --git a/src/modules/Image/blit.c b/src/modules/Image/blit.c index fae36efccf618b476e598a791199f32bd3971bee..83ab0b6a56eba1bcebc243b12fa416479ba3eb09 100644 --- a/src/modules/Image/blit.c +++ b/src/modules/Image/blit.c @@ -1,4 +1,4 @@ -/* $Id: blit.c,v 1.2 1997/03/17 03:07:59 hubbe Exp $ */ +/* $Id: blit.c,v 1.3 1997/03/20 07:56:02 mirar Exp $ */ #include "global.h" #include <math.h> @@ -22,6 +22,7 @@ extern struct program *image_program; #define THIS ((struct image *)(fp->current_storage)) #define THISOBJ (fp->current_object) +#define absdiff(a,b) ((a)<(b)?((b)-(a)):((a)-(b))) #define min(a,b) ((a)<(b)?(a):(b)) #define max(a,b) ((a)<(b)?(b):(a)) @@ -463,3 +464,230 @@ void img_box(INT32 x1,INT32 y1,INT32 x2,INT32 y2) +void image_add_layers(INT32 args) +/* + +[x1,y1,x2,y2], +({object image,object mask|0|1,[int alpha_value,[int method]]}), +({object image,object mask|0|1,[int alpha_value,[int method]]}), +... +:object + + */ +{ + struct img_layer + { + rgb_group *s; + rgb_group *m; + int alpha; + enum layer_method method; + } *layer; + float q2=1/(255.0*255.0); + float q=1/(255.0); + rgb_group *s; + rgb_group *d; + struct object *o; + + int allalpha255=1,allmask=1,allnop=1; + + int i,j,l,mod,layers; + int x1,y1,x2,y2; + + if (!THIS->img) error("No image."); + s=THIS->img; + + if (args>=4 + && sp[-args].type==T_INT + && sp[1-args].type==T_INT + && sp[2-args].type==T_INT + && sp[3-args].type==T_INT) + { + x1=sp[-args].u.integer; + y1=sp[1-args].u.integer; + x2=sp[2-args].u.integer; + y2=sp[3-args].u.integer; + + if (x2>x1) x2^=x1,x1^=x2,x2^=x1; + if (y2>y1) y2^=y1,y1^=y2,y2^=y1; + + if (x2>THIS->xsize-1 || + y2>THIS->ysize-1 || + x1<0 || y1<0) + error("Illegal coordinates to image->add_layers()\n"); + layers=args-4; + } + else + { + x1=0; + y1=0; + x2=THIS->xsize-1; + y2=THIS->ysize-1; + layers=args; + } + + layer=(struct img_layer*)xalloc(sizeof(struct img_layer)*layers); + + for (j=0,i=layers; i>0; i--,j++) + { + struct array *a; + struct image *img; + if (sp[-i].type!=T_ARRAY) + { + free(layer); + error("Illegal argument(s) to image->add_layers()\n"); + } + a=sp[-i].u.array; + if (a->size<2) + { + free(layer); + error("Illegal size of array argument to image->add_layers()\n"); + } + + if (a->item[0].type!=T_OBJECT + || !a->item[0].u.object + || a->item[0].u.object->prog!=image_program) + { + free(layer); + error("Illegal array contents (wrong or no image) to image->add_layers()\n"); + } + img=(struct image*)a->item[0].u.object->storage; + if (!img->img + || img->xsize != THIS->xsize + || img->ysize != THIS->ysize) + { + free(layer); + error("Illegal array contents (no image or wrong image size) to image->add_layers()\n"); + } + layer[j].s=img->img; + + if (a->item[1].type==T_INT + && a->item[1].u.integer==0) + { + layer[j].m=NULL; + } + else + { + if (a->item[1].type!=T_OBJECT + || !a->item[1].u.object + || a->item[1].u.object->prog!=image_program) + { + free(layer); + error("Illegal array contents (wrong or no image for mask) to image->add_layers()\n"); + } + img=(struct image*)a->item[1].u.object->storage; + if (!img->img + || img->xsize != THIS->xsize + || img->ysize != THIS->ysize) + { + free(layer); + error("Illegal array contents (no mask or wrong mask size) to image->add_layers()\n"); + } + layer[j].m=img->img; + } + + if (a->size>=3) + { + if (a->item[2].type!=T_INT) + { + free(layer); + error("Illegal array contents (illegal alpha) to image->add_layers()\n"); + } + layer[j].alpha=a->item[2].u.integer; + } + else + layer[j].alpha=255; + + if (a->size>=4) + { + if (a->item[3].type!=T_INT) + { + free(layer); + error("Illegal array contents (illegal method) to image->add_layers()\n"); + } + layer[j].method=a->item[3].u.integer; + } + else + layer[j].method=LAYER_NOP; + } + + pop_n_elems(args); + + push_int(1+x2-x1); + push_int(1+y2-y1); + o=clone_object(image_program,2); + d=((struct image*)(o->storage))->img; + + + mod=THIS->xsize-(x2-x1+1); + s+=x1+THIS->xsize*y1; + for (i=0; i<layers; i++) + { + layer[i].s+=x1+THIS->xsize*y1; + if (layer[i].m) layer[i].m+=x1+THIS->xsize*y1; + else allmask=0; + if (layer[i].alpha!=255) allalpha255=0; + if (layer[i].method!=LAYER_NOP) allnop=0; + } + + if (allmask && allalpha255 && allnop) + { +#define ALL_IS_NOP +#define ALL_HAVE_MASK +#define ALL_HAVE_ALPHA +#include "blit_layer_include.h" +#undef ALL_IS_NOP +#undef ALL_HAVE_MASK +#undef ALL_HAVE_ALPHA + } + else if (allalpha255 && allnop) + { +#define ALL_IS_NOP +#define ALL_HAVE_ALPHA +#include "blit_layer_include.h" +#undef ALL_IS_NOP +#undef ALL_HAVE_ALPHA + } + else if (allmask && allnop) + { +#define ALL_HAVE_MASK +#define ALL_HAVE_ALPHA +#include "blit_layer_include.h" +#undef ALL_HAVE_MASK +#undef ALL_HAVE_ALPHA + } + else if (allnop) + { +#define ALL_IS_NOP +#include "blit_layer_include.h" +#undef ALL_IS_NOP + } + else if (allmask && allalpha255) + { +#define ALL_HAVE_MASK +#define ALL_HAVE_ALPHA +#include "blit_layer_include.h" +#undef ALL_HAVE_MASK +#undef ALL_HAVE_ALPHA + } + else if (allalpha255) + { +#define ALL_HAVE_ALPHA +#include "blit_layer_include.h" +#undef ALL_HAVE_ALPHA + } + else if (allmask) + { +#define ALL_HAVE_MASK +#include "blit_layer_include.h" +#undef ALL_HAVE_MASK + } + else + { +#include "blit_layer_include.h" + } + + + free(layer); + + push_object(o); +} diff --git a/src/modules/Image/blit_layer_include.h b/src/modules/Image/blit_layer_include.h new file mode 100644 index 0000000000000000000000000000000000000000..4152011af96e6bcc3cb86a91c4148b3a85eee813 --- /dev/null +++ b/src/modules/Image/blit_layer_include.h @@ -0,0 +1,207 @@ +/* $Id: blit_layer_include.h,v 1.1 1997/03/20 07:56:05 mirar Exp $ */ +/* included w/ defines in blit.c, image_add_layer() */ + + + i=(y2-y1+1); + while (i--) + { + j=(x2-x1+1); + + while (j--) + { + rgb_group rgb; + struct img_layer *lr=layer; + rgb=*s; + for (l=0; l<layers; l++,lr++) + if (lr->alpha!=0) + { +#ifndef ALL_IS_NOP + if (lr->method==LAYER_NOP) + { +#endif +#ifndef ALL_HAVE_MASK + if (lr->m) /* mask */ + { +#endif +#ifndef ALL_HAVE_ALPHA_255 + if (lr->alpha==255) /* only mask */ + { +#endif + if (lr->m->r==255) + rgb.r=lr->s->r; + else if (lr->m->r!=0) + rgb.r=(unsigned char) + ((rgb.r*(255-lr->m->r) + +lr->s->r*lr->m->r)*q); + if (lr->m->g==255) + rgb.g=lr->s->g; + else if (lr->m->g!=0) + rgb.g=(unsigned char) + ((rgb.g*(255-lr->m->g) + +lr->s->g*lr->m->g)*q); + if (lr->m->b==255) + rgb.b=lr->s->b; + else if (lr->m->b!=0) + rgb.b=(unsigned char) + ((rgb.b*(255-lr->m->b) + +lr->s->b*lr->m->b)*q); +#ifndef ALL_HAVE_ALPHA_255 + } + else /* alpha and mask */ + { + rgb.r=(unsigned char) + ((rgb.r*(255*255-lr->m->r*lr->alpha) + +lr->s->r*lr->m->r*lr->alpha)*q2); + rgb.g=(unsigned char) + ((rgb.g*(255*255-lr->m->g*lr->alpha) + +lr->s->g*lr->m->g*lr->alpha)*q2); + rgb.b=(unsigned char) + ((rgb.b*(255*255-lr->m->b*lr->alpha) + +lr->s->b*lr->m->b*lr->alpha)*q2); + } +#endif + lr->m++; +#ifndef ALL_HAVE_MASK + } + else /* no mask */ + { +#ifndef ALL_HAVE_ALPHA_255 + if (lr->alpha==255) /* no alpha (bam!) */ +#endif + rgb=lr->s[0]; +#ifndef ALL_HAVE_ALPHA_255 + else /* only alpha */ + { + rgb.r=(unsigned char) + ((rgb.r*(255-lr->alpha) + +lr->s->r*lr->alpha)*q); + rgb.g=(unsigned char) + ((rgb.g*(255-lr->alpha) + +lr->s->g*lr->alpha)*q); + rgb.b=(unsigned char) + ((rgb.b*(255-lr->alpha) + +lr->s->b*lr->alpha)*q); + } +#endif + } +#endif +#ifndef ALL_IS_NOP + } + else + { + rgb_group res; + + if (!lr->m || lr->m->r || lr->m->g || lr->m->b) + switch (lr->method) + { + case LAYER_MAX: + res.r=max(lr->s->r,rgb.r); + res.g=max(lr->s->g,rgb.g); + res.b=max(lr->s->b,rgb.b); + break; + case LAYER_MIN: + res.r=min(lr->s->r,rgb.r); + res.g=min(lr->s->g,rgb.g); + res.b=min(lr->s->b,rgb.b); + break; + case LAYER_ADD: + res.r=(unsigned char)max(255,(lr->s->r+rgb.r)); + res.g=(unsigned char)max(255,(lr->s->g+rgb.g)); + res.b=(unsigned char)max(255,(lr->s->b+rgb.b)); + break; + case LAYER_MULT: + res.r=(unsigned char)((lr->s->r*rgb.r)*q); + res.g=(unsigned char)((lr->s->g*rgb.g)*q); + res.b=(unsigned char)((lr->s->b*rgb.b)*q); + break; + case LAYER_DIFF: + res.r=absdiff(lr->s->r,rgb.r); + res.g=absdiff(lr->s->g,rgb.g); + res.b=absdiff(lr->s->b,rgb.b); + break; + default: + res=rgb; + } + else res=rgb; + +#ifndef ALL_HAVE_MASK + if (lr->m) /* mask */ + { +#endif +#ifndef ALL_HAVE_ALPHA_255 + if (lr->alpha==255) /* only mask */ + { +#endif + if (lr->m->r==255) + rgb.r=res.r; + else if (lr->m->r!=0) + rgb.r=(unsigned char) + ((rgb.r*(255-lr->m->r) + +res.r*lr->m->r)*q); + if (lr->m->g==255) + rgb.g=res.g; + else if (lr->m->g!=0) + rgb.g=(unsigned char) + ((rgb.g*(255-lr->m->g) + +res.g*lr->m->g)*q); + if (lr->m->b==255) + rgb.b=res.b; + else if (lr->m->b!=0) + rgb.b=(unsigned char) + ((rgb.b*(255-lr->m->b) + +res.b*lr->m->b)*q); +#ifndef ALL_HAVE_ALPHA_255 + } + else /* alpha and mask */ + { + rgb.r=(unsigned char) + ((rgb.r*(255*255-lr->m->r*lr->alpha) + +res.r*lr->m->r*lr->alpha)*q2); + rgb.g=(unsigned char) + ((rgb.g*(255*255-lr->m->g*lr->alpha) + +res.g*lr->m->g*lr->alpha)*q2); + rgb.b=(unsigned char) + ((rgb.b*(255*255-lr->m->b*lr->alpha) + +res.b*lr->m->b*lr->alpha)*q2); + } +#endif + lr->m++; +#ifndef ALL_HAVE_MASK + } + else /* no mask */ + { +#ifndef ALL_HAVE_ALPHA_255 + if (lr->alpha==255) /* no alpha (bam!) */ +#endif + rgb=res; +#ifndef ALL_HAVE_ALPHA_255 + else /* only alpha */ + { + rgb.r=(unsigned char) + ((rgb.r*(255-lr->alpha) + +res.r*lr->alpha)*q); + rgb.g=(unsigned char) + ((rgb.g*(255-lr->alpha) + +res.g*lr->alpha)*q); + rgb.b=(unsigned char) + ((rgb.b*(255-lr->alpha) + +res.b*lr->alpha)*q); + } +#endif + } +#endif + } +#endif + lr->s++; + } + *(d++)=rgb; + s++; + } + + s+=mod; + for (l=0; l<layers; l++) + { + layer[l].s+=mod; + if (layer[l].m) layer[l].m+=mod; + } + }