e576bb2002-10-11Martin Nilsson /* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. */
1b10db2002-10-08Martin Nilsson 
ab6aec1997-02-11Fredrik Hübinette (Hubbe) #include "global.h"
b9284c1997-04-09Mirar (Pontus Hagland) /* **! module Image
448c201999-04-13Mirar (Pontus Hagland) **! class Image
b9284c1997-04-09Mirar (Pontus Hagland) */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) #include <math.h> #include <ctype.h>
bb55f81997-03-16Fredrik Hübinette (Hubbe) #include "pike_macros.h"
ab6aec1997-02-11Fredrik Hübinette (Hubbe) #include "interpret.h" #include "svalue.h"
b2d3e42000-12-01Fredrik Hübinette (Hubbe) #include "pike_error.h"
ab6aec1997-02-11Fredrik Hübinette (Hubbe) #include "threads.h" #include "image.h"
e34df12000-06-03Per Hedbor #include "image_machine.h"
6ad2372002-05-11Martin Nilsson #define sp Pike_sp
ab6aec1997-02-11Fredrik Hübinette (Hubbe) extern struct program *image_program;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) #ifdef THIS #undef THIS /* Needed for NT */ #endif
39221e2000-07-07Henrik Grubbström (Grubba) #define THIS ((struct image *)(Pike_fp->current_storage)) #define THISOBJ (Pike_fp->current_object)
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  #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 /***************** internals ***********************************/
01b9212016-01-12Per Hedbor static inline int getrgb(struct image *img,
0164be1999-05-25Mirar (Pontus Hagland)  INT32 args_start,INT32 args,INT32 max,char *name)
ab6aec1997-02-11Fredrik Hübinette (Hubbe) { INT32 i;
f6dbf61999-05-20Mirar (Pontus Hagland)  if (args-args_start<1) return 0; if (image_color_svalue(sp-args+args_start,&(img->rgb))) return 1;
0164be1999-05-25Mirar (Pontus Hagland)  if (max<3 || args-args_start<3) return 0;
f6dbf61999-05-20Mirar (Pontus Hagland) 
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  for (i=0; i<3; i++)
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(sp[-args+i+args_start]) != T_INT)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Illegal r,g,b argument to %s\n",name);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  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;
f5e1e61999-05-24Mirar (Pontus Hagland) 
57d4d32000-08-23Henrik Grubbström (Grubba)  if (max > 3 && args-args_start>=4) {
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(sp[3-args+args_start]) != T_INT) {
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Illegal alpha argument to %s\n",name);
f6dbf61999-05-20Mirar (Pontus Hagland)  }
57d4d32000-08-23Henrik Grubbström (Grubba)  img->alpha=sp[3-args+args_start].u.integer; return 4;
f6dbf61999-05-20Mirar (Pontus Hagland)  }
57d4d32000-08-23Henrik Grubbström (Grubba)  img->alpha=0; return 3;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) }
f6dbf61999-05-20Mirar (Pontus Hagland) 
ab6aec1997-02-11Fredrik Hübinette (Hubbe) /*** end internals ***/
4b4c692000-08-09Henrik Grubbström (Grubba) void img_clear(rgb_group *dest, rgb_group rgb, ptrdiff_t size)
ab6aec1997-02-11Fredrik Hübinette (Hubbe) {
2c7bd41997-11-23Per Hedbor  if(!size) return; THREADS_ALLOW();
b7f9fb2000-06-04Per Hedbor  if( ( rgb.r == rgb.g && rgb.r == rgb.b ) )
21b12a2014-09-03Martin Nilsson  memset(dest, rgb.r, size*sizeof(rgb_group) );
2c7bd41997-11-23Per Hedbor  else if(size) {
b7f9fb2000-06-04Per Hedbor  int increment = 1; rgb_group *from = dest; *(dest++)=rgb; size -= 1;
13670c2015-05-25Martin Nilsson  while (size>increment)
2c7bd41997-11-23Per Hedbor  {
59fc9e2014-09-03Martin Nilsson  memcpy(dest,from,increment*sizeof(rgb_group));
b7f9fb2000-06-04Per Hedbor  size-=increment,dest+=increment; if (increment<1024) increment *= 2;
2c7bd41997-11-23Per Hedbor  }
59fc9e2014-09-03Martin Nilsson  if(size>0) memcpy(dest,from,size*sizeof(rgb_group));
2c7bd41997-11-23Per Hedbor  } THREADS_DISALLOW();
ab6aec1997-02-11Fredrik Hübinette (Hubbe) } void img_box_nocheck(INT32 x1,INT32 y1,INT32 x2,INT32 y2) { INT32 x,mod; rgb_group *foo,*end,rgb; struct image *this; this=THIS;
7192821997-11-23Per Hedbor  rgb=this->rgb;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  mod=this->xsize-(x2-x1)-1; foo=this->img+x1+y1*this->xsize;
6fa2c81997-11-24Mirar (Pontus Hagland)  end=this->img+x2+y2*this->xsize+1;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
49d4632003-03-31Henrik Grubbström (Grubba)  if(!this->alpha) { if(!mod) img_clear(foo,rgb,end-foo); else { THREADS_ALLOW(); do {
b7b7e52000-04-13Henrik Grubbström (Grubba)  int length = x2-x1+1, xs=this->xsize, y=y2-y1+1; rgb_group *from = foo; if(!length) break; /* Break to the while(0). */ for(x=0; x<length; x++) *(foo+x) = rgb;
13670c2015-05-25Martin Nilsson  while(--y) memcpy((foo+=xs), from, length*sizeof(rgb_group));
49d4632003-03-31Henrik Grubbström (Grubba)  } while(0); THREADS_DISALLOW(); }
13670c2015-05-25Martin Nilsson  } else
49d4632003-03-31Henrik Grubbström (Grubba)  { THREADS_ALLOW(); do {
2b379f2006-08-31Martin Nilsson  for (; foo<end; foo+=mod) for (x=x1; x<=x2; x++,foo++) set_rgb_group_alpha(*foo,rgb,this->alpha);
49d4632003-03-31Henrik Grubbström (Grubba)  } while(0); THREADS_DISALLOW(); }
ab6aec1997-02-11Fredrik Hübinette (Hubbe) } void img_blit(rgb_group *dest,rgb_group *src,INT32 width, INT32 lines,INT32 moddest,INT32 modsrc) {
1f99241997-09-06Per Hedbor  if(width <= 0 || lines <= 0) return;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) CHRONO("image_blit begin"); THREADS_ALLOW();
7192821997-11-23Per Hedbor  if(!moddest && !modsrc)
59fc9e2014-09-03Martin Nilsson  memcpy(dest,src,sizeof(rgb_group)*width*lines);
7192821997-11-23Per Hedbor  else while (lines--) {
59fc9e2014-09-03Martin Nilsson  memcpy(dest,src,sizeof(rgb_group)*width);
7192821997-11-23Per Hedbor  dest+=moddest; src+=modsrc; }
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  THREADS_DISALLOW(); CHRONO("image_blit end"); } void img_crop(struct image *dest, struct image *img, INT32 x1,INT32 y1, INT32 x2,INT32 y2) { rgb_group *new;
49b0292002-04-10Stefan Wallström  INT32 xp,yp,xs,ys,tmp;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
93d6082015-04-26Peter Bortas  if (dest->img) { free(dest->img); dest->img=NULL; }
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
49b0292002-04-10Stefan Wallström  if (x1>x2) tmp=x1, x1=x2, x2=tmp; if (y1>y2) tmp=y1, y1=y2, y2=tmp;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
20d0552009-04-22Martin Stjernholm  new=xalloc( (x2-x1+1)*(y2-y1+1)*sizeof(rgb_group)+RGB_VEC_PAD );
7d60af2004-05-19Martin Nilsson 
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (x1==0 && y1==0 && img->xsize-1==x2 && img->ysize-1==y2) { *dest=*img; THREADS_ALLOW();
59fc9e2014-09-03Martin Nilsson  memcpy(new,img->img,(x2-x1+1)*(y2-y1+1)*sizeof(rgb_group));
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  THREADS_DISALLOW(); dest->img=new; return; } img_clear(new,THIS->rgb,(x2-x1+1)*(y2-y1+1)); dest->xsize=x2-x1+1; dest->ysize=y2-y1+1;
7210191997-12-22Fredrik Hübinette (Hubbe)  xp=MAXIMUM(0,-x1); yp=MAXIMUM(0,-y1); xs=MAXIMUM(0,x1); ys=MAXIMUM(0,y1);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
49b0292002-04-10Stefan Wallström  if( ! (( x2 < 0) || (y2 < 0) || (x1>=img->xsize) || (y1>=img->ysize))) {
13670c2015-05-25Martin Nilsson 
afbe792015-04-18Henrik Grubbström (Grubba)  if (x1<0) x1=0; if (y1<0) y1=0; if (x2>=img->xsize) x2=img->xsize-1; if (y2>=img->ysize) y2=img->ysize-1;
13670c2015-05-25Martin Nilsson 
49b0292002-04-10Stefan Wallström  img_blit(new+xp+yp*dest->xsize, img->img+xs+(img->xsize)*ys, x2-x1+1, y2-y1+1, dest->xsize, img->xsize);
13670c2015-05-25Martin Nilsson  }
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  dest->img=new; } void img_clone(struct image *newimg,struct image *img) { if (newimg->img) free(newimg->img);
20d0552009-04-22Martin Stjernholm  newimg->img=xalloc(sizeof(rgb_group)*img->xsize*img->ysize+RGB_VEC_PAD);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  THREADS_ALLOW();
59fc9e2014-09-03Martin Nilsson  memcpy(newimg->img,img->img,sizeof(rgb_group)*img->xsize*img->ysize);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  THREADS_DISALLOW(); newimg->xsize=img->xsize; newimg->ysize=img->ysize; newimg->rgb=img->rgb; }
64f1361997-03-25Mirar (Pontus Hagland) /* **! method object paste(object image) **! method object paste(object image,int x,int y) **! Pastes a given image over the current image. **! **! returns the object called **!
f311411997-04-18Mirar (Pontus Hagland) **! arg object image
8597ae1997-11-06Mirar (Pontus Hagland) **! image to paste (may be empty, needs to be an image object)
f311411997-04-18Mirar (Pontus Hagland) **! arg int x **! arg int y
64f1361997-03-25Mirar (Pontus Hagland) **! where to paste the image; default is 0,0 **! **! see also: paste_mask, paste_alpha, paste_alpha_color */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void image_paste(INT32 args) {
f6dbf61999-05-20Mirar (Pontus Hagland)  struct image *img=NULL;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  INT32 x1,y1,x2,y2,blitwidth,blitheight; if (args<1
017b572011-10-28Henrik Grubbström (Grubba)  || TYPEOF(sp[-args]) != T_OBJECT
13b5ed2014-05-26Per Hedbor  || !(img=get_storage(sp[-args].u.object,image_program)))
212c392018-02-25Martin Nilsson  bad_arg_error("paste",args,1,"",sp+1-1-args,
de22f72014-08-25Martin Nilsson  "Bad argument 1 to paste.\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (!THIS->img) return;
8597ae1997-11-06Mirar (Pontus Hagland)  if (!img->img) return;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
8597ae1997-11-06Mirar (Pontus Hagland)  if (args>1)
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  {
13670c2015-05-25Martin Nilsson  if (args<3
017b572011-10-28Henrik Grubbström (Grubba)  || TYPEOF(sp[1-args]) != T_INT || TYPEOF(sp[2-args]) != T_INT)
212c392018-02-25Martin Nilsson  bad_arg_error("paste",args,0,"",sp-args,
de22f72014-08-25Martin Nilsson  "Bad arguments to paste.\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  x1=sp[1-args].u.integer; y1=sp[2-args].u.integer; } else x1=y1=0;
f729e81997-09-01Per Hedbor  if(x1 >= THIS->xsize || y1 >= THIS->ysize) /* Per */ { pop_n_elems(args);
d6ac731998-04-20Henrik Grubbström (Grubba)  ref_push_object(THISOBJ);
f729e81997-09-01Per Hedbor  return;
13670c2015-05-25Martin Nilsson  }
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  x2=x1+img->xsize-1; y2=y1+img->ysize-1;
f729e81997-09-01Per Hedbor  if(x2 < 0 || y2 < 0) /* Per */ { pop_n_elems(args);
d6ac731998-04-20Henrik Grubbström (Grubba)  ref_push_object(THISOBJ);
f729e81997-09-01Per Hedbor  return;
13670c2015-05-25Martin Nilsson  }
7210191997-12-22Fredrik Hübinette (Hubbe)  blitwidth=MINIMUM(x2,THIS->xsize-1)-MAXIMUM(x1,0)+1; blitheight=MINIMUM(y2,THIS->ysize-1)-MAXIMUM(y1,0)+1;
13670c2015-05-25Martin Nilsson 
7210191997-12-22Fredrik Hübinette (Hubbe)  img_blit(THIS->img+MAXIMUM(0,x1)+(THIS->xsize)*MAXIMUM(0,y1), img->img+MAXIMUM(0,-x1)+(x2-x1+1)*MAXIMUM(0,-y1),
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  blitwidth, blitheight, THIS->xsize, img->xsize); pop_n_elems(args);
d6ac731998-04-20Henrik Grubbström (Grubba)  ref_push_object(THISOBJ);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) }
64f1361997-03-25Mirar (Pontus Hagland) /* **! method object paste_alpha(object image,int alpha) **! method object paste_alpha(object image,int alpha,int x,int y) **! Pastes a given image over the current image, with **! the specified alpha channel value.
13670c2015-05-25Martin Nilsson **! **! An alpha channel value of 0 leaves nothing of the original
64f1361997-03-25Mirar (Pontus Hagland) **! image in the paste area, 255 is meaningless and makes the **! given image invisible. **! **! returns the object called **!
f311411997-04-18Mirar (Pontus Hagland) **! arg object image
64f1361997-03-25Mirar (Pontus Hagland) **! image to paste
f311411997-04-18Mirar (Pontus Hagland) **! arg int alpha
64f1361997-03-25Mirar (Pontus Hagland) **! alpha channel value
f311411997-04-18Mirar (Pontus Hagland) **! arg int x **! arg int y
64f1361997-03-25Mirar (Pontus Hagland) **! where to paste the image; default is 0,0 **! **! see also: paste_mask, paste, paste_alpha_color */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void image_paste_alpha(INT32 args) {
36a00c2000-08-15Henrik Grubbström (Grubba)  struct image *img = NULL;
8597ae1997-11-06Mirar (Pontus Hagland)  INT32 x1,y1;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (args<2
017b572011-10-28Henrik Grubbström (Grubba)  || TYPEOF(sp[-args]) != T_OBJECT
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  || !sp[-args].u.object
13b5ed2014-05-26Per Hedbor  || !(img=get_storage(sp[-args].u.object,image_program))
017b572011-10-28Henrik Grubbström (Grubba)  || TYPEOF(sp[1-args]) != T_INT)
212c392018-02-25Martin Nilsson  bad_arg_error("paste_alpha",args,0,"",sp-args,
de22f72014-08-25Martin Nilsson  "Bad arguments to paste_alpha.\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (!THIS->img) return;
8597ae1997-11-06Mirar (Pontus Hagland)  if (!img->img) return;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  THIS->alpha=(unsigned char)(sp[1-args].u.integer);
13670c2015-05-25Martin Nilsson 
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (args>=4) {
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(sp[2-args]) != T_INT || TYPEOF(sp[3-args]) != T_INT)
212c392018-02-25Martin Nilsson  bad_arg_error("paste_alpha",args,0,"",sp-args,
de22f72014-08-25Martin Nilsson  "Bad arguments to paste_alpha.\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  x1=sp[2-args].u.integer; y1=sp[3-args].u.integer; } else x1=y1=0;
f729e81997-09-01Per Hedbor  if(x1 >= THIS->xsize || y1 >= THIS->ysize) /* Per */ { pop_n_elems(args);
d6ac731998-04-20Henrik Grubbström (Grubba)  ref_push_object(THISOBJ);
f729e81997-09-01Per Hedbor  return;
13670c2015-05-25Martin Nilsson  }
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
f729e81997-09-01Per Hedbor /* tråda här nåndag.. Ok /Per */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
f729e81997-09-01Per Hedbor  { rgb_group *source = img->img; struct image *this = THIS; int xs = this->xsize, ix, mx=img->xsize, my=img->ysize, x; int ys = this->ysize, iy, y; THREADS_ALLOW(); for (iy=0; iy<my; iy++) for (ix=0; ix<mx; ix++) { x = ix + x1; y = iy + y1;
0af1852000-08-11Henrik Grubbström (Grubba)  if(x>=0 && y>=0 && x<xs && y<ys) {
f729e81997-09-01Per Hedbor  if(this->alpha) set_rgb_group_alpha(this->img[x+y*xs],*(source),this->alpha); else this->img[x+y*xs]=*(source);
0af1852000-08-11Henrik Grubbström (Grubba)  }
f729e81997-09-01Per Hedbor  source++; } THREADS_DISALLOW(); }
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  pop_n_elems(args);
d6ac731998-04-20Henrik Grubbström (Grubba)  ref_push_object(THISOBJ);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) }
64f1361997-03-25Mirar (Pontus Hagland) /* **! method object paste_mask(object image,object mask) **! method object paste_mask(object image,object mask,int x,int y) **! Pastes a given image over the current image,
13670c2015-05-25Martin Nilsson **! using the given mask as opaque channel. **!
64f1361997-03-25Mirar (Pontus Hagland) **! A pixel value of 255 makes the result become a pixel **! from the given image, 0 doesn't change anything. **! **! The masks red, green and blue values are used separately. **! **! returns the object called **!
f311411997-04-18Mirar (Pontus Hagland) **! arg object image
64f1361997-03-25Mirar (Pontus Hagland) **! image to paste
f311411997-04-18Mirar (Pontus Hagland) **! arg object mask
64f1361997-03-25Mirar (Pontus Hagland) **! mask image
f311411997-04-18Mirar (Pontus Hagland) **! arg int x **! arg int y
64f1361997-03-25Mirar (Pontus Hagland) **! where to paste the image; default is 0,0 **! **! see also: paste, paste_alpha, paste_alpha_color */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void image_paste_mask(INT32 args) {
36a00c2000-08-15Henrik Grubbström (Grubba)  struct image *img = NULL, *mask = NULL;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  INT32 x1,y1,x,y,x2,y2,smod,dmod,mmod; rgb_group *s,*d,*m;
65a5492000-08-10Per Hedbor  double q;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  CHRONO("image_paste_mask init"); if (args<2)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("illegal number of arguments to image->paste_mask()\n");
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(sp[-args]) != T_OBJECT
13b5ed2014-05-26Per Hedbor  || !(img=get_storage(sp[-args].u.object,image_program)))
212c392018-02-25Martin Nilsson  bad_arg_error("paste_mask",args,1,"",sp+1-1-args,
de22f72014-08-25Martin Nilsson  "Bad argument 1 to paste_mask.\n");
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(sp[1-args]) != T_OBJECT
13b5ed2014-05-26Per Hedbor  || !(mask=get_storage(sp[1-args].u.object,image_program)))
212c392018-02-25Martin Nilsson  bad_arg_error("paste_mask",args,2,"",sp+2-1-args,
de22f72014-08-25Martin Nilsson  "Bad argument 2 to paste_mask.\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (!THIS->img) return;
8597ae1997-11-06Mirar (Pontus Hagland)  if (!mask->img) return; if (!img->img) return;
13670c2015-05-25Martin Nilsson 
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (args>=4) {
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(sp[2-args]) != T_INT || TYPEOF(sp[3-args]) != T_INT)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("illegal coordinate arguments to image->paste_mask()\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  x1=sp[2-args].u.integer; y1=sp[3-args].u.integer; } else x1=y1=0;
7210191997-12-22Fredrik Hübinette (Hubbe)  x2=MINIMUM(THIS->xsize-x1,MINIMUM(img->xsize,mask->xsize)); y2=MINIMUM(THIS->ysize-y1,MINIMUM(img->ysize,mask->ysize));
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  CHRONO("image_paste_mask begin");
7210191997-12-22Fredrik Hübinette (Hubbe)  s=img->img+MAXIMUM(0,-x1)+MAXIMUM(0,-y1)*img->xsize; m=mask->img+MAXIMUM(0,-x1)+MAXIMUM(0,-y1)*mask->xsize; d=THIS->img+MAXIMUM(0,-x1)+x1+(y1+MAXIMUM(0,-y1))*THIS->xsize; x=MAXIMUM(0,-x1);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  smod=img->xsize-(x2-x); mmod=mask->xsize-(x2-x); dmod=THIS->xsize-(x2-x); q=1.0/255; THREADS_ALLOW();
7210191997-12-22Fredrik Hübinette (Hubbe)  for (y=MAXIMUM(0,-y1); y<y2; y++)
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  {
7210191997-12-22Fredrik Hübinette (Hubbe)  for (x=MAXIMUM(0,-x1); x<x2; x++)
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  { if (m->r==255) d->r=s->r;
64f1361997-03-25Mirar (Pontus Hagland)  else if (m->r==0) {}
8cc82a2016-02-12Martin Nilsson  else d->r = (COLORTYPE)(((d->r*(255-m->r))+(s->r*m->r))*q);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (m->g==255) d->g=s->g;
64f1361997-03-25Mirar (Pontus Hagland)  else if (m->g==0) {}
8cc82a2016-02-12Martin Nilsson  else d->g = (COLORTYPE)(((d->g*(255-m->g))+(s->g*m->g))*q);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (m->b==255) d->b=s->b;
64f1361997-03-25Mirar (Pontus Hagland)  else if (m->b==0) {}
8cc82a2016-02-12Martin Nilsson  else d->b = (COLORTYPE)(((d->b*(255-m->b))+(s->b*m->b))*q);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  s++; m++; d++; } s+=smod; m+=mmod; d+=dmod; } THREADS_DISALLOW(); CHRONO("image_paste_mask end"); pop_n_elems(args);
d6ac731998-04-20Henrik Grubbström (Grubba)  ref_push_object(THISOBJ);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) }
64f1361997-03-25Mirar (Pontus Hagland) /* **! method object paste_alpha_color(object mask) **! method object paste_alpha_color(object mask,int x,int y) **! method object paste_alpha_color(object mask,int r,int g,int b) **! method object paste_alpha_color(object mask,int r,int g,int b,int x,int y)
f6dbf61999-05-20Mirar (Pontus Hagland) **! method object paste_alpha_color(object mask,Color color) **! method object paste_alpha_color(object mask,Color color,int x,int y)
64f1361997-03-25Mirar (Pontus Hagland) **! Pastes a given color over the current image,
13670c2015-05-25Martin Nilsson **! using the given mask as opaque channel. **!
64f1361997-03-25Mirar (Pontus Hagland) **! A pixel value of 255 makes the result become the color given, **! 0 doesn't change anything.
13670c2015-05-25Martin Nilsson **!
64f1361997-03-25Mirar (Pontus Hagland) **! The masks red, green and blue values are used separately. **! If no color are given, the current is used. **! **! returns the object called **!
f311411997-04-18Mirar (Pontus Hagland) **! arg object mask
64f1361997-03-25Mirar (Pontus Hagland) **! mask image
f311411997-04-18Mirar (Pontus Hagland) **! arg int r **! arg int g **! arg int b
64f1361997-03-25Mirar (Pontus Hagland) **! what color to paint with; default is current
f311411997-04-18Mirar (Pontus Hagland) **! arg int x **! arg int y
64f1361997-03-25Mirar (Pontus Hagland) **! where to paste the image; default is 0,0 **! **! see also: paste_mask, paste_alpha, paste_alpha_color */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void image_paste_alpha_color(INT32 args) {
36a00c2000-08-15Henrik Grubbström (Grubba)  struct image *mask = NULL;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  INT32 x1,y1,x,y,x2,y2; rgb_group rgb,*d,*m; INT32 mmod,dmod;
65a5492000-08-10Per Hedbor  double q;
f6dbf61999-05-20Mirar (Pontus Hagland)  int arg=1;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
f6dbf61999-05-20Mirar (Pontus Hagland)  if (args<1)
06bd612016-01-26Martin Nilsson  SIMPLE_WRONG_NUM_ARGS_ERROR("image->paste_alpha_color",1);
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(sp[-args]) != T_OBJECT
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  || !sp[-args].u.object
13b5ed2014-05-26Per Hedbor  || !(mask=get_storage(sp[-args].u.object,image_program)))
212c392018-02-25Martin Nilsson  bad_arg_error("paste_alpha_color",args,1,"",sp+1-1-args,
de22f72014-08-25Martin Nilsson  "Bad argument 1 to paste_alpha_color.\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (!THIS->img) return;
8597ae1997-11-06Mirar (Pontus Hagland)  if (!mask->img) return;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
f6dbf61999-05-20Mirar (Pontus Hagland)  if (args==6 || args==4 || args==2 || args==3) /* color at arg 2.. */
bf4d372018-02-16Martin Nilsson  arg=1+getrgb(THIS,1,args,3,"paste_alpha_color");
13670c2015-05-25Martin Nilsson  if (args>arg+1)
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  {
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(sp[arg-args]) != T_INT || TYPEOF(sp[1+arg-args]) != T_INT)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("illegal coordinate arguments to image->paste_alpha_color()\n");
f6dbf61999-05-20Mirar (Pontus Hagland)  x1=sp[arg-args].u.integer;
f5e1e61999-05-24Mirar (Pontus Hagland)  y1=sp[1+arg-args].u.integer;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } else x1=y1=0;
13670c2015-05-25Martin Nilsson 
7210191997-12-22Fredrik Hübinette (Hubbe)  x2=MINIMUM(THIS->xsize-x1,mask->xsize); y2=MINIMUM(THIS->ysize-y1,mask->ysize);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  CHRONO("image_paste_alpha_color begin");
7210191997-12-22Fredrik Hübinette (Hubbe)  m=mask->img+MAXIMUM(0,-x1)+MAXIMUM(0,-y1)*mask->xsize; d=THIS->img+MAXIMUM(0,-x1)+x1+(y1+MAXIMUM(0,-y1))*THIS->xsize; x=MAXIMUM(0,-x1);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  mmod=mask->xsize-(x2-x); dmod=THIS->xsize-(x2-x); q=1.0/255; rgb=THIS->rgb; THREADS_ALLOW();
7210191997-12-22Fredrik Hübinette (Hubbe)  for (y=MAXIMUM(0,-y1); y<y2; y++)
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  {
7210191997-12-22Fredrik Hübinette (Hubbe)  for (x=MAXIMUM(0,-x1); x<x2; x++)
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  { if (m->r==255) d->r=rgb.r; else if (m->r==0) ;
8cc82a2016-02-12Martin Nilsson  else d->r = (COLORTYPE)(((d->r*(255-m->r))+(rgb.r*m->r))*q);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (m->g==255) d->g=rgb.g; else if (m->g==0) ;
8cc82a2016-02-12Martin Nilsson  else d->g = (COLORTYPE)(((d->g*(255-m->g))+(rgb.g*m->g))*q);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (m->b==255) d->b=rgb.b; else if (m->b==0) ;
8cc82a2016-02-12Martin Nilsson  else d->b = (COLORTYPE)(((d->b*(255-m->b))+(rgb.b*m->b))*q);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  m++; d++; } m+=mmod; d+=dmod; } THREADS_DISALLOW(); CHRONO("image_paste_alpha_color end"); pop_n_elems(args);
d6ac731998-04-20Henrik Grubbström (Grubba)  ref_push_object(THISOBJ);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) } void img_box(INT32 x1,INT32 y1,INT32 x2,INT32 y2)
13670c2015-05-25Martin Nilsson {
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (x1>x2) x1^=x2,x2^=x1,x1^=x2; if (y1>y2) y1^=y2,y2^=y1,y1^=y2;
eca7571997-09-19Henrik Grubbström (Grubba)  if (x2 >= THIS->xsize) x2 = THIS->xsize-1; if (y2 >= THIS->ysize) y2 = THIS->ysize-1;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (x2<0||y2<0||x1>=THIS->xsize||y1>=THIS->ysize) return;
eca7571997-09-19Henrik Grubbström (Grubba)  if (x1<0) x1 = 0; if (y1<0) y1 = 0;
7210191997-12-22Fredrik Hübinette (Hubbe)  img_box_nocheck(MAXIMUM(x1,0),MAXIMUM(y1,0),MINIMUM(x2,THIS->xsize-1),MINIMUM(y2,THIS->ysize-1));
ab6aec1997-02-11Fredrik Hübinette (Hubbe) }