diff --git a/src/modules/Image/image.c b/src/modules/Image/image.c index 4e46e6bef798dfd4df9640987bb39e72858081f0..0018f709f2d5354e00f6d122c55d4e733ccfde86 100644 --- a/src/modules/Image/image.c +++ b/src/modules/Image/image.c @@ -1,9 +1,9 @@ -/* $Id: image.c,v 1.79 1998/02/10 23:51:49 mirar Exp $ */ +/* $Id: image.c,v 1.80 1998/02/13 00:41:40 mirar Exp $ */ /* **! module Image **! note -**! $Id: image.c,v 1.79 1998/02/10 23:51:49 mirar Exp $ +**! $Id: image.c,v 1.80 1998/02/13 00:41:40 mirar Exp $ **! class image **! **! The main object of the <ref>Image</ref> module, this object @@ -82,7 +82,7 @@ #include "stralloc.h" #include "global.h" -RCSID("$Id: image.c,v 1.79 1998/02/10 23:51:49 mirar Exp $"); +RCSID("$Id: image.c,v 1.80 1998/02/13 00:41:40 mirar Exp $"); #include "pike_macros.h" #include "object.h" #include "constants.h" @@ -2386,6 +2386,227 @@ CHRONO("apply_matrix, end"); push_object(o); } +/* +**! method object outline() +**! method object outline(int olr,int olg,int olb) +**! method object outline(int olr,int olg,int olb,int bkgr,int bkgg,int bkgb) +**! method object outline(array(array(int)) mask) +**! method object outline(array(array(int)) mask,int olr,int olg,int olb) +**! method object outline(array(array(int)) mask,int olr,int olg,int olb,int bkgr,int bkgg,int bkgb) +**! method object outline_mask() +**! method object outline_mask(int bkgr,int bkgg,int bkgb) +**! method object outline_mask(array(array(int)) mask) +**! method object outline_mask(array(array(int)) mask,int bkgr,int bkgg,int bkgb) +**! Makes an outline of this image, ie paints with the +**! given color around the non-background pixels. +**! +**! Default is to paint above, below, to the left and the right of +**! these pixels. +**! +**! You can also run your own outline mask. +**! +**! The outline_mask function gives the calculated outline as an +**! alpha channel image of white and black instead. +**! +**! returns the new image object +**! +**! arg array(array(int)) mask +**! mask matrix. Default is <tt>({({0,1,0}),({1,1,1}),({0,1,0})})</tt>. +**! arg int olr +**! arg int olg +**! arg int olb +**! outline color. Default is current. +**! arg int bkgr +**! arg int bkgg +**! arg int bkgb +**! background color (what color to outline to); +**! default is color of pixel 0,0. +**! arg int|float div +**! division factor, default is 1.0. +**! +**! note +**! no antialias! +*/ + +static void _image_outline(INT32 args,int mask) +{ + static unsigned char defaultmatrix[9]={0,1,0,1,1,1,0,1,0}; + unsigned char *matrix=defaultmatrix; + int height=3; + int width=3; + unsigned char *tmp,*d; + INT32 ai=0; + rgb_group *s,*di; + int x,y,xz; + rgbl_group bkgl={0,0,0}; + struct object *o; + struct image *img; + + if (!THIS->img || !THIS->xsize || !THIS->ysize) + error("Image.image->outline: no image\n"); + + if (args && sp[-args].type==T_ARRAY) + { + int i,j; + height=sp[-args].u.array->size; + width=-1; + for (i=0; i<height; i++) + { + struct svalue s=sp[-args].u.array->item[i]; + if (s.type!=T_ARRAY) + error("Image.image->outline: Illegal contents of (root) array\n"); + if (width==-1) + width=s.u.array->size; + else + if (width!=s.u.array->size) + error("Image.image->outline: Arrays has different size\n"); + } + if (width==-1) width=0; + + matrix=malloc(sizeof(int)*width*height+1); + if (!matrix) error("Out of memory"); + + for (i=0; i<height; i++) + { + struct svalue s=sp[-args].u.array->item[i]; + for (j=0; j<width; j++) + { + struct svalue s2=s.u.array->item[j]; + if (s2.type==T_INT) + matrix[j+i*width]=(unsigned char)s2.u.integer; + else + matrix[j+i*width]=1; + } + } + ai=1; + } + + push_int(THIS->xsize); + push_int(THIS->ysize); + o=clone_object(image_program,2); + img=(struct image*)(o->storage); + + tmp=malloc((THIS->xsize+width-1)*(THIS->ysize+height)); + if (!tmp) { free_object(o); error("out of memory\n"); } + MEMSET(tmp,0,(THIS->xsize+width-1)*(THIS->ysize+height-1)); + + s=THIS->img; + + if (!mask) + { + if (args-ai==6) + { + getrgbl(&bkgl,ai+3,args,"Image.image->outline"); + pop_n_elems(args-(ai+3)); + args=ai+3; + } + else if (args-ai==7) + { + getrgbl(&bkgl,ai+4,args,"Image.image->outline"); + pop_n_elems(args-(ai+4)); + args=ai+4; + } + else + { + bkgl.r=s->r; + bkgl.g=s->g; + bkgl.b=s->b; + } + getrgb(img,ai,args,"Image.image->outline"); + } + else + { + if (args-ai==4) + { + getrgbl(&bkgl,ai,args,"Image.image->outline_mask"); + pop_n_elems(args-(ai+3)); + args=ai+3; + } + else + { + bkgl.r=s->r; + bkgl.g=s->g; + bkgl.b=s->b; + } + } + + xz=img->xsize; + d=tmp+width/2+(height/2)*(width+xz); + y=img->ysize; + while (y--) + { + x=xz; + while (x--) + { + if (s->r!=bkgl.r || s->g!=bkgl.g || s->b!=bkgl.b) + { + unsigned char *d2=d-width/2-(height/2)*(width+xz); + int y2,x2; + unsigned char *s2=matrix; + y2=height; + while (y2--) + { + x2=width; + while (x2--) *(d2++)|=*(s2++); + d2+=xz; + } + } + s++; + d++; + } + d+=width; + } + + di=img->img; + d=tmp+width/2+(height/2)*(width+xz); + s=THIS->img; + y=img->ysize; + while (y--) + { + x=xz; + if (mask) + while (x--) + { + static rgb_group white={255,255,255}; + static rgb_group black={0,0,0}; + if (*d && s->r==bkgl.r && s->g==bkgl.g && s->b==bkgl.b) + *di=white; + else + *di=black; + s++; + d++; + di++; + } + else + while (x--) + { + if (*d && s->r==bkgl.r && s->g==bkgl.g && s->b==bkgl.b) + *di=img->rgb; + else + *di=*s; + s++; + d++; + di++; + } + d+=width; + } + + if (matrix!=defaultmatrix) free(matrix); + + pop_n_elems(args); + push_object(o); +} + +static void image_outline(INT32 args) +{ + _image_outline(args,0); +} + +static void image_outline_mask(INT32 args) +{ + _image_outline(args,1); +} + /* **! method object modify_by_intensity(int r,int g,int b,int|array(int) v1,...,int|array(int) vn) **! Recolor an image from intensity values. @@ -2922,6 +3143,13 @@ void pike_module_init(void) add_function("apply_matrix",image_apply_matrix, "function(array(array(int|array(int))), void|int ...:object)",0); + add_function("outline",image_outline, + "function(void|array(array(int)):object)" + "|function(array(array(int)),int,int,int,void|int:object)" + "|function(array(array(int)),int,int,int,int,int,int,void|int:object)",0); + add_function("outline_mask",image_outline_mask, + "function(void|array(array(int)):object)" + "|function(array(array(int)),int,int,int:object)",0); add_function("modify_by_intensity",image_modify_by_intensity, "function(int,int,int,int,int:object)",0);