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. */
2f7d791997-03-25Mirar (Pontus Hagland)  /* **! module Image
7740622014-08-25Per Hedbor **! Image processing, decoding/loading and encoding/saving. **! **! Some starting points: **! <ref>Image.Image</ref> - The main image object <br> **! <ref>Image.load</ref>, <ref>Image.load_layers</ref> - Loads and decodes data <br> **! <ref>Image.lay</ref> - The base image layer compositing method <br> **!
02c2d21999-04-13Mirar (Pontus Hagland) **! class Image
a827cd1997-04-19Mirar (Pontus Hagland) **! **! The main object of the <ref>Image</ref> module, this object **! is used as drawing area, mask or result of operations. **!
8626fb1998-04-16Mirar (Pontus Hagland) **! basic: <br> **! <ref>clear</ref>,
a827cd1997-04-19Mirar (Pontus Hagland) **! <ref>clone</ref>,
7740622014-08-25Per Hedbor **! <ref>create</ref>,
a827cd1997-04-19Mirar (Pontus Hagland) **! <ref>xsize</ref>, **! <ref>ysize</ref> **!
8626fb1998-04-16Mirar (Pontus Hagland) **! plain drawing: <br> **! <ref>box</ref>,
a827cd1997-04-19Mirar (Pontus Hagland) **! <ref>circle</ref>,
7740622014-08-25Per Hedbor **! <ref>getpixel</ref>,
a827cd1997-04-19Mirar (Pontus Hagland) **! <ref>line</ref>, **! <ref>setcolor</ref>,
7740622014-08-25Per Hedbor **! <ref>setpixel</ref>,
f8feda1997-11-13Henrik Wallin **! <ref>threshold</ref>,
cee41d1997-11-12Mirar (Pontus Hagland) **! <ref>polyfill</ref>
a827cd1997-04-19Mirar (Pontus Hagland) **!
8626fb1998-04-16Mirar (Pontus Hagland) **! operators: <br> **! <ref>`&</ref>,
a827cd1997-04-19Mirar (Pontus Hagland) **! <ref>`*</ref>, **! <ref>`+</ref>, **! <ref>`-</ref>,
8626fb1998-04-16Mirar (Pontus Hagland) **! <ref>`==</ref>, **! <ref>`></ref>,
b0f6b21998-07-04Martin Stjernholm **! <ref>`&lt;</ref>,
a827cd1997-04-19Mirar (Pontus Hagland) **! <ref>`|</ref> **!
ab83a81999-04-16Mirar (Pontus Hagland) **! pasting images: <br>
a827cd1997-04-19Mirar (Pontus Hagland) **! <ref>paste</ref>, **! <ref>paste_alpha</ref>, **! <ref>paste_alpha_color</ref>, **! <ref>paste_mask</ref> **!
8626fb1998-04-16Mirar (Pontus Hagland) **! getting subimages, scaling, rotating: <br>
13670c2015-05-25Martin Nilsson **! <ref>autocrop</ref>,
a827cd1997-04-19Mirar (Pontus Hagland) **! <ref>clone</ref>,
13670c2015-05-25Martin Nilsson **! <ref>copy</ref>,
a827cd1997-04-19Mirar (Pontus Hagland) **! <ref>dct</ref>,
13670c2015-05-25Martin Nilsson **! <ref>mirrorx</ref>,
a827cd1997-04-19Mirar (Pontus Hagland) **! <ref>rotate</ref>,
2c8d131997-05-30Mirar (Pontus Hagland) **! <ref>rotate_ccw</ref>, **! <ref>rotate_cw</ref>,
13670c2015-05-25Martin Nilsson **! <ref>rotate_expand</ref>, **! <ref>scale</ref>,
a827cd1997-04-19Mirar (Pontus Hagland) **! <ref>skewx</ref>, **! <ref>skewx_expand</ref>, **! <ref>skewy</ref>, **! <ref>skewy_expand</ref> **!
8626fb1998-04-16Mirar (Pontus Hagland) **! calculation by pixels: <br>
13670c2015-05-25Martin Nilsson **! <ref>apply_matrix</ref>,
a827cd1997-04-19Mirar (Pontus Hagland) **! <ref>change_color</ref>, **! <ref>color</ref>,
13670c2015-05-25Martin Nilsson **! <ref>distancesq</ref>,
a827cd1997-04-19Mirar (Pontus Hagland) **! <ref>grey</ref>,
13670c2015-05-25Martin Nilsson **! <ref>invert</ref>,
a827cd1997-04-19Mirar (Pontus Hagland) **! <ref>modify_by_intensity</ref>,
8626fb1998-04-16Mirar (Pontus Hagland) **! <ref>outline</ref>
13670c2015-05-25Martin Nilsson **! <ref>select_from</ref>,
2c8d131997-05-30Mirar (Pontus Hagland) **! <ref>rgb_to_hsv</ref>,
9e2b662004-07-08Marcus Comstedt **! <ref>hsv_to_rgb</ref>, **! <ref>rgb_to_yuv</ref>, **! <ref>yuv_to_rgb</ref>,<br>
a827cd1997-04-19Mirar (Pontus Hagland) **!
8626fb1998-04-16Mirar (Pontus Hagland) **! <ref>average</ref>, **! <ref>max</ref>, **! <ref>min</ref>, **! <ref>sum</ref>, **! <ref>sumf</ref>, **! <ref>find_min</ref>, **! <ref>find_max</ref>
a827cd1997-04-19Mirar (Pontus Hagland) **!
8626fb1998-04-16Mirar (Pontus Hagland) **! special pattern drawing:<br>
4ce7411997-05-29Mirar (Pontus Hagland) **! <ref>noise</ref>,
8626fb1998-04-16Mirar (Pontus Hagland) **! <ref>turbulence</ref>, **! <ref>test</ref>, **! <ref>tuned_box</ref>,
ab83a81999-04-16Mirar (Pontus Hagland) **! <ref>gradients</ref>, **! <ref>random</ref>
4ce7411997-05-29Mirar (Pontus Hagland) **!
448c201999-04-13Mirar (Pontus Hagland) **! see also: Image, Image.Font, Image.Colortable, Image.X
a8622f1997-04-20Henrik Grubbström (Grubba) */
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  #include "global.h"
40555b2000-06-02Per Hedbor #include "image_machine.h"
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  #include <math.h> #include <ctype.h> #include "stralloc.h"
bb55f81997-03-16Fredrik Hübinette (Hubbe) #include "pike_macros.h"
ab6aec1997-02-11Fredrik Hübinette (Hubbe) #include "object.h" #include "interpret.h" #include "svalue.h" #include "threads.h" #include "array.h"
b2d3e42000-12-01Fredrik Hübinette (Hubbe) #include "pike_error.h"
d158881999-07-21Mirar (Pontus Hagland) #include "module_support.h"
68ec3f2014-08-18Martin Nilsson #include "pike_types.h"
aff9242016-01-17Martin Nilsson #include "operators.h" #include "mapping.h" #include "constants.h"
9d1f542017-01-25Henrik Grubbström (Grubba) #include "sprintf.h"
068c061997-04-30Mirar (Pontus Hagland) 
ab6aec1997-02-11Fredrik Hübinette (Hubbe) #include "image.h"
99f1ea1997-11-08Henrik Grubbström (Grubba) #include "colortable.h"
ab6aec1997-02-11Fredrik Hübinette (Hubbe) #include "builtin_functions.h"
40555b2000-06-02Per Hedbor #ifdef ASSEMBLY_OK #include "assembly.h" #endif
6dc2772000-07-28Fredrik Hübinette (Hubbe) 
6ad2372002-05-11Martin Nilsson #define sp Pike_sp
6dc2772000-07-28Fredrik Hübinette (Hubbe) 
cd0c611999-06-03Mirar (Pontus Hagland) extern struct program *image_program;
844eae1997-11-07Mirar (Pontus Hagland) extern struct program *image_colortable_program;
94050c2009-07-21Henrik Grubbström (Grubba) extern struct program *image_color_program;
068c061997-04-30Mirar (Pontus Hagland) 
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)  #define sq(x) ((x)*(x)) #define CIRCLE_STEPS 128 static INT32 circle_sin_table[CIRCLE_STEPS]; #define circle_sin(x) circle_sin_table[((x)+CIRCLE_STEPS)%CIRCLE_STEPS] #define circle_cos(x) circle_sin((x)-CIRCLE_STEPS/4) #define circle_sin_mul(x,y) ((circle_sin(x)*(y))/4096) #define circle_cos_mul(x,y) ((circle_cos(x)*(y))/4096) #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 /***************** init & exit *********************************/
3df84b2017-07-19Martin Nilsson #ifdef PIKE_NULL_IS_SPECIAL
74dfe82012-12-30Jonas Walldén static void init_image_struct(struct object *UNUSED(obj))
ab6aec1997-02-11Fredrik Hübinette (Hubbe) { THIS->img=NULL; THIS->rgb.r=0; THIS->rgb.g=0; THIS->rgb.b=0;
2f7d791997-03-25Mirar (Pontus Hagland)  THIS->xsize=THIS->ysize=0; THIS->alpha=0;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) }
3df84b2017-07-19Martin Nilsson #endif
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
74dfe82012-12-30Jonas Walldén static void exit_image_struct(struct object *UNUSED(obj))
ab6aec1997-02-11Fredrik Hübinette (Hubbe) {
b359622014-07-28Per Hedbor  if (THIS->img) { if( Pike_fp->current_object->flags & OBJECT_CLEAR_ON_EXIT ) memset( THIS->img, 0, sizeof(rgb_group)*THIS->xsize*(long)THIS->ysize );
ac3f772015-04-24Peter Bortas  free(THIS->img);
b359622014-07-28Per Hedbor  }
ab6aec1997-02-11Fredrik Hübinette (Hubbe) } /***************** internals ***********************************/ #define setpixel(x,y) \ (THIS->alpha? \ set_rgb_group_alpha(THIS->img[(x)+(y)*THIS->xsize],THIS->rgb,THIS->alpha): \ ((pixel(THIS,x,y)=THIS->rgb),0))
157e101997-11-23Per Hedbor #define color_equal(A,B) (((A).r == (B).r) && ((A).g == (B).g) && ((A).b == (B).b))
1482aa1997-11-23Per Hedbor 
ab6aec1997-02-11Fredrik Hübinette (Hubbe) #define setpixel_test(x,y) \
c1260f1997-11-23Per Hedbor  ((((int)x)<0||((int)y)<0||((int)x)>=(int)THIS->xsize||((int)y)>=(int)THIS->ysize)? \ 0:(setpixel((int)x,(int)y),0))
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
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;
db75b01999-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;
db75b01999-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;
0164be1999-05-25Mirar (Pontus Hagland) 
017b572011-10-28Henrik Grubbström (Grubba)  if (max > 3 && args-args_start>=4) if (TYPEOF(sp[3-args+args_start]) != T_INT)
e2becd1999-08-27Mirar (Pontus Hagland)  {
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Illegal alpha argument to %s\n",name);
e2becd1999-08-27Mirar (Pontus Hagland)  return 0; /* avoid stupid warning */ }
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  else
db75b01999-05-20Mirar (Pontus Hagland)  {
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  img->alpha=sp[3-args+args_start].u.integer;
db75b01999-05-20Mirar (Pontus Hagland)  return 4; }
45e55c1998-01-25Mirar (Pontus Hagland)  else
db75b01999-05-20Mirar (Pontus Hagland)  {
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  img->alpha=0;
db75b01999-05-20Mirar (Pontus Hagland)  return 3; }
ab6aec1997-02-11Fredrik Hübinette (Hubbe) }
01b9212016-01-12Per Hedbor static inline void getrgbl(rgbl_group *rgb,INT32 args_start,INT32 args,char *name)
ab6aec1997-02-11Fredrik Hübinette (Hubbe) { INT32 i; if (args-args_start<3) return; 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)  rgb->r=sp[-args+args_start].u.integer; rgb->g=sp[1-args+args_start].u.integer; rgb->b=sp[2-args+args_start].u.integer; }
01b9212016-01-12Per Hedbor static inline void img_line(INT32 x1,INT32 y1,INT32 x2,INT32 y2)
13670c2015-05-25Martin Nilsson {
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  INT32 pixelstep,pos;
13670c2015-05-25Martin Nilsson  if (x1==x2)
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  { if (y1>y2) y1^=y2,y2^=y1,y1^=y2; if (x1<0||x1>=THIS->xsize|| y2<0||y1>=THIS->ysize) return; if (y1<0) y1=0; if (y2>=THIS->ysize) y2=THIS->ysize-1; for (;y1<=y2;y1++) setpixel_test(x1,y1); return; } else if (y1==y2) { if (x1>x2) x1^=x2,x2^=x1,x1^=x2; if (y1<0||y1>=THIS->ysize|| x2<0||x1>=THIS->xsize) return;
13670c2015-05-25Martin Nilsson  if (x1<0) x1=0;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (x2>=THIS->xsize) x2=THIS->xsize-1; for (;x1<=x2;x1++) setpixel_test(x1,y1); return; } else if (abs(x2-x1)<abs(y2-y1)) /* mostly vertical line */ { if (y1>y2) y1^=y2,y2^=y1,y1^=y2, x1^=x2,x2^=x1,x1^=x2;
c1260f1997-11-23Per Hedbor  pixelstep=(int)((x2-x1)*1024)/(int)(y2-y1);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  pos=x1*1024; for (;y1<=y2;y1++) { setpixel_test((pos+512)/1024,y1); pos+=pixelstep; } } else /* mostly horisontal line */ { if (x1>x2) y1^=y2,y2^=y1,y1^=y2, x1^=x2,x2^=x1,x1^=x2; pixelstep=((y2-y1)*1024)/(x2-x1); pos=y1*1024; for (;x1<=x2;x1++) { setpixel_test(x1,(pos+512)/1024); pos+=pixelstep; } } }
01b9212016-01-12Per Hedbor static inline rgb_group _pixel_apply_matrix(struct image *img,
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  int x,int y, int width,int height, rgbd_group *matrix, rgb_group default_rgb, double div) { rgb_group res; int i,j,bx,by,xp,yp; int sumr,sumg,sumb,r,g,b;
0dd2d42000-08-08Henrik Grubbström (Grubba)  double qdiv=1.0/div;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
cf3b7b1997-10-22Mirar (Pontus Hagland)  /* NOTE: * This code MUST be MT-SAFE! */ HIDE_GLOBAL_VARIABLES();
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  sumr=sumg=sumb=0; r=g=b=0; bx=width/2; by=height/2;
286fef1998-02-15Henrik Wallin 
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  for (xp=x-bx,i=0; i<width; i++,xp++) for (yp=y-by,j=0; j<height; j++,yp++) if (xp>=0 && xp<img->xsize && yp>=0 && yp<img->ysize) {
cc7cf42015-10-14Martin Nilsson  r += (int)(matrix[i+j*width].r*img->img[xp+yp*img->xsize].r); g += (int)(matrix[i+j*width].g*img->img[xp+yp*img->xsize].g); b += (int)(matrix[i+j*width].b*img->img[xp+yp*img->xsize].b);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) #ifdef MATRIX_DEBUG fprintf(stderr,"%d,%d %d,%d->%d,%d,%d\n", i,j,xp,yp, img->img[x+i+(y+j)*img->xsize].r, img->img[x+i+(y+j)*img->xsize].g, img->img[x+i+(y+j)*img->xsize].b); #endif
cc7cf42015-10-14Martin Nilsson  sumr += (int)matrix[i+j*width].r; sumg += (int)matrix[i+j*width].g; sumb += (int)matrix[i+j*width].b;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  }
13670c2015-05-25Martin Nilsson  if (sumr) res.r=testrange(default_rgb.r+r/(sumr*div));
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  else res.r=testrange(r*qdiv+default_rgb.r);
13670c2015-05-25Martin Nilsson  if (sumg) res.g=testrange(default_rgb.g+g/(sumg*div));
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  else res.g=testrange(g*qdiv+default_rgb.g);
87a4f92018-08-10Henrik Grubbström (Grubba)  if (sumb) res.b=testrange(default_rgb.b+b/(sumb*div));
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  else res.b=testrange(b*qdiv+default_rgb.b); #ifdef MATRIX_DEBUG fprintf(stderr,"->%d,%d,%d\n",res.r,res.g,res.b); #endif return res;
affb2e1997-10-21Henrik Grubbström (Grubba)  REVEAL_GLOBAL_VARIABLES();
ab6aec1997-02-11Fredrik Hübinette (Hubbe) }
e581ea2002-03-08Henrik Grubbström (Grubba) static void img_apply_matrix(struct image *dest, struct image *img, int width,int height, rgbd_group *matrix, double div, rgb_group default_rgb)
ab6aec1997-02-11Fredrik Hübinette (Hubbe) { rgb_group *d,*ip,*dp; rgbd_group *mp;
943c871998-03-23Mirar (Pontus Hagland)  int i,x,y,bx,by,ex,ey,yp;
286fef1998-02-15Henrik Wallin  int widthheight;
2f7d791997-03-25Mirar (Pontus Hagland)  double sumr,sumg,sumb;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  double qr,qg,qb;
636bc52014-11-01Martin Nilsson  double r=0,g=0,b=0;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  THREADS_ALLOW();
286fef1998-02-15Henrik Wallin  widthheight=width*height;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  sumr=sumg=sumb=0;
286fef1998-02-15Henrik Wallin  for (i=0; i<widthheight;) { sumr+=matrix[i].r; sumg+=matrix[i].g; sumb+=matrix[i++].b; }
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
fbefc52016-09-19Chris Angelico  if (!sumr) {sumr=1;} sumr*=div; qr=1.0/sumr; if (!sumg) {sumg=1;} sumg*=div; qg=1.0/sumg; if (!sumb) {sumb=1;} sumb*=div; qb=1.0/sumb;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  bx=width/2; by=height/2; ex=width-bx; ey=height-by;
13670c2015-05-25Martin Nilsson 
e375a11997-09-01Per Hedbor THREADS_DISALLOW();
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
20d0552009-04-22Martin Stjernholm  d=xalloc(sizeof(rgb_group)*img->xsize*img->ysize + RGB_VEC_PAD);
30bb592004-05-04Martin Nilsson 
e375a11997-09-01Per Hedbor THREADS_ALLOW();
ab6aec1997-02-11Fredrik Hübinette (Hubbe) CHRONO("apply_matrix, one"); for (y=by; y<img->ysize-ey; y++) {
635c3c1998-03-25Henrik Wallin  dp=d+y*img->xsize+bx;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  for (x=bx; x<img->xsize-ex; x++) { r=g=b=0; mp=matrix;
286fef1998-02-15Henrik Wallin  ip=img->img+(x-bx)+(y-by)*img->xsize;
7b2ae21998-02-17Fredrik Hübinette (Hubbe)  /* for (yp=y-by,j=0; j<height; j++,yp++) */
286fef1998-02-15Henrik Wallin #ifdef MATRIX_DEBUG j=-1; #endif for (yp=y-by; yp<height+y-by; yp++)
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  {
286fef1998-02-15Henrik Wallin #ifdef MATRIX_DEBUG j++; #endif
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  for (i=0; i<width; i++) { r+=ip->r*mp->r; g+=ip->g*mp->g; b+=ip->b*mp->b; #ifdef MATRIX_DEBUG fprintf(stderr,"%d,%d ->%d,%d,%d\n", i,j, img->img[x+i+(y+j)*img->xsize].r, img->img[x+i+(y+j)*img->xsize].g, img->img[x+i+(y+j)*img->xsize].b); #endif mp++; ip++; }
286fef1998-02-15Henrik Wallin  ip+=img->xsize-width;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } #ifdef MATRIX_DEBUG fprintf(stderr,"->%d,%d,%d\n",r/sumr,g/sumg,b/sumb); #endif
f6b3b52016-02-12Martin Nilsson  r=default_rgb.r+(int)(r*qr+0.5); dp->r=testrange(r); g=default_rgb.g+(int)(g*qg+0.5); dp->g=testrange(g); b=default_rgb.b+(int)(b*qb+0.5); dp->b=testrange(b);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  dp++; } } CHRONO("apply_matrix, two"); for (y=0; y<img->ysize; y++) { for (x=0; x<bx; x++) d[x+y*img->xsize]=_pixel_apply_matrix(img,x,y,width,height, matrix,default_rgb,div); for (x=img->xsize-ex; x<img->xsize; x++) d[x+y*img->xsize]=_pixel_apply_matrix(img,x,y,width,height, matrix,default_rgb,div); } for (x=0; x<img->xsize; x++) { for (y=0; y<by; y++) d[x+y*img->xsize]=_pixel_apply_matrix(img,x,y,width,height, matrix,default_rgb,div); for (y=img->ysize-ey; y<img->ysize; y++) d[x+y*img->xsize]=_pixel_apply_matrix(img,x,y,width,height, matrix,default_rgb,div); } CHRONO("apply_matrix, three"); if (dest->img) free(dest->img); *dest=*img; dest->img=d; THREADS_DISALLOW(); } /***************** methods *************************************/
2f7d791997-03-25Mirar (Pontus Hagland) /* **! method void create()
a63c362011-11-11Henrik Grubbström (Grubba) **! method void create(Image.Image image)
2f7d791997-03-25Mirar (Pontus Hagland) **! method void create(int xsize,int ysize)
db75b01999-05-20Mirar (Pontus Hagland) **! method void create(int xsize,int ysize,Color color)
2f7d791997-03-25Mirar (Pontus Hagland) **! method void create(int xsize,int ysize,int r,int g,int b) **! method void create(int xsize,int ysize,int r,int g,int b,int alpha)
8a4dbb1999-07-16Mirar (Pontus Hagland) ** **! method void create(int xsize,int ysize,string method,method ...)
2f7d791997-03-25Mirar (Pontus Hagland) **! Initializes a new image object.
8626fb1998-04-16Mirar (Pontus Hagland) **! **! <table><tr valign=center> **! <td><illustration> return lena()->clear(0,0,0); </illustration></td> **! <td><illustration> return lena()->clear(255,128,0); </illustration></td> **! </tr><tr>
02c2d21999-04-13Mirar (Pontus Hagland) **! <td>Image.Image<wbr>(XSIZE,YSIZE)</td> **! <td>Image.Image<wbr>(XSIZE,YSIZE,255,128,0)</td>
8626fb1998-04-16Mirar (Pontus Hagland) **! </tr></table>
8a4dbb1999-07-16Mirar (Pontus Hagland) **! **! The image can also be calculated from some special methods, **! for convinience: **! **! <pre>
a63c362011-11-11Henrik Grubbström (Grubba) **! channel modes; followed by a number of 1-char-per-pixel strings **! or image objects (where red channel will be used),
8a4dbb1999-07-16Mirar (Pontus Hagland) **! or an integer value: **! "grey" : make a grey image (needs 1 source: grey) **! "rgb" : make an rgb image (needs 3 sources: red, green and blue) **! "cmyk" : make a rgb image from cmyk (cyan, magenta, yellow, black)
fa63d92006-09-20Henrik Grubbström (Grubba) **! "adjusted_cmyk" : make a rgb image from cmyk **! (cyan, magenta, yellow, black) where the colors aren't **! 100% pure (C: 009ee0, M: e2007a, Y: ffec00, K: 1a171b).
fbee102016-02-03Martin Nilsson **! "raw" : make an image from a binary string
8a4dbb1999-07-16Mirar (Pontus Hagland) **! **! generate modes; all extra arguments is given to the
9a14cd1999-07-20Fredrik Hübinette (Hubbe) **! generation function. These has the same name as the method:
a63c362011-11-11Henrik Grubbström (Grubba) **! "<ref>test</ref>,"
8a4dbb1999-07-16Mirar (Pontus Hagland) **! "<ref>gradients</ref>" **! "<ref>noise</ref>" **! "<ref>turbulence</ref>" **! "<ref>random</ref>" **! "<ref>randomgrey</ref>" **! specials cases: **! "<ref>tuned_box</ref>" (coordinates is automatic) **! </pre> **!
a63c362011-11-11Henrik Grubbström (Grubba) **! arg Image.Image image **! Image to clone.
2f7d791997-03-25Mirar (Pontus Hagland) **! arg int xsize **! arg int ysize **! size of (new) image in pixels
db75b01999-05-20Mirar (Pontus Hagland) **! arg Color color
2f7d791997-03-25Mirar (Pontus Hagland) **! arg int r **! arg int g **! arg int b **! background color (will also be current color), **! default color is black **! arg int alpha **! default alpha channel value
02c2d21999-04-13Mirar (Pontus Hagland) **! see also: copy, clone, Image.Image
bb001b1997-10-12Mirar (Pontus Hagland) **! bugs
ab94bf1998-03-08Per Hedbor **! SIGSEGVS can be caused if the size is too big, due
a63c362011-11-11Henrik Grubbström (Grubba) **! to unchecked overflow -
bb001b1997-10-12Mirar (Pontus Hagland) **! (xsize*ysize)&MAXINT is small enough to allocate.
2f7d791997-03-25Mirar (Pontus Hagland) */
cd074b2016-02-03Martin Nilsson static int image_size_check(INT_TYPE xsize,INT_TYPE ysize)
87ac791998-04-16Mirar (Pontus Hagland) {
636bc52014-11-01Martin Nilsson  INT_TYPE a,b,c,d;
87ac791998-04-16Mirar (Pontus Hagland) 
f445e12017-12-28Martin Nilsson  if (xsize<0 || ysize<0) return 1;
87ac791998-04-16Mirar (Pontus Hagland) 
fa6e741998-04-17Mirar (Pontus Hagland)  if (xsize<0x20000000) xsize*=sizeof(rgb_group); else if (ysize<0x20000000) ysize*=sizeof(rgb_group); else return 1;
87ac791998-04-16Mirar (Pontus Hagland)  a=(xsize>>16); b=xsize&0xffff; c=(ysize>>16); d=ysize&0xffff;
fa6e741998-04-17Mirar (Pontus Hagland)  /* check for overflow */
87ac791998-04-16Mirar (Pontus Hagland)  if ((a&&c) || ((b*d>>16)&0xffff) + (a*d) + (b*c) > 0x7fff) return 1; return 0; }
cd074b2016-02-03Martin Nilsson static void img_read_get_channel(int arg,char *name,INT32 args, int *m,unsigned char **s,COLORTYPE *c)
8a4dbb1999-07-16Mirar (Pontus Hagland) { struct image *img; if (arg>args)
cd074b2016-02-03Martin Nilsson  SIMPLE_WRONG_NUM_ARGS_ERROR("create",1+arg);
017b572011-10-28Henrik Grubbström (Grubba)  switch (TYPEOF(sp[arg-args-1]))
8a4dbb1999-07-16Mirar (Pontus Hagland)  { case T_INT: *c=(COLORTYPE)sp[arg-args-1].u.integer; *s=c; *m=0; break; case T_STRING: if (sp[arg-args-1].u.string->size_shift)
cd074b2016-02-03Martin Nilsson  Pike_error("create: argument %d (%s channel): "
8a4dbb1999-07-16Mirar (Pontus Hagland)  "wide strings are not supported (yet)\n",arg+1,name); if (sp[arg-args-1].u.string->len!=THIS->xsize*THIS->ysize)
cd074b2016-02-03Martin Nilsson  Pike_error("create: argument %d (%s channel): "
125e522000-08-16Henrik Grubbström (Grubba)  "string is %ld characters, expected %ld\n", arg+1, name,
cc7cf42015-10-14Martin Nilsson  (long)sp[arg-args-1].u.string->len, (long)(THIS->xsize*THIS->ysize));
01a9572000-02-03Henrik Grubbström (Grubba)  *s=(unsigned char *)sp[arg-args-1].u.string->str;
8a4dbb1999-07-16Mirar (Pontus Hagland)  *m=1; break; case T_OBJECT:
13b5ed2014-05-26Per Hedbor  img=get_storage(sp[arg-args-1].u.object,image_program);
13670c2015-05-25Martin Nilsson  if (!img)
cd074b2016-02-03Martin Nilsson  Pike_error("create: argument %d (%s channel): "
8a4dbb1999-07-16Mirar (Pontus Hagland)  "not an image object\n",arg+1,name);
13670c2015-05-25Martin Nilsson  if (!img->img)
cd074b2016-02-03Martin Nilsson  Pike_error("create: argument %d (%s channel): "
8a4dbb1999-07-16Mirar (Pontus Hagland)  "uninitialized image object\n",arg+1,name);
13670c2015-05-25Martin Nilsson  if (img->xsize!=THIS->xsize || img->ysize!=THIS->ysize)
cd074b2016-02-03Martin Nilsson  Pike_error("create: argument %d (%s channel): "
cf734b2003-01-27Mirar (Pontus Hagland)  "size is wrong, %"PRINTPIKEINT"dx%"PRINTPIKEINT"d;" " expected %"PRINTPIKEINT"dx%"PRINTPIKEINT"d\n",
8a4dbb1999-07-16Mirar (Pontus Hagland)  arg+1,name,img->xsize,img->ysize, THIS->xsize,THIS->ysize); *s=(COLORTYPE*)img->img; *m=sizeof(rgb_group); break; default:
cd074b2016-02-03Martin Nilsson  Pike_error("create: argument %d (%s channel): "
8a4dbb1999-07-16Mirar (Pontus Hagland)  "illegal type\n",arg+1,name); } }
cd074b2016-02-03Martin Nilsson static void img_read_grey(INT32 args)
8a4dbb1999-07-16Mirar (Pontus Hagland) { int m1; COLORTYPE c1; unsigned char *s1; int n=THIS->xsize*THIS->ysize; rgb_group *d;
8153e72017-12-31Martin Nilsson  if(args==0) { push_int(190); img_read_get_channel(1,"grey",1,&m1,&s1,&c1); pop_stack(); } else img_read_get_channel(1,"grey",args,&m1,&s1,&c1);
dc8d022014-04-27Martin Nilsson  d=THIS->img=xalloc(sizeof(rgb_group)*n+RGB_VEC_PAD);
8a4dbb1999-07-16Mirar (Pontus Hagland)  switch (m1) {
21b12a2014-09-03Martin Nilsson  case 0: memset(d,c1,n*sizeof(rgb_group)); break;
8a4dbb1999-07-16Mirar (Pontus Hagland)  case 1: while (n--) { d->r=d->g=d->b=*(s1++); d++; } break; default: while (n--) { d->r=d->g=d->b=*s1; s1+=m1; d++; } } }
cd074b2016-02-03Martin Nilsson static void img_read_rgb(INT32 args)
8a4dbb1999-07-16Mirar (Pontus Hagland) { int m1,m2,m3; unsigned char *s1,*s2,*s3; int n=THIS->xsize*THIS->ysize; rgb_group *d,rgb; img_read_get_channel(1,"red",args,&m1,&s1,&(rgb.r)); img_read_get_channel(2,"green",args,&m2,&s2,&(rgb.g)); img_read_get_channel(3,"blue",args,&m3,&s3,&(rgb.b));
dc8d022014-04-27Martin Nilsson  d=THIS->img=xalloc(sizeof(rgb_group)*n+RGB_VEC_PAD);
8a4dbb1999-07-16Mirar (Pontus Hagland)  switch (m1|(m2<<4)|(m3<<4)) { case 0: /* all constant */ while (n--) *(d++)=rgb; break; case 0x111: /* all is one-byte */ while (n--) { d->r=*(s1++); d->g=*(s2++); d->b=*(s3++); d++; } break; case 0x333: /* all is rgb-source */ while (n--) { d->r=*s1; d->g=*s2; d->b=*s3; s1+=3; s2+=3; s3+=3; d++; } break; default: while (n--) { d->r=*s1; d->g=*s2; d->b=*s3; s1+=m1; s2+=m2; s3+=m3; d++; } break; } }
cd074b2016-02-03Martin Nilsson static void img_read_cmyk(INT32 args)
8a4dbb1999-07-16Mirar (Pontus Hagland) { int m1,m2,m3,m4; unsigned char *s1,*s2,*s3,*s4; int n=THIS->xsize*THIS->ysize; rgb_group *d,rgb; COLORTYPE k; img_read_get_channel(1,"cyan",args,&m1,&s1,&(rgb.r)); img_read_get_channel(2,"magenta",args,&m2,&s2,&(rgb.g)); img_read_get_channel(3,"yellow",args,&m3,&s3,&(rgb.b)); img_read_get_channel(4,"black",args,&m4,&s4,&k);
dc8d022014-04-27Martin Nilsson  d=THIS->img=xalloc(sizeof(rgb_group)*n+RGB_VEC_PAD);
8a4dbb1999-07-16Mirar (Pontus Hagland)  while (n--) {
e3dd8c2006-09-13Henrik Grubbström (Grubba)  d->r = ((COLORMAX-*s1)*(COLORMAX-*s4))/COLORMAX; d->g = ((COLORMAX-*s2)*(COLORMAX-*s4))/COLORMAX; d->b = ((COLORMAX-*s3)*(COLORMAX-*s4))/COLORMAX;
8a4dbb1999-07-16Mirar (Pontus Hagland)  s1+=m1; s2+=m2; s3+=m3; s4+=m4; d++; } }
fa63d92006-09-20Henrik Grubbström (Grubba) /* Ink colors for C, M, Y & K. */ #define CMYK_CR 0x00 #define CMYK_CG 0x9e #define CMYK_CB 0xe0 #define CMYK_MR 0xe2 #define CMYK_MG 0x00 #define CMYK_MB 0x7a #define CMYK_YR 0xff #define CMYK_YG 0xec #define CMYK_YB 0x00 #define CMYK_KR 0x1a #define CMYK_KG 0x17 #define CMYK_KB 0x1b
cd074b2016-02-03Martin Nilsson static void img_read_adjusted_cmyk(INT32 args)
fa63d92006-09-20Henrik Grubbström (Grubba) { int m1,m2,m3,m4; unsigned char *s1,*s2,*s3,*s4; int n=THIS->xsize*THIS->ysize; rgb_group *d,rgb; COLORTYPE k; img_read_get_channel(1,"cyan",args,&m1,&s1,&(rgb.r)); img_read_get_channel(2,"magenta",args,&m2,&s2,&(rgb.g)); img_read_get_channel(3,"yellow",args,&m3,&s3,&(rgb.b)); img_read_get_channel(4,"black",args,&m4,&s4,&k);
dc8d022014-04-27Martin Nilsson  d=THIS->img=xalloc(sizeof(rgb_group)*n+RGB_VEC_PAD);
fa63d92006-09-20Henrik Grubbström (Grubba)  while (n--) { unsigned char c = *s1; unsigned char m = *s2; unsigned char y = *s3; unsigned char k = *s4; unsigned long tmp; /* Mix the channels multiplicatively. */ tmp = 255*255; tmp *= 255*255-(255-CMYK_CR)*c; tmp /= 255*255; tmp *= 255*255-(255-CMYK_MR)*m; tmp /= 255*255; tmp *= 255*255-(255-CMYK_YR)*y; tmp /= 255*255; tmp *= 255*255-(255-CMYK_KR)*k; tmp /= 255*255*255; d->r = tmp; tmp = 255*255; tmp *= 255*255-(255-CMYK_CG)*c; tmp /= 255*255; tmp *= 255*255-(255-CMYK_MG)*m; tmp /= 255*255; tmp *= 255*255-(255-CMYK_YG)*y; tmp /= 255*255; tmp *= 255*255-(255-CMYK_KG)*k; tmp /= 255*255*255; d->g = tmp; tmp = 255*255; tmp *= 255*255-(255-CMYK_CB)*c; tmp /= 255*255; tmp *= 255*255-(255-CMYK_MB)*m; tmp /= 255*255; tmp *= 255*255-(255-CMYK_YB)*y; tmp /= 255*255; tmp *= 255*255-(255-CMYK_KB)*k; tmp /= 255*255*255; d->b = tmp; s1+=m1; s2+=m2; s3+=m3; s4+=m4; d++; } }
cd074b2016-02-03Martin Nilsson static void img_read_cmy(INT32 args)
8a4dbb1999-07-16Mirar (Pontus Hagland) { int m1,m2,m3; unsigned char *s1,*s2,*s3; int n=THIS->xsize*THIS->ysize; rgb_group *d,rgb; img_read_get_channel(1,"cyan",args,&m1,&s1,&(rgb.r)); img_read_get_channel(2,"magenta",args,&m2,&s2,&(rgb.g)); img_read_get_channel(3,"yellow",args,&m3,&s3,&(rgb.b));
dc8d022014-04-27Martin Nilsson  d=THIS->img=xalloc(sizeof(rgb_group)*n+RGB_VEC_PAD);
8a4dbb1999-07-16Mirar (Pontus Hagland)  while (n--) { d->r=COLORMAX-*s1; d->g=COLORMAX-*s2; d->b=COLORMAX-*s3; s1+=m1; s2+=m2; s3+=m3; d++; } } static void image_gradients(INT32 args); static void image_tuned_box(INT32 args); static void image_test(INT32 args);
fa63d92006-09-20Henrik Grubbström (Grubba) static struct pike_string *s_grey,*s_rgb,*s_cmyk,*s_adjusted_cmyk,*s_cmy;
aa67372004-05-03Martin Nilsson static struct pike_string *s_test,*s_gradients,*s_noise,*s_turbulence,
fbee102016-02-03Martin Nilsson  *s_random,*s_randomgrey,*s_tuned_box, *s_raw;
aa67372004-05-03Martin Nilsson 
cd074b2016-02-03Martin Nilsson static void image_create_method(INT32 args)
8a4dbb1999-07-16Mirar (Pontus Hagland) { struct image *img; if (!args)
cd074b2016-02-03Martin Nilsson  SIMPLE_WRONG_NUM_ARGS_ERROR("create",1);
8a4dbb1999-07-16Mirar (Pontus Hagland) 
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(sp[-args]) != T_STRING)
cd074b2016-02-03Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("create",1,"string");
8a4dbb1999-07-16Mirar (Pontus Hagland) 
b6a3e02004-05-04Martin Nilsson  MAKE_CONST_STRING(s_rgb,"rgb"); MAKE_CONST_STRING(s_cmyk,"cmyk");
fa63d92006-09-20Henrik Grubbström (Grubba)  MAKE_CONST_STRING(s_adjusted_cmyk,"adjusted_cmyk");
b6a3e02004-05-04Martin Nilsson  MAKE_CONST_STRING(s_cmy,"cmy"); MAKE_CONST_STRING(s_test,"test"); MAKE_CONST_STRING(s_gradients,"gradients"); MAKE_CONST_STRING(s_noise,"noise"); MAKE_CONST_STRING(s_turbulence,"turbulence"); MAKE_CONST_STRING(s_random,"random"); MAKE_CONST_STRING(s_randomgrey,"randomgrey"); MAKE_CONST_STRING(s_tuned_box,"tuned_box");
fbee102016-02-03Martin Nilsson  MAKE_CONST_STRING(s_raw,"raw");
8a4dbb1999-07-16Mirar (Pontus Hagland) 
f445e12017-12-28Martin Nilsson  if (THIS->xsize<=0 || THIS->ysize<=0) Pike_error("create: image size is too small\n");
8a4dbb1999-07-16Mirar (Pontus Hagland)  if (sp[-args].u.string==s_grey) {
ed7b192015-11-16Martin Nilsson  img_read_grey(args-1); return;
8a4dbb1999-07-16Mirar (Pontus Hagland)  } if (sp[-args].u.string==s_rgb) {
ed7b192015-11-16Martin Nilsson  img_read_rgb(args-1); return;
8a4dbb1999-07-16Mirar (Pontus Hagland)  } if (sp[-args].u.string==s_cmyk) {
ed7b192015-11-16Martin Nilsson  img_read_cmyk(args-1); return;
8a4dbb1999-07-16Mirar (Pontus Hagland)  }
fa63d92006-09-20Henrik Grubbström (Grubba)  if (sp[-args].u.string==s_adjusted_cmyk) {
ed7b192015-11-16Martin Nilsson  img_read_adjusted_cmyk(args-1); return;
fa63d92006-09-20Henrik Grubbström (Grubba)  }
8a4dbb1999-07-16Mirar (Pontus Hagland)  if (sp[-args].u.string==s_cmy) {
ed7b192015-11-16Martin Nilsson  img_read_cmy(args-1); return;
8a4dbb1999-07-16Mirar (Pontus Hagland)  } if (sp[-args].u.string==s_test) image_test(args-1);
aa67372004-05-03Martin Nilsson  else if (sp[-args].u.string==s_gradients) { if(args<2) { push_int(THIS->xsize/2); push_int(0); push_int(0); push_int(0); push_int(0); f_aggregate(5); push_int(THIS->xsize/2); push_int(THIS->ysize); push_int(255); push_int(255); push_int(255); f_aggregate(5); args+=2; } image_gradients(args-1); }
8a4dbb1999-07-16Mirar (Pontus Hagland)  else if (sp[-args].u.string==s_noise) image_noise(args-1); else if (sp[-args].u.string==s_turbulence) image_turbulence(args-1); else if (sp[-args].u.string==s_random) image_random(args-1); else if (sp[-args].u.string==s_randomgrey) image_randomgrey(args-1); else if (sp[-args].u.string==s_tuned_box) { if (args<2) push_int(0);
dc8d022014-04-27Martin Nilsson  THIS->img=
fbee102016-02-03Martin Nilsson  xalloc(sizeof(rgb_group)*THIS->xsize*THIS->ysize+RGB_VEC_PAD);
aa67372004-05-03Martin Nilsson 
8a4dbb1999-07-16Mirar (Pontus Hagland)  if (args>2) pop_n_elems(args-2); push_int(0); stack_swap(); push_int(0); stack_swap(); push_int(THIS->xsize-1); stack_swap(); push_int(THIS->ysize-1); stack_swap(); image_tuned_box(5);
aa67372004-05-03Martin Nilsson  return;
8a4dbb1999-07-16Mirar (Pontus Hagland)  }
fbee102016-02-03Martin Nilsson  else if (sp[-args].u.string==s_raw) {
11a33b2017-04-23Henrik Grubbström (Grubba)  struct pike_string *s; int size; char *dst;
fbee102016-02-03Martin Nilsson  if( args!=2 || TYPEOF(sp[1-args])!=T_STRING || sp[1-args].u.string->size_shift) SIMPLE_ARG_TYPE_ERROR("create",2,"string(8bit)");
11a33b2017-04-23Henrik Grubbström (Grubba)  s = sp[1-args].u.string; size = sizeof(rgb_group)*THIS->xsize*THIS->ysize;
fbee102016-02-03Martin Nilsson  if( s->len > size ) SIMPLE_ARG_ERROR("create",2,"String size too large."); THIS->img = xalloc(size+RGB_VEC_PAD);
11a33b2017-04-23Henrik Grubbström (Grubba)  dst = (char*)THIS->img;
fbee102016-02-03Martin Nilsson  memcpy(THIS->img, s->str, s->len); memset(dst+s->len, 0, size - s->len); return; }
13670c2015-05-25Martin Nilsson  else
cd074b2016-02-03Martin Nilsson  Pike_error("create: unknown method\n");
8a4dbb1999-07-16Mirar (Pontus Hagland)  /* on stack: "string" image */ /* want: put that image in this, crap that image */
13b5ed2014-05-26Per Hedbor  img=get_storage(sp[-1].u.object,image_program);
8a4dbb1999-07-16Mirar (Pontus Hagland)  THIS->img=img->img; img->img=NULL; }
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void image_create(INT32 args) {
a63c362011-11-11Henrik Grubbström (Grubba)  if ((args >= 1) && (TYPEOF(sp[-args]) == T_OBJECT)) { struct object *o = sp[-args].u.object; pop_n_elems(args - 1); apply(o, "xsize", 0); apply(o, "ysize", 0); image_create(2); image_paste(1);
6bea282017-12-28Martin Nilsson  pop_stack();
a63c362011-11-11Henrik Grubbström (Grubba)  return; }
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (args<2) return;
391ac52018-08-05Martin Nilsson  get_all_args(NULL, args, "%i%i", &THIS->xsize, &THIS->ysize);
cd074b2016-02-03Martin Nilsson  if (image_size_check(THIS->xsize,THIS->ysize)) Pike_error("create: image too small or large (>2Gpixels)\n");
87ac791998-04-16Mirar (Pontus Hagland) 
ef31512018-02-21Martin Nilsson  if (THIS->img) { free(THIS->img); THIS->img=NULL; }
fc60b92017-12-28Martin Nilsson  MAKE_CONST_STRING(s_grey,"grey");
017b572011-10-28Henrik Grubbström (Grubba)  if (args>2 && TYPEOF(sp[2-args]) == T_STRING &&
fc60b92017-12-28Martin Nilsson  (!image_color_svalue(sp+2-args,&(THIS->rgb)) || sp[2-args].u.string==s_grey))
8a4dbb1999-07-16Mirar (Pontus Hagland)  /* don't try method "lightblue", etc */ {
6bea282017-12-28Martin Nilsson  struct svalue *stack = Pike_sp; image_create_method(args-2); pop_n_elems(args+Pike_sp-stack); return;
8a4dbb1999-07-16Mirar (Pontus Hagland)  } else
6bea282017-12-28Martin Nilsson  {
bf4d372018-02-16Martin Nilsson  getrgb(THIS,2,args,args,"create");
6bea282017-12-28Martin Nilsson  pop_n_elems(args); }
8a4dbb1999-07-16Mirar (Pontus Hagland) 
20d0552009-04-22Martin Stjernholm  THIS->img=xalloc(sizeof(rgb_group)*THIS->xsize*THIS->ysize+RGB_VEC_PAD);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  img_clear(THIS->img,THIS->rgb,THIS->xsize*THIS->ysize); }
2f7d791997-03-25Mirar (Pontus Hagland) /* **! method object clone() **! method object clone(int xsize,int ysize) **! method object clone(int xsize,int ysize,int r,int g,int b) **! method object clone(int xsize,int ysize,int r,int g,int b,int alpha) **! Copies to or initialize a new image object.
8626fb1998-04-16Mirar (Pontus Hagland) **! **! <table><tr valign=center> **! <td><illustration> return lena(); </illustration></td> **! <td><illustration> return lena()->clone(); </illustration></td> **! <td><illustration> return lena()->clone(50,50); </illustration></td> **! </tr><tr> **! <td>original</td> **! <td>clone</td> **! <td>clone(50,50)</td> **! </tr></table>
13670c2015-05-25Martin Nilsson **!
2f7d791997-03-25Mirar (Pontus Hagland) **! returns the new object **! arg int xsize **! arg int ysize **! size of (new) image in pixels, called image **! is cropped to that size **! arg int r **! arg int g **! arg int b
13670c2015-05-25Martin Nilsson **! current color of the new image, **! default is black.
2f7d791997-03-25Mirar (Pontus Hagland) **! Will also be the background color if the cloned image **! is empty (no drawing area made). **! arg int alpha **! new default alpha channel value **! see also: copy, create */
7d60af2004-05-19Martin Nilsson static void my_free_object(struct object *o) { free_object(o); }
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void image_clone(INT32 args) { struct object *o; struct image *img;
7d60af2004-05-19Martin Nilsson  ONERROR err;
ef31512018-02-21Martin Nilsson  INT_TYPE x,y;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
ef31512018-02-21Martin Nilsson  if( args )
391ac52018-08-05Martin Nilsson  get_all_args(NULL, args, "%+%+", &x, &y);
ef31512018-02-21Martin Nilsson  else { x = THIS->xsize; y = THIS->ysize; } if( x<0 ) x = 1; if( y<0 ) y = 1;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
e709751997-03-12Fredrik Hübinette (Hubbe)  o=clone_object(image_program,0);
7d60af2004-05-19Martin Nilsson  SET_ONERROR(err, my_free_object, o);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  img=(struct image*)(o->storage); *img=*THIS;
bf4d372018-02-16Martin Nilsson  getrgb(img,2,args,args,"clone");
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
ef31512018-02-21Martin Nilsson  img->xsize = x; img->ysize = y; img->img=xalloc(sizeof(rgb_group)*x*y+RGB_VEC_PAD);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (THIS->img) {
ef31512018-02-21Martin Nilsson  if (x==THIS->xsize && y==THIS->ysize) memcpy(img->img,THIS->img,sizeof(rgb_group)*x*y);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  else
ef31512018-02-21Martin Nilsson  img_crop(img,THIS,0,0,x-1,y-1);
13670c2015-05-25Martin Nilsson 
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } else
ef31512018-02-21Martin Nilsson  img_clear(img->img,img->rgb,x*y);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
7d60af2004-05-19Martin Nilsson  UNSET_ONERROR(err);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  pop_n_elems(args); push_object(o); }
2f7d791997-03-25Mirar (Pontus Hagland)  /*
ed7b192015-11-16Martin Nilsson **! method object clear() **! method object clear(int r,int g,int b) **! method object clear(int r,int g,int b,int alpha)
2f7d791997-03-25Mirar (Pontus Hagland) **! gives a new, cleared image with the same size of drawing area
8626fb1998-04-16Mirar (Pontus Hagland) **! **! <table><tr valign=center> **! <td><illustration> return lena(); </illustration></td> **! <td><illustration> return lena()->clear(0,128,255); </illustration></td> **! </tr><tr> **! <td>original</td> **! <td>->clear<wbr>(0,128,255)</td> **! </tr></table> **!
2f7d791997-03-25Mirar (Pontus Hagland) **! arg int r **! arg int g **! arg int b **! color of the new image **! arg int alpha **! new default alpha channel value **! see also: copy, clone */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void image_clear(INT32 args) { struct object *o; struct image *img;
e709751997-03-12Fredrik Hübinette (Hubbe)  o=clone_object(image_program,0);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  img=(struct image*)(o->storage); *img=*THIS;
bf4d372018-02-16Martin Nilsson  getrgb(img,0,args,args,"clear");
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
20d0552009-04-22Martin Stjernholm  img->img=malloc(sizeof(rgb_group)*img->xsize*img->ysize+RGB_VEC_PAD);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (!img->img) { free_object(o);
1a597d2005-08-15Henrik Grubbström (Grubba)  SIMPLE_OUT_OF_MEMORY_ERROR("clear",
20d0552009-04-22Martin Stjernholm  sizeof(rgb_group)*img->xsize*img->ysize+RGB_VEC_PAD);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } img_clear(img->img,img->rgb,img->xsize*img->ysize); pop_n_elems(args); push_object(o); }
2f7d791997-03-25Mirar (Pontus Hagland) /* **! method object copy() **! method object copy(int x1,int y1,int x2,int y2) **! method object copy(int x1,int y1,int x2,int y2,int r,int g,int b) **! method object copy(int x1,int y1,int x2,int y2,int r,int g,int b,int alpha) **! Copies this part of the image. The requested area can
13670c2015-05-25Martin Nilsson **! be smaller, giving a cropped image, or bigger -
2f7d791997-03-25Mirar (Pontus Hagland) **! the new area will be filled with the given or current color. **!
8626fb1998-04-16Mirar (Pontus Hagland) **! <table><tr valign=center> **! <td><illustration> return lena(); </illustration></td> **! <td><illustration> return lena()->copy(5,5,lena()->xsize()-6,lena()->ysize()-6); </illustration></td> **! <td><illustration> return lena()->copy(-5,-5,lena()->xsize()+4,lena()->ysize()+4,10,75,10); </illustration></td> **! </tr><tr> **! <td>original</td> **! <td>->copy<wbr>(5,5,<wbr>XSIZE-6,YSIZE-6)</td> **! <td>->copy<wbr>(-5,-5,<wbr>XSIZE+4,YSIZE+4,<wbr>10,75,10)</td> **! </tr></table> **!
2f7d791997-03-25Mirar (Pontus Hagland) **! returns a new image object **! **! note
13670c2015-05-25Martin Nilsson **! <ref>clone</ref>(void) and <ref>copy</ref>(void) does the same
2f7d791997-03-25Mirar (Pontus Hagland) **! operation **! **! arg int x1 **! arg int y1 **! arg int x2 **! arg int y2 **! The requested new area. Default is the old image size. **! arg int r **! arg int g **! arg int b **! color of the new image **! arg int alpha **! new default alpha channel value **! see also: clone, autocrop */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void image_copy(INT32 args) { struct object *o; struct image *img;
ef31512018-02-21Martin Nilsson  int x1,y1,x2,y2;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (!args) {
e709751997-03-12Fredrik Hübinette (Hubbe)  o=clone_object(image_program,0);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (THIS->img) img_clone((struct image*)o->storage,THIS); pop_n_elems(args); push_object(o); return; }
ef31512018-02-21Martin Nilsson 
391ac52018-08-05Martin Nilsson  get_all_args(NULL, args, "%d%d%d%d", &x1,&y1,&x2,&y2);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
48b1512018-02-22Martin Nilsson  CHECK_INIT();
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
bf4d372018-02-16Martin Nilsson  getrgb(THIS,4,args,args,"copy");
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
e709751997-03-12Fredrik Hübinette (Hubbe)  o=clone_object(image_program,0);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  img=(struct image*)(o->storage);
ef31512018-02-21Martin Nilsson  img_crop(img,THIS, x1,y1,x2,y2);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  pop_n_elems(args); push_object(o); }
2f7d791997-03-25Mirar (Pontus Hagland) /* **! method object change_color(int tor,int tog,int tob)
aa67372004-05-03Martin Nilsson **! method object change_color(int fromr,int fromg,int fromb,int tor,int tog,int tob) **! Changes one color (exact match) to another. **! If non-exact-match is preferred, check <ref>distancesq</ref>
2f7d791997-03-25Mirar (Pontus Hagland) **! and <ref>paste_alpha_color</ref>. **! returns a new (the destination) image object **! **! arg int tor **! arg int tog **! arg int tob **! destination color and next current color **! arg int fromr **! arg int fromg **! arg int fromb **! source color, default is current color */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 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;
db75b01999-05-20Mirar (Pontus Hagland)  int arg;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
48b1512018-02-22Martin Nilsson  CHECK_INIT();
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
13670c2015-05-25Martin Nilsson  to=THIS->rgb;
bf4d372018-02-16Martin Nilsson  if (!(arg=getrgb(THIS,0,args,3,"change_color")))
06bd612016-01-26Martin Nilsson  SIMPLE_WRONG_NUM_ARGS_ERROR("Image",1);
db75b01999-05-20Mirar (Pontus Hagland)  from=THIS->rgb;
bf4d372018-02-16Martin Nilsson  if (getrgb(THIS,arg,args,args,"change_color"))
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  to=THIS->rgb;
13670c2015-05-25Martin Nilsson 
e709751997-03-12Fredrik Hübinette (Hubbe)  o=clone_object(image_program,0);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  img=(struct image*)(o->storage); *img=*THIS;
20d0552009-04-22Martin Stjernholm  if (!(img->img=malloc(sizeof(rgb_group)*img->xsize*img->ysize+RGB_VEC_PAD)))
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  { free_object(o);
1a597d2005-08-15Henrik Grubbström (Grubba)  SIMPLE_OUT_OF_MEMORY_ERROR("change_color",
20d0552009-04-22Martin Stjernholm  sizeof(rgb_group)*img->xsize*img->ysize+RGB_VEC_PAD);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } left=THIS->xsize*THIS->ysize; s=THIS->img; d=img->img; while (left--) {
7192821997-11-23Per Hedbor  if (color_equal(*s,from))
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  *d=to; else *d=*s; d++; s++; } pop_n_elems(args); push_object(o); }
2f7d791997-03-25Mirar (Pontus Hagland) /* **! method object autocrop() **! method object autocrop(int border)
7383191999-06-21Mirar (Pontus Hagland) **! method object autocrop(int border,Color color)
2f7d791997-03-25Mirar (Pontus Hagland) **! method object autocrop(int border,int left,int right,int top,int bottom)
7383191999-06-21Mirar (Pontus Hagland) **! method object autocrop(int border,int left,int right,int top,int bottom,Color color) **! method array(int) find_autocrop() **! method array(int) find_autocrop(int border) **! method array(int) find_autocrop(int border,int left,int right,int top,int bottom)
4d27b62017-08-11Chris Angelico **! Removes "unnecessary" borders around the image, adds one of
2f7d791997-03-25Mirar (Pontus Hagland) **! its own if wanted to, in selected directions. **!
4d27b62017-08-11Chris Angelico **! "Unnecessary" is all pixels that are equal -- ie if all the same pixels
2f7d791997-03-25Mirar (Pontus Hagland) **! to the left are the same color, that column of pixels are removed. **!
7383191999-06-21Mirar (Pontus Hagland) **! The find_autocrop() function simply returns x1,y1,x2,y2 for the **! kept area. (This can be used with <ref>copy</ref> later.) **!
2f7d791997-03-25Mirar (Pontus Hagland) **! returns the new image object **! **! arg int border **! added border size in pixels **! arg int left **! arg int right **! arg int top **! arg int bottom
13670c2015-05-25Martin Nilsson **! which borders to scan and cut the image;
4d27b62017-08-11Chris Angelico **! a typical example is removing the top and bottom unnecessary
2f7d791997-03-25Mirar (Pontus Hagland) **! pixels:
b9284c1997-04-09Mirar (Pontus Hagland) **! <pre>img=img->autocrop(0, 0,0,1,1);</pre>
7383191999-06-21Mirar (Pontus Hagland) **!
2f7d791997-03-25Mirar (Pontus Hagland) **! see also: copy */
01b9212016-01-12Per Hedbor static inline int try_autocrop_vertical(struct image *this,
7383191999-06-21Mirar (Pontus Hagland)  INT32 x,INT32 y,INT32 y2, INT32 rgb_set,rgb_group *rgb) { if (!rgb_set) *rgb=pixel(THIS,x,y); for (;y<=y2; y++) if (pixel(this,x,y).r!=rgb->r || pixel(this,x,y).g!=rgb->g || pixel(this,x,y).b!=rgb->b) return 0; return 1; }
2f7d791997-03-25Mirar (Pontus Hagland) 
01b9212016-01-12Per Hedbor static inline int try_autocrop_horisontal(struct image *this,
7383191999-06-21Mirar (Pontus Hagland)  INT32 y,INT32 x,INT32 x2, INT32 rgb_set,rgb_group *rgb) { if (!rgb_set) *rgb=pixel(THIS,x,y); for (;x<=x2; x++) if (pixel(this,x,y).r!=rgb->r || pixel(this,x,y).g!=rgb->g || pixel(this,x,y).b!=rgb->b) return 0; return 1; } void img_find_autocrop(struct image *this,
b875ff2001-03-04Mirar (Pontus Hagland)  INT32 *px1,INT32 *py1,INT32 *px2,INT32 *py2,
7383191999-06-21Mirar (Pontus Hagland)  int border, int left,int right, int top,int bottom, int rgb_set, rgb_group rgb) { int done; INT32 x1=0,y1=0,x2=this->xsize-1,y2=this->ysize-1; while (x2>x1 && y2>y1) { done=0; if (left &&
13670c2015-05-25Martin Nilsson  try_autocrop_vertical(this,x1,y1,y2,rgb_set,&rgb))
7383191999-06-21Mirar (Pontus Hagland)  x1++,done=rgb_set=1; if (right &&
13670c2015-05-25Martin Nilsson  x2>x1 && try_autocrop_vertical(this,x2,y1,y2,rgb_set,&rgb))
7383191999-06-21Mirar (Pontus Hagland)  x2--,done=rgb_set=1; if (top &&
13670c2015-05-25Martin Nilsson  try_autocrop_horisontal(this,y1,x1,x2,rgb_set,&rgb))
7383191999-06-21Mirar (Pontus Hagland)  y1++,done=rgb_set=1; if (bottom &&
13670c2015-05-25Martin Nilsson  y2>y1 && try_autocrop_horisontal(this,y2,x1,x2,rgb_set,&rgb))
7383191999-06-21Mirar (Pontus Hagland)  y2--,done=rgb_set=1; if (!done) break; } x2+=border; y2+=border; x1-=border; y1-=border; if (x2<x1||y2<y1) px1[0]=py1[0]=0,px2[0]=py2[0]=-1; else px1[0]=x1,py1[0]=y1,px2[0]=x2,py2[0]=y2; } static void image_find_autocrop(INT32 args)
ab6aec1997-02-11Fredrik Hübinette (Hubbe) {
ef31512018-02-21Martin Nilsson  int border=0,x1,y1,x2,y2;
7383191999-06-21Mirar (Pontus Hagland)  rgb_group rgb={0,0,0};
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  int left=1,right=1,top=1,bottom=1;
ef31512018-02-21Martin Nilsson  if (args)
391ac52018-08-05Martin Nilsson  get_all_args(NULL, args, "%d.%d%d%d%d",
ef31512018-02-21Martin Nilsson  &border, &left, &right, &top, &bottom);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
48b1512018-02-22Martin Nilsson  CHECK_INIT();
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
7383191999-06-21Mirar (Pontus Hagland)  img_find_autocrop(THIS,&x1,&y1,&x2,&y2, border,left,right,top,bottom,0,rgb);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
7383191999-06-21Mirar (Pontus Hagland)  pop_n_elems(args); push_int(x1); push_int(y1); push_int(x2); push_int(y2); f_aggregate(4); } void image_autocrop(INT32 args) { INT32 border=0,x1,y1,x2,y2;
340c562001-06-13Henrik Grubbström (Grubba)  int rgb_set=0;
7383191999-06-21Mirar (Pontus Hagland)  struct object *o; struct image *img; int left=1,right=1,top=1,bottom=1;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
7383191999-06-21Mirar (Pontus Hagland)  if (args>=5)
bf4d372018-02-16Martin Nilsson  getrgb(THIS,5,args,args,"autocrop");
13670c2015-05-25Martin Nilsson  else
bf4d372018-02-16Martin Nilsson  getrgb(THIS,1,args,args,"autocrop");
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
7383191999-06-21Mirar (Pontus Hagland)  image_find_autocrop(args); args++;
13670c2015-05-25Martin Nilsson 
7383191999-06-21Mirar (Pontus Hagland)  x1=sp[-1].u.array->item[0].u.integer; y1=sp[-1].u.array->item[1].u.integer; x2=sp[-1].u.array->item[2].u.integer; y2=sp[-1].u.array->item[3].u.integer; push_object(o=clone_object(image_program,0)); img=(struct image*)(o->storage); if (x2==-1 && y2==-1 && x1==0 && y1==0) /* magic, equal image */ img_crop(img,THIS,0,0,0,0); else img_crop(img,THIS,x1,y1,x2,y2);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) }
2f7d791997-03-25Mirar (Pontus Hagland) /* **! method object setcolor(int r,int g,int b) **! method object setcolor(int r,int g,int b,int alpha) **! set the current color **! **! returns the object called **! **! arg int r **! arg int g **! arg int b **! new color **! arg int alpha **! new alpha value */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void image_setcolor(INT32 args) { if (args<3)
ef31512018-02-21Martin Nilsson  SIMPLE_WRONG_NUM_ARGS_ERROR("setcolor", 3);
bf4d372018-02-16Martin Nilsson  getrgb(THIS,0,args,args,"setcolor");
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) }
2f7d791997-03-25Mirar (Pontus Hagland) /* **! method object setpixel(int x,int y)
071bf62003-12-01Martin Nilsson **! method object setpixel(int x,int y,Image.Color c)
2f7d791997-03-25Mirar (Pontus Hagland) **! method object setpixel(int x,int y,int r,int g,int b) **! method object setpixel(int x,int y,int r,int g,int b,int alpha)
13670c2015-05-25Martin Nilsson **!
8626fb1998-04-16Mirar (Pontus Hagland) **! <table><tr valign=center> **! <td><illustration> return lena(); </illustration></td> **! <td><illustration> return lena()->copy()->setpixel(10,10,255,0,0); </illustration></td> **! </tr><tr> **! <td>original</td> **! <td>->setpixel<wbr>(10,10,<wbr>255,0,0)</td> **! </tr></table> **!
2f7d791997-03-25Mirar (Pontus Hagland) **! returns the object called **! **! arg int x **! arg int y **! position of the pixel **! arg int r **! arg int g **! arg int b **! color **! arg int alpha **! alpha value */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void image_setpixel(INT32 args) {
ef31512018-02-21Martin Nilsson  int x,y;
391ac52018-08-05Martin Nilsson  get_all_args(NULL, args, "%d%d", &x, &y);
bf4d372018-02-16Martin Nilsson  getrgb(THIS,2,args,args,"setpixel");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (!THIS->img) return; setpixel_test(x,y); pop_n_elems(args);
d6ac731998-04-20Henrik Grubbström (Grubba)  ref_push_object(THISOBJ);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) }
2f7d791997-03-25Mirar (Pontus Hagland) /* **! method array(int) getpixel(int x,int y)
13670c2015-05-25Martin Nilsson **!
2f7d791997-03-25Mirar (Pontus Hagland) **! returns color of the requested pixel -- ({int red,int green,int blue}) **! **! arg int x **! arg int y **! position of the pixel */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void image_getpixel(INT32 args) {
ef31512018-02-21Martin Nilsson  int x,y;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  rgb_group rgb;
391ac52018-08-05Martin Nilsson  get_all_args(NULL, args, "%d%d", &x, &y);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (!THIS->img) return; if(x<0||y<0||x>=THIS->xsize||y>=THIS->ysize) rgb=THIS->rgb; else rgb=pixel(THIS,x,y); pop_n_elems(args); push_int(rgb.r); push_int(rgb.g); push_int(rgb.b); f_aggregate(3); }
2f7d791997-03-25Mirar (Pontus Hagland) /* **! method object line(int x1,int y1,int x2,int y2) **! method object line(int x1,int y1,int x2,int y2,int r,int g,int b) **! method object line(int x1,int y1,int x2,int y2,int r,int g,int b,int alpha) **! Draws a line on the image. The line is <i>not</i> antialiased.
8626fb1998-04-16Mirar (Pontus Hagland) **! **! <table><tr valign=center> **! <td><illustration> return lena(); </illustration></td> **! <td><illustration> return lena()->copy()->line(50,10,10,50,255,0,0); </illustration></td> **! </tr><tr> **! <td>original</td> **! <td>->line<wbr>(50,10,<wbr>10,50,<wbr>255,0,0)</td> **! </tr></table>
13670c2015-05-25Martin Nilsson **!
2f7d791997-03-25Mirar (Pontus Hagland) **! returns the object called **! **! arg int x1 **! arg int y1 **! arg int x2 **! arg int y2 **! line endpoints **! arg int r **! arg int g **! arg int b **! color **! arg int alpha **! alpha value */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void image_line(INT32 args) {
ef31512018-02-21Martin Nilsson  int x1,y1,x2,y2;
391ac52018-08-05Martin Nilsson  get_all_args(NULL, args, "%d%d%d%d", &x1,&y1,&x2,&y2);
bf4d372018-02-16Martin Nilsson  getrgb(THIS,4,args,args,"line");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (!THIS->img) return;
ef31512018-02-21Martin Nilsson  img_line(x1, y1, x2, y2);
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) }
2f7d791997-03-25Mirar (Pontus Hagland) /* **! method object box(int x1,int y1,int x2,int y2) **! method object box(int x1,int y1,int x2,int y2,int r,int g,int b) **! method object box(int x1,int y1,int x2,int y2,int r,int g,int b,int alpha)
13670c2015-05-25Martin Nilsson **! Draws a filled rectangle on the image. **!
8626fb1998-04-16Mirar (Pontus Hagland) **! <table><tr valign=center> **! <td><illustration> return lena(); </illustration></td> **! <td><illustration> return lena()->copy()->box(40,10,10,80,0,255,0); </illustration></td>
1e725e2003-07-23Martin Nilsson **! <td><illustration> return lena()->copy()->box(40,10,10,80,255,0,0,75); </illustration></td>
8626fb1998-04-16Mirar (Pontus Hagland) **! </tr><tr> **! <td>original</td> **! <td>->box<wbr>(40,10,<wbr>10,80,<wbr>0,255,0)</td>
1e725e2003-07-23Martin Nilsson **! <td>->box<wbr>(40,10,<wbr>10,80,<wbr>255,0,0,75)</td>
8626fb1998-04-16Mirar (Pontus Hagland) **! </tr></table>
13670c2015-05-25Martin Nilsson **!
2f7d791997-03-25Mirar (Pontus Hagland) **! returns the object called **! **! arg int x1 **! arg int y1 **! arg int x2 **! arg int y2 **! box corners **! arg int r **! arg int g **! arg int b **! color of the box **! arg int alpha
13670c2015-05-25Martin Nilsson **! alpha value
2f7d791997-03-25Mirar (Pontus Hagland) */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void image_box(INT32 args) {
118f582018-02-22Martin Nilsson  int x1,y1,x2,y2;
391ac52018-08-05Martin Nilsson  get_all_args(NULL, args, "%d%d%d%d", &x1, &y1, &x2, &y2);
bf4d372018-02-16Martin Nilsson  getrgb(THIS,4,args,args,"box");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (!THIS->img) return;
118f582018-02-22Martin Nilsson  img_box(x1, y1, x2, y2);
d6ac731998-04-20Henrik Grubbström (Grubba)  ref_push_object(THISOBJ);
a92ad62003-10-13Henrik Grubbström (Grubba)  stack_pop_n_elems_keep_top(args);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) }
2f7d791997-03-25Mirar (Pontus Hagland) /* **! method object circle(int x,int y,int rx,int ry) **! method object circle(int x,int y,int rx,int ry,int r,int g,int b) **! method object circle(int x,int y,int rx,int ry,int r,int g,int b,int alpha)
8626fb1998-04-16Mirar (Pontus Hagland) **! Draws a circle on the image. The circle is <i>not</i> antialiased.
13670c2015-05-25Martin Nilsson **!
8626fb1998-04-16Mirar (Pontus Hagland) **! <table><tr valign=center> **! <td><illustration> return lena(); </illustration></td> **! <td><illustration> return lena()->copy()->circle(50,50,30,50,255,255); </illustration></td> **! </tr><tr> **! <td>original</td> **! <td>->circle<wbr>(50,50,<wbr>30,50,<wbr>0,255,255)</td> **! </tr></table>
13670c2015-05-25Martin Nilsson **!
2f7d791997-03-25Mirar (Pontus Hagland) **! returns the object called **! **! arg int x **! arg int y **! circle center **! arg int rx **! arg int ry **! circle radius in pixels **! arg int r **! arg int g **! arg int b **! color **! arg int alpha **! alpha value */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void image_circle(INT32 args) {
118f582018-02-22Martin Nilsson  int x,y,rx,ry;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  INT32 i;
391ac52018-08-05Martin Nilsson  get_all_args(NULL, args, "%d%d%d%d", &x,&y,&rx,&ry);
bf4d372018-02-16Martin Nilsson  getrgb(THIS,4,args,args,"circle");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (!THIS->img) return; for (i=0; i<CIRCLE_STEPS; i++) img_line(x+circle_sin_mul(i,rx), y+circle_cos_mul(i,ry), x+circle_sin_mul(i+1,rx), y+circle_cos_mul(i+1,ry));
13670c2015-05-25Martin Nilsson 
b6f4d41997-03-24Mirar (Pontus Hagland)  pop_n_elems(args);
d6ac731998-04-20Henrik Grubbström (Grubba)  ref_push_object(THISOBJ);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) }
01b9212016-01-12Per Hedbor static inline int image_color_svalue_rgba(struct svalue *s,
d158881999-07-21Mirar (Pontus Hagland)  rgba_group *d)
ab6aec1997-02-11Fredrik Hübinette (Hubbe) {
d158881999-07-21Mirar (Pontus Hagland)  rgb_group rgb;
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(*s) == T_ARRAY && s->u.array->size>=4)
8a4dbb1999-07-16Mirar (Pontus Hagland)  {
751dfa2004-05-14Martin Nilsson  struct array *a = s->u.array; if( (a->type_field!=BIT_INT) && (array_fix_type_field(a)!=BIT_INT) ) return 0; d->r=(COLORTYPE)a->item[0].u.integer; d->g=(COLORTYPE)a->item[1].u.integer; d->b=(COLORTYPE)a->item[2].u.integer; d->alpha=(COLORTYPE)a->item[3].u.integer; return 1;
8a4dbb1999-07-16Mirar (Pontus Hagland)  }
d158881999-07-21Mirar (Pontus Hagland)  else if (image_color_svalue(s,&rgb))
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  {
d158881999-07-21Mirar (Pontus Hagland)  d->r=rgb.r; d->g=rgb.g; d->b=rgb.b; d->alpha=0; return 1;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  }
13670c2015-05-25Martin Nilsson  return 0;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) }
01b9212016-01-12Per Hedbor static inline void
1482aa1997-11-23Per Hedbor  add_to_rgbda_sum_with_factor(rgbda_group *sum, rgba_group rgba,
8a80a82000-08-08Henrik Grubbström (Grubba)  double factor)
ab6aec1997-02-11Fredrik Hübinette (Hubbe) {
d9ae471997-10-07Henrik Grubbström (Grubba)  /* NOTE:
1482aa1997-11-23Per Hedbor  * This code MUST be MT-SAFE! (but also fast /per)
d9ae471997-10-07Henrik Grubbström (Grubba)  */
1482aa1997-11-23Per Hedbor /* HIDE_GLOBAL_VARIABLES(); */
cc7cf42015-10-14Martin Nilsson  sum->r = (float)(sum->r + rgba.r*factor); sum->g = (float)(sum->g + rgba.g*factor); sum->b = (float)(sum->b + rgba.b*factor); sum->alpha = (float)(sum->alpha + rgba.alpha*factor);
1482aa1997-11-23Per Hedbor /* REVEAL_GLOBAL_VARIABLES(); */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) }
01b9212016-01-12Per Hedbor static inline void
1482aa1997-11-23Per Hedbor  add_to_rgbd_sum_with_factor(rgbd_group *sum, rgba_group rgba,
8a80a82000-08-08Henrik Grubbström (Grubba)  double factor)
ab6aec1997-02-11Fredrik Hübinette (Hubbe) {
d9ae471997-10-07Henrik Grubbström (Grubba)  /* NOTE:
1482aa1997-11-23Per Hedbor  * This code MUST be MT-SAFE! (but also fast /per)
d9ae471997-10-07Henrik Grubbström (Grubba)  */
1482aa1997-11-23Per Hedbor /* HIDE_GLOBAL_VARIABLES(); */
cc7cf42015-10-14Martin Nilsson  sum->r = (float)(sum->r+rgba.r*factor); sum->g = (float)(sum->g+rgba.g*factor); sum->b = (float)(sum->b+rgba.b*factor);
1482aa1997-11-23Per Hedbor /* REVEAL_GLOBAL_VARIABLES(); */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) }
2f7d791997-03-25Mirar (Pontus Hagland) /* **! method object tuned_box(int x1,int y1,int x2,int y2,array(array(int)) corner_color) **! Draws a filled rectangle with colors (and alpha values) tuned **! between the corners. **! **! Tuning function is (1.0-x/xw)*(1.0-y/yw) where x and y is **! the distance to the corner and xw and yw are the sides of the **! rectangle. **!
68b67c1997-05-30Mirar (Pontus Hagland) **! <table><tr valign=center> **! <td><illustration> return lena(); </illustration></td>
8626fb1998-04-16Mirar (Pontus Hagland) **! <td><illustration> return lena()->copy()->tuned_box(30,10,lena()->xsize()-20,lena()->ysize()-20,({({255,0,0}),({0,255,0}),({0,0,255}),({255,255,0})})); </illustration></td>
68b67c1997-05-30Mirar (Pontus Hagland) **! <td><illustration> return lena()->copy()->tuned_box(0,0,lena()->xsize(),lena()->ysize(),({({255,0,0}),({0,255,0}),({0,0,255}),({255,255,0})})); </illustration></td> **! <td><illustration> return lena()->copy()->tuned_box(0,0,lena()->xsize(),lena()->ysize(),({({255,0,0,255}),({0,255,0,128}),({0,0,255,128}),({255,255,0})})); </illustration></td> **! </tr><tr valign=center> **! <td>original</td>
8626fb1998-04-16Mirar (Pontus Hagland) **! <td>tuned box</td>
68b67c1997-05-30Mirar (Pontus Hagland) **! <td>solid tuning<br>(blue,red,green,yellow)</td> **! <td>tuning transparency<br>(as left + 255,128,128,0)</td> **! </tr></table> **!
2f7d791997-03-25Mirar (Pontus Hagland) **! returns the object called **! **! arg int x1 **! arg int y1 **! arg int x2 **! arg int y2 **! rectangle corners **! arg array(array(int)) corner_color **! colors of the corners:
f311411997-04-18Mirar (Pontus Hagland) **! <pre>
2f7d791997-03-25Mirar (Pontus Hagland) **! ({x1y1,x2y1,x1y2,x2y2})
f311411997-04-18Mirar (Pontus Hagland) **! </pre>
2f7d791997-03-25Mirar (Pontus Hagland) **! each of these is an array of integeres:
f311411997-04-18Mirar (Pontus Hagland) **! <pre>
2f7d791997-03-25Mirar (Pontus Hagland) **! ({r,g,b}) or ({r,g,b,alpha})
f311411997-04-18Mirar (Pontus Hagland) **! </pre>
2f7d791997-03-25Mirar (Pontus Hagland) **! Default alpha channel value is 0 (opaque). */
01b9212016-01-12Per Hedbor inline static void
13670c2015-05-25Martin Nilsson image_tuned_box_leftright(const rgba_group left, const rgba_group right, rgb_group *dest, const int length, const int maxlength,
5524691997-11-29Henrik Wallin  const int xsize, const int height)
c1260f1997-11-23Per Hedbor {
f744291998-02-11Mirar (Pontus Hagland)  int x, y=height;
c1260f1997-11-23Per Hedbor  rgb_group *from = dest;
2c7bd41997-11-23Per Hedbor  if(!xsize || !height) return;
5524691997-11-29Henrik Wallin  for(x=0; x<maxlength; x++)
c1260f1997-11-23Per Hedbor  {
cc7cf42015-10-14Martin Nilsson  (dest+x)->r = (COLORTYPE)((((long)left.r)*(length-x)+((long)right.r)*(x))/length); (dest+x)->g = (COLORTYPE)((((long)left.g)*(length-x)+((long)right.g)*(x))/length); (dest+x)->b = (COLORTYPE)((((long)left.b)*(length-x)+((long)right.b)*(x))/length);
c1260f1997-11-23Per Hedbor  }
13670c2015-05-25Martin Nilsson  while(--y) memcpy((dest+=xsize), from, maxlength*sizeof(rgb_group));
c1260f1997-11-23Per Hedbor }
01b9212016-01-12Per Hedbor inline static void
c1260f1997-11-23Per Hedbor image_tuned_box_topbottom(const rgba_group left, const rgba_group right,
13670c2015-05-25Martin Nilsson  rgb_group *dest, const int length, const int xsize,
5524691997-11-29Henrik Wallin  const int height, const int maxheight)
c1260f1997-11-23Per Hedbor { int x,y; rgb_group color, *from, old;
5524691997-11-29Henrik Wallin  if(!xsize || !maxheight) return;
dffabf2014-02-24Per Hedbor 
170f4c2005-12-12Martin Nilsson  old.r = old.g = old.b = 0;
dffabf2014-02-24Per Hedbor 
c1260f1997-11-23Per Hedbor  if(length > 128) {
5524691997-11-29Henrik Wallin  for(y=0; y<maxheight; y++)
c1260f1997-11-23Per Hedbor  {
cc7cf42015-10-14Martin Nilsson  color.r = (COLORTYPE)((((long)left.r)*(height-y)+((long)right.r)*(y))/height); color.g = (COLORTYPE)((((long)left.g)*(height-y)+((long)right.g)*(y))/height); color.b = (COLORTYPE)((((long)left.b)*(height-y)+((long)right.b)*(y))/height);
1482aa1997-11-23Per Hedbor  if(y && color_equal(old, color))
c1260f1997-11-23Per Hedbor  {
59fc9e2014-09-03Martin Nilsson  memcpy(dest,dest-xsize,length*sizeof(rgb_group));
c1260f1997-11-23Per Hedbor  dest+=xsize; } else {
1482aa1997-11-23Per Hedbor  from = dest;
c1260f1997-11-23Per Hedbor  for(x=0; x<64; x++) *(dest++) = color;
13670c2015-05-25Martin Nilsson  for(;x<length-64;x+=64,dest+=64)
59fc9e2014-09-03Martin Nilsson  memcpy(dest, from, 64*sizeof(rgb_group));
c1260f1997-11-23Per Hedbor  for(;x<length; x++) *(dest++) = color; dest += xsize-length; old = color; } } } else {
5524691997-11-29Henrik Wallin  for(y=0; y<maxheight; y++)
c1260f1997-11-23Per Hedbor  {
cc7cf42015-10-14Martin Nilsson  color.r = (COLORTYPE)((((long)left.r)*(height-y)+((long)right.r)*(y))/height); color.g = (COLORTYPE)((((long)left.g)*(height-y)+((long)right.g)*(y))/height); color.b = (COLORTYPE)((((long)left.b)*(height-y)+((long)right.b)*(y))/height);
1482aa1997-11-23Per Hedbor  if(y && color_equal(old, color))
c1260f1997-11-23Per Hedbor  {
59fc9e2014-09-03Martin Nilsson  memcpy(dest,dest-xsize,length*sizeof(rgb_group));
c1260f1997-11-23Per Hedbor  dest+=xsize; } else { for(x=0; x<length; x++) *(dest++) = color; dest += xsize-length; old = color; } } } }
2f7d791997-03-25Mirar (Pontus Hagland) 
01a9572000-02-03Henrik Grubbström (Grubba) static void image_tuned_box(INT32 args)
ab6aec1997-02-11Fredrik Hübinette (Hubbe) {
5524691997-11-29Henrik Wallin  INT32 x1,y1,x2,y2,xw,yw,x,y;
f744291998-02-11Mirar (Pontus Hagland)  rgba_group topleft,topright,bottomleft,bottomright,sum;
5524691997-11-29Henrik Wallin  rgb_group *img; INT32 ymax; struct image *this;
0dd2d42000-08-08Henrik Grubbström (Grubba)  double dxw, dyw;
5524691997-11-29Henrik Wallin  if (args<5||
017b572011-10-28Henrik Grubbström (Grubba)  TYPEOF(sp[-args]) != T_INT|| TYPEOF(sp[1-args]) != T_INT|| TYPEOF(sp[2-args]) != T_INT|| TYPEOF(sp[3-args]) != T_INT)
06bd612016-01-26Martin Nilsson  SIMPLE_WRONG_NUM_ARGS_ERROR("tuned_box",5);
5524691997-11-29Henrik Wallin 
48b1512018-02-22Martin Nilsson  CHECK_INIT();
5524691997-11-29Henrik Wallin  x1=sp[-args].u.integer; y1=sp[1-args].u.integer; x2=sp[2-args].u.integer; y2=sp[3-args].u.integer;
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(sp[4-args]) == T_ARRAY)
d158881999-07-21Mirar (Pontus Hagland)  { if (args>5) pop_n_elems(args-5); args+=sp[-1].u.array->size-1; sp--; push_array_items(sp->u.array); /* frees */ } if (args<8)
06bd612016-01-26Martin Nilsson  SIMPLE_WRONG_NUM_ARGS_ERROR("tuned_box",8);
d158881999-07-21Mirar (Pontus Hagland)  if (!image_color_svalue_rgba(sp-4,&topleft))
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("tuned_box",5,"color");
d158881999-07-21Mirar (Pontus Hagland)  if (!image_color_svalue_rgba(sp-3,&topright))
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("tuned_box",6,"color");
d158881999-07-21Mirar (Pontus Hagland)  if (!image_color_svalue_rgba(sp-2,&bottomleft))
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("tuned_box",7,"color");
d158881999-07-21Mirar (Pontus Hagland)  if (!image_color_svalue_rgba(sp-1,&bottomright))
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("tuned_box",8,"color");
5524691997-11-29Henrik Wallin  if (x1>x2) x1^=x2,x2^=x1,x1^=x2, sum=topleft,topleft=topright,topright=sum, sum=bottomleft,bottomleft=bottomright,bottomright=sum; if (y1>y2) y1^=y2,y2^=y1,y1^=y2, sum=topleft,topleft=bottomleft,bottomleft=sum, sum=topright,topright=bottomright,bottomright=sum; pop_n_elems(args);
d6ac731998-04-20Henrik Grubbström (Grubba)  ref_push_object(THISOBJ);
5524691997-11-29Henrik Wallin  if (x2<0||y2<0||x1>=THIS->xsize||y1>=THIS->ysize) return; xw=x2-x1; yw=y2-y1; if(xw == 0 || yw == 0) return; this=THIS; THREADS_ALLOW(); if (! (topleft.alpha||topright.alpha||bottomleft.alpha||bottomright.alpha)) {
13670c2015-05-25Martin Nilsson  if(color_equal(topleft,bottomleft) &&
5524691997-11-29Henrik Wallin  color_equal(topright, bottomright)) {
13670c2015-05-25Martin Nilsson  image_tuned_box_leftright(topleft, bottomright, this->img+x1+this->xsize*y1, xw+1, MINIMUM(xw+1, this->xsize-x1),
7210191997-12-22Fredrik Hübinette (Hubbe)  this->xsize, MINIMUM(yw+1, this->ysize-y1));
5524691997-11-29Henrik Wallin 
13670c2015-05-25Martin Nilsson  }
5524691997-11-29Henrik Wallin  else if(color_equal(topleft,topright) && color_equal(bottomleft,bottomright)) {
13670c2015-05-25Martin Nilsson  image_tuned_box_topbottom(topleft, bottomleft, this->img+x1+this->xsize*y1, MINIMUM(xw+1, this->xsize-x1), this->xsize,
7210191997-12-22Fredrik Hübinette (Hubbe)  yw+1, MINIMUM(yw+1, this->ysize-y1));
13670c2015-05-25Martin Nilsson  } else
5524691997-11-29Henrik Wallin  goto ugly;
13670c2015-05-25Martin Nilsson  } else {
5524691997-11-29Henrik Wallin  ugly:
8a80a82000-08-08Henrik Grubbström (Grubba)  dxw = 1.0/(double)xw; dyw = 1.0/(double)yw;
d158881999-07-21Mirar (Pontus Hagland)  ymax=MINIMUM(yw,this->ysize-y1-1);
7210191997-12-22Fredrik Hübinette (Hubbe)  for (x=MAXIMUM(0,-x1); x<=xw && x+x1<this->xsize; x++)
5524691997-11-29Henrik Wallin  {
0dd2d42000-08-08Henrik Grubbström (Grubba) #define tune_factor(a,aw) (1.0-((double)(a)*(aw))) double tfx1 = tune_factor(x,dxw); double tfx2 = tune_factor(xw-x,dxw);
5524691997-11-29Henrik Wallin 
7210191997-12-22Fredrik Hübinette (Hubbe)  img=this->img+x+x1+this->xsize*MAXIMUM(0,y1);
5524691997-11-29Henrik Wallin  if (topleft.alpha||topright.alpha||bottomleft.alpha||bottomright.alpha)
d158881999-07-21Mirar (Pontus Hagland)  for (y=MAXIMUM(0,-y1); y<=ymax; y++)
5524691997-11-29Henrik Wallin  {
0dd2d42000-08-08Henrik Grubbström (Grubba)  double tfy;
5524691997-11-29Henrik Wallin  rgbda_group sum={0.0,0.0,0.0,0.0}; rgbd_group rgb;
0dd2d42000-08-08Henrik Grubbström (Grubba)  add_to_rgbda_sum_with_factor(&sum, topleft, (tfy=tune_factor(y,dyw))*tfx1); add_to_rgbda_sum_with_factor(&sum, topright, tfy*tfx2); add_to_rgbda_sum_with_factor(&sum, bottomleft, (tfy=tune_factor(yw-y,dyw))*tfx1); add_to_rgbda_sum_with_factor(&sum, bottomright, tfy*tfx2);
5524691997-11-29Henrik Wallin 
cc7cf42015-10-14Martin Nilsson  sum.alpha *= (float)(1.0/255.0);
5524691997-11-29Henrik Wallin 
cc7cf42015-10-14Martin Nilsson  rgb.r = (float)(sum.r*(1.0-sum.alpha)+img->r*sum.alpha); rgb.g = (float)(sum.g*(1.0-sum.alpha)+img->g*sum.alpha); rgb.b = (float)(sum.b*(1.0-sum.alpha)+img->b*sum.alpha);
5524691997-11-29Henrik Wallin 
0dd2d42000-08-08Henrik Grubbström (Grubba)  img->r = testrange(rgb.r+0.5); img->g = testrange(rgb.g+0.5); img->b = testrange(rgb.b+0.5);
5524691997-11-29Henrik Wallin 
0dd2d42000-08-08Henrik Grubbström (Grubba)  img += this->xsize;
5524691997-11-29Henrik Wallin  } else
d158881999-07-21Mirar (Pontus Hagland)  for (y=MAXIMUM(0,-y1); y<=ymax; y++)
5524691997-11-29Henrik Wallin  {
8a80a82000-08-08Henrik Grubbström (Grubba)  double tfy;
5524691997-11-29Henrik Wallin  rgbd_group sum={0,0,0}; add_to_rgbd_sum_with_factor(&sum,topleft,(tfy=tune_factor(y,dyw))*tfx1); add_to_rgbd_sum_with_factor(&sum,topright,tfy*tfx2); add_to_rgbd_sum_with_factor(&sum,bottomleft,(tfy=tune_factor(yw-y,dyw))*tfx1); add_to_rgbd_sum_with_factor(&sum,bottomright,tfy*tfx2); img->r=testrange(sum.r+0.5); img->g=testrange(sum.g+0.5); img->b=testrange(sum.b+0.5); img+=this->xsize; }
13670c2015-05-25Martin Nilsson 
5524691997-11-29Henrik Wallin  } } THREADS_DISALLOW();
ab6aec1997-02-11Fredrik Hübinette (Hubbe) }
2f7d791997-03-25Mirar (Pontus Hagland) /*
ae05371998-03-24Mirar (Pontus Hagland) **! method int gradients(array(int) point, ...) **! method int gradients(array(int) point, ..., float grad)
8626fb1998-04-16Mirar (Pontus Hagland) **! **! <table><tr valign=center> **! <td><illustration> return lena(); </illustration></td> **! <td><illustration> return lena()->gradients( **! ({random(lena()->xsize()),random(lena()->ysize()),255,0,0}), **! ({random(lena()->xsize()),random(lena()->ysize()),255,255,0}) **! )</illustration></td> **! <td><illustration> return lena()->gradients( **! ({random(lena()->xsize()),random(lena()->ysize()),255,0,0}), **! ({random(lena()->xsize()),random(lena()->ysize()),255,255,0}), **! ({random(lena()->xsize()),random(lena()->ysize()),255,0,255}), **! ({random(lena()->xsize()),random(lena()->ysize()),0,0,0}), **! ({random(lena()->xsize()),random(lena()->ysize()),128,128,255}), **! ({random(lena()->xsize()),random(lena()->ysize()),0,128,255}), **! ({random(lena()->xsize()),random(lena()->ysize()),0,0,255}), **! ({random(lena()->xsize()),random(lena()->ysize()),255,128,0}), **! ({random(lena()->xsize()),random(lena()->ysize()),255,255,255}), **! ({random(lena()->xsize()),random(lena()->ysize()),0,255,0}) **! )</illustration></td> **! <td><illustration> return lena()->gradients( **! ({(int)(0.2*lena()->xsize()),(int)(0.8*lena()->ysize()),255,0,0}), **! ({(int)(0.5*lena()->xsize()),(int)(-0.2*lena()->ysize()),16,16,64}), **! ({(int)(0.7*lena()->xsize()),(int)(0.6*lena()->ysize()),255,255,0}), **! 4.0)</illustration></td> **! <td><illustration> return lena()->gradients( **! ({(int)(0.2*lena()->xsize()),(int)(0.8*lena()->ysize()),255,0,0}), **! ({(int)(0.5*lena()->xsize()),(int)(-0.2*lena()->ysize()),16,16,64}), **! ({(int)(0.7*lena()->xsize()),(int)(0.6*lena()->ysize()),255,255,0}), **! 1.0)</illustration></td> **! <td><illustration> return lena()->gradients( **! ({(int)(0.2*lena()->xsize()),(int)(0.8*lena()->ysize()),255,0,0}), **! ({(int)(0.5*lena()->xsize()),(int)(-0.2*lena()->ysize()),16,16,64}), **! ({(int)(0.7*lena()->xsize()),(int)(0.6*lena()->ysize()),255,255,0}), **! 0.25)</illustration></td> **! </tr><tr> **! <td>original</td> **! <td>2 color<br>gradient</td> **! <td>10 color<br>gradient</td> **! <td>3 colors,<br>grad=4.0</td> **! <td>3 colors,<br>grad=1.0</td> **! <td>3 colors,<br>grad=0.25</td> **! </tr></table> **!
ae05371998-03-24Mirar (Pontus Hagland) **! returns the new image */ static void image_gradients(INT32 args) { struct gr_point { INT32 x,y,yd,xd; double r,g,b; struct gr_point *next; } *first=NULL,*c; INT32 n; INT32 x,y,xz; struct object *o; struct image *img; rgb_group *d; double grad=0.0; push_int(THIS->xsize); push_int(THIS->ysize); o=clone_object(image_program,2);
13b5ed2014-05-26Per Hedbor  img=get_storage(o,image_program);
ae05371998-03-24Mirar (Pontus Hagland)  d=img->img;
017b572011-10-28Henrik Grubbström (Grubba)  if (args && TYPEOF(sp[-1]) == T_FLOAT)
ae05371998-03-24Mirar (Pontus Hagland)  { args--; grad=sp[-1].u.float_number; pop_n_elems(1); } n=args; while (args--) {
36a00c2000-08-15Henrik Grubbström (Grubba)  struct array *a = NULL;
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(sp[-1]) != T_ARRAY ||
ae05371998-03-24Mirar (Pontus Hagland)  (a=sp[-1].u.array)->size!=5 ||
b6a3e02004-05-04Martin Nilsson  ( (a->type_field & ~BIT_INT) &&
751dfa2004-05-14Martin Nilsson  (array_fix_type_field(a) & ~BIT_INT) ))
ae05371998-03-24Mirar (Pontus Hagland)  { while (first) { c=first; first=c->next; free(c); }
212c392018-02-25Martin Nilsson  bad_arg_error("gradients",args,0,"",sp-args,
de22f72014-08-25Martin Nilsson  "Bad arguments to gradients.\n");
ae05371998-03-24Mirar (Pontus Hagland)  } c=malloc(sizeof(struct gr_point)); if (!c) { while (first) { c=first; first=c->next; free(c); }
7d60af2004-05-19Martin Nilsson  SIMPLE_OUT_OF_MEMORY_ERROR("gradients", sizeof(struct gr_point));
ae05371998-03-24Mirar (Pontus Hagland)  } c->next=first; c->x=a->item[0].u.integer; c->y=a->item[1].u.integer; c->r=(double)a->item[2].u.integer; c->g=(double)a->item[3].u.integer; c->b=(double)a->item[4].u.integer; first=c; n--; pop_n_elems(1); }
13670c2015-05-25Martin Nilsson  if (!first)
bf4d372018-02-16Martin Nilsson  SIMPLE_WRONG_NUM_ARGS_ERROR("gradients",1);
ae05371998-03-24Mirar (Pontus Hagland)  THREADS_ALLOW(); xz=img->xsize; for (y=0; y<img->ysize; y++) { c=first; while (c) { c->yd=y-c->y; c->xd=-1-c->x; c=c->next; } for (x=0; x<xz; x++) { double r,g,b; double z,di; r=g=b=z=0.0; c=first;
1755451998-04-06Mirar (Pontus Hagland)  if (grad==0.0)
ae05371998-03-24Mirar (Pontus Hagland)  while (c) { c->xd++;
1755451998-04-06Mirar (Pontus Hagland)  di=pow((c->xd*c->xd)+(c->yd*c->yd),0.5); if (!di) di=1e20; else di=1.0/di; r+=c->r*di; g+=c->g*di; b+=c->b*di; z+=di; c=c->next; } else if (grad==2.0) while (c) { c->xd++; di=(c->xd*c->xd)+(c->yd*c->yd);
ae05371998-03-24Mirar (Pontus Hagland)  if (!di) di=1e20; else di=1.0/di; r+=c->r*di; g+=c->g*di; b+=c->b*di; z+=di; c=c->next; } else while (c) { c->xd++;
1755451998-04-06Mirar (Pontus Hagland)  di=pow((c->xd*c->xd)+(c->yd*c->yd),0.5*grad);
ae05371998-03-24Mirar (Pontus Hagland)  if (!di) di=1e20; else di=1.0/di; r+=c->r*di; g+=c->g*di; b+=c->b*di; z+=di; c=c->next; } z=1.0/z;
8cc82a2016-02-12Martin Nilsson  d->r=(COLORTYPE)(r*z); d->g=(COLORTYPE)(g*z); d->b=(COLORTYPE)(b*z);
ae05371998-03-24Mirar (Pontus Hagland)  d++; } } while (first) { c=first; first=c->next; free(c); } THREADS_DISALLOW(); push_object(o); }
aff9242016-01-17Martin Nilsson static void select_random(INT32 args) { if(args>1) Pike_error("Too may arguments.\n"); if(!args) {
0f7d6e2016-02-23Henrik Grubbström (Grubba)  struct svalue *random =
0d4a4e2016-03-19Martin Nilsson  simple_mapping_string_lookup(get_builtin_constants(), "random");
0f7d6e2016-02-23Henrik Grubbström (Grubba)  if(!random || (TYPEOF(*random) != T_FUNCTION))
aff9242016-01-17Martin Nilsson  Pike_error("Unable to resolve random function.\n");
0f7d6e2016-02-23Henrik Grubbström (Grubba)  push_svalue(random);
aff9242016-01-17Martin Nilsson  } else if(TYPEOF(sp[-1])==T_INT) {
f27ce72017-04-23Henrik Grubbström (Grubba)  struct program *o;
aff9242016-01-17Martin Nilsson  push_constant_text("Random.Deterministic"); SAFE_APPLY_MASTER("resolv_or_error",1); if(TYPEOF(sp[-1])!=T_PROGRAM) Pike_error("Unable to resolve Random.Deterministic program.\n");
f27ce72017-04-23Henrik Grubbström (Grubba)  o = sp[-1].u.program;
aff9242016-01-17Martin Nilsson  stack_swap(); push_object(clone_object(o, 1));
0d4a4e2016-03-19Martin Nilsson  push_constant_text("random");
aff9242016-01-17Martin Nilsson  o_index(); if(TYPEOF(sp[-1])!=T_FUNCTION)
a2643d2016-03-19Martin Nilsson  Pike_error("random is not a function.\n");
aff9242016-01-17Martin Nilsson  } else if(TYPEOF(sp[-1])!=T_FUNCTION) { Pike_error("Expected seed or random function.\n"); } }
ae05371998-03-24Mirar (Pontus Hagland) /*
1755451998-04-06Mirar (Pontus Hagland) **! method object test()
824cf91999-01-26Mirar (Pontus Hagland) **! method object test(int seed)
aff9242016-01-17Martin Nilsson **! method object test(function(int:string) random)
8626fb1998-04-16Mirar (Pontus Hagland) **! Generates a test image, currently random gradients. **! **! <table><tr valign=center> **! <td><illustration> return lena(); </illustration></td> **! <td><illustration> return lena()->test()</illustration></td>
1e725e2003-07-23Martin Nilsson **! <td><illustration> return lena()->test()</illustration></td>
8626fb1998-04-16Mirar (Pontus Hagland) **! </tr><tr> **! <td>original</td> **! <td>->test()</td> **! <td>...and again</td> **! </tr></table> **!
1755451998-04-06Mirar (Pontus Hagland) **! returns the new image **! note **! May be subject to change or cease without prior warning.
2158f21999-07-02Mirar (Pontus Hagland) **! **! see also: gradients, tuned_box
1755451998-04-06Mirar (Pontus Hagland) */
01a9572000-02-03Henrik Grubbström (Grubba) static void image_test(INT32 args)
1755451998-04-06Mirar (Pontus Hagland) { int i;
f27ce72017-04-23Henrik Grubbström (Grubba)  struct svalue *s;
aff9242016-01-17Martin Nilsson  select_random(args);
f27ce72017-04-23Henrik Grubbström (Grubba)  s = &Pike_sp[-1];
1755451998-04-06Mirar (Pontus Hagland)  for (i=0; i<5; i++) {
aff9242016-01-17Martin Nilsson  push_int(THIS->xsize); apply_svalue(s, 1); push_int(THIS->ysize); apply_svalue(s, 1); push_int((i!=0)?255:0); apply_svalue(s, 1); push_int((i!=1)?255:0); if (i!=4) apply_svalue(s, 1); push_int((i!=2)?255:0); if (i!=3) apply_svalue(s, 1); f_aggregate(5);
1755451998-04-06Mirar (Pontus Hagland)  } push_float(2.0); image_gradients(6);
aff9242016-01-17Martin Nilsson  // Let apply clean the stack.
1755451998-04-06Mirar (Pontus Hagland) } /*
2f7d791997-03-25Mirar (Pontus Hagland) **! method int xsize() **! returns the width of the image */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void image_xsize(INT32 args) { pop_n_elems(args); if (THIS->img) push_int(THIS->xsize); else push_int(0); }
2f7d791997-03-25Mirar (Pontus Hagland) /* **! method int ysize() **! returns the height of the image */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void image_ysize(INT32 args) { pop_n_elems(args); if (THIS->img) push_int(THIS->ysize); else push_int(0); }
2f7d791997-03-25Mirar (Pontus Hagland) /* **! method object grey() **! method object grey(int r,int g,int b) **! Makes a grey-scale image (with weighted values). **! **! returns the new image object **!
5379b21997-05-30Mirar (Pontus Hagland) **! <table><tr valign=center> **! <td><illustration> return lena(); </illustration></td> **! <td><illustration> return lena()->grey(); </illustration></td> **! <td><illustration> return lena()->grey(0,0,255); </illustration></td> **! </tr><tr valign=center> **! <td>original</td> **! <td>->grey();</td> **! <td>->grey(0,0,255);</td> **! </tr></table> **!
2f7d791997-03-25Mirar (Pontus Hagland) **! arg int r **! arg int g **! arg int b **! weight of color, default is r=87,g=127,b=41, **! which should be pretty accurate of what the eyes see... **! **! see also: color, `*, modify_by_intensity */ void image_grey(INT32 args)
ab6aec1997-02-11Fredrik Hübinette (Hubbe) {
bb001b1997-10-12Mirar (Pontus Hagland)  INT32 x,div;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  rgbl_group rgb; rgb_group *d,*s; struct object *o; struct image *img; if (args<3) { rgb.r=87; rgb.g=127; rgb.b=41; } else
bf4d372018-02-16Martin Nilsson  getrgbl(&rgb,0,args,"grey");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  div=rgb.r+rgb.g+rgb.b;
e709751997-03-12Fredrik Hübinette (Hubbe)  o=clone_object(image_program,0);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  img=(struct image*)o->storage; *img=*THIS;
20d0552009-04-22Martin Stjernholm  if (!(img->img=malloc(sizeof(rgb_group)*THIS->xsize*THIS->ysize+RGB_VEC_PAD)))
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  { free_object(o);
7d60af2004-05-19Martin Nilsson  SIMPLE_OUT_OF_MEMORY_ERROR("grey",
20d0552009-04-22Martin Stjernholm  sizeof(rgb_group)*THIS->xsize*THIS->ysize+RGB_VEC_PAD);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } d=img->img; s=THIS->img; x=THIS->xsize*THIS->ysize; THREADS_ALLOW(); while (x--) { d->r=d->g=d->b= testrange( ((((long)s->r)*rgb.r+ ((long)s->g)*rgb.g+ ((long)s->b)*rgb.b)/div) ); d++; s++; } THREADS_DISALLOW(); pop_n_elems(args); push_object(o); }
2f7d791997-03-25Mirar (Pontus Hagland) /* **! method object color() **! method object color(int value)
94050c2009-07-21Henrik Grubbström (Grubba) **! method object color(Color color)
2f7d791997-03-25Mirar (Pontus Hagland) **! method object color(int r,int g,int b)
13670c2015-05-25Martin Nilsson **! Colorize an image.
2f7d791997-03-25Mirar (Pontus Hagland) **! **! The red, green and blue values of the pixels are multiplied **! with the given value(s). This works best on a grey image... **! **! The result is divided by 255, giving correct pixel values. **! **! If no arguments are given, the current color is used as factors. **!
5379b21997-05-30Mirar (Pontus Hagland) **! <table><tr valign=center> **! <td><illustration> return lena(); </illustration></td> **! <td><illustration> return lena()->color(128,128,255); </illustration></td> **! </tr><tr valign=center> **! <td>original</td> **! <td>->color(128,128,255);</td> **! </tr></table> **!
2f7d791997-03-25Mirar (Pontus Hagland) **! returns the new image object **! **! arg int r **! arg int g **! arg int b **! red, green, blue factors
94050c2009-07-21Henrik Grubbström (Grubba) **! arg Color color **! Color object with factors
2f7d791997-03-25Mirar (Pontus Hagland) **! arg int value **! factor **! **! see also: grey, `*, modify_by_intensity */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void image_color(INT32 args) {
bb001b1997-10-12Mirar (Pontus Hagland)  INT32 x;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  rgbl_group rgb; rgb_group *s,*d; struct object *o; struct image *img;
48b1512018-02-22Martin Nilsson  CHECK_INIT();
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (args<3) {
94050c2009-07-21Henrik Grubbström (Grubba)  struct color_struct *cs;
017b572011-10-28Henrik Grubbström (Grubba)  if (args>0 && TYPEOF(sp[-args]) == T_INT)
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  rgb.r=rgb.b=rgb.g=sp[-args].u.integer;
017b572011-10-28Henrik Grubbström (Grubba)  else if (args>0 && TYPEOF(sp[-args]) == T_OBJECT &&
76f7462014-05-26Martin Nilsson  (cs =get_storage(sp[-args].u.object, image_color_program)))
94050c2009-07-21Henrik Grubbström (Grubba)  rgb.r=cs->rgb.r, rgb.g=cs->rgb.g, rgb.b=cs->rgb.b; else
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  rgb.r=THIS->rgb.r, rgb.g=THIS->rgb.g, rgb.b=THIS->rgb.b; } else
bf4d372018-02-16Martin Nilsson  getrgbl(&rgb,0,args,"color");
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
e709751997-03-12Fredrik Hübinette (Hubbe)  o=clone_object(image_program,0);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  img=(struct image*)o->storage; *img=*THIS;
20d0552009-04-22Martin Stjernholm  if (!(img->img=malloc(sizeof(rgb_group)*THIS->xsize*THIS->ysize+RGB_VEC_PAD)))
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  { free_object(o);
7d60af2004-05-19Martin Nilsson  SIMPLE_OUT_OF_MEMORY_ERROR("color",
20d0552009-04-22Martin Stjernholm  sizeof(rgb_group)*THIS->xsize*THIS->ysize+RGB_VEC_PAD);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } d=img->img; s=THIS->img; x=THIS->xsize*THIS->ysize; THREADS_ALLOW();
30c1962000-08-28Per Hedbor #if 0
40555b2000-06-02Per Hedbor #ifdef ASSEMBLY_OK
30c1962000-08-28Per Hedbor  if( (image_cpuid & IMAGE_MMX) && x>>2 ) {
13670c2015-05-25Martin Nilsson  image_mult_buffer_mmx_x86asm( d,s,x>>2, RGB2ASMCOL( rgb ) );
30c1962000-08-28Per Hedbor  s += x; x = x%4; s -= x;
c985e92000-06-05Martin Stjernholm  }
30c1962000-08-28Per Hedbor #endif #endif
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  while (x--) {
cc7cf42015-10-14Martin Nilsson  d->r = (COLORTYPE)( (((long)rgb.r*s->r)/255) ); d->g = (COLORTYPE)( (((long)rgb.g*s->g)/255) ); d->b = (COLORTYPE)( (((long)rgb.b*s->b)/255) );
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  d++; s++; } THREADS_DISALLOW(); pop_n_elems(args); push_object(o); }
2f7d791997-03-25Mirar (Pontus Hagland) /* **! method object invert()
13670c2015-05-25Martin Nilsson **! Invert an image. Each pixel value gets to be 255-x, where x
2f7d791997-03-25Mirar (Pontus Hagland) **! is the old value. **!
68b67c1997-05-30Mirar (Pontus Hagland) **! <table><tr valign=center> **! <td><illustration> return lena(); </illustration></td> **! <td><illustration> return lena()->invert(); </illustration></td>
5379b21997-05-30Mirar (Pontus Hagland) **! <td><illustration> return lena()->rgb_to_hsv()->invert()->hsv_to_rgb(); </illustration></td>
68b67c1997-05-30Mirar (Pontus Hagland) **! </tr><tr valign=center> **! <td>original</td> **! <td>->invert();</td>
5379b21997-05-30Mirar (Pontus Hagland) **! <td>->rgb_to_hsv()->invert()->hsv_to_rgb();</td>
68b67c1997-05-30Mirar (Pontus Hagland) **! </tr></table> **!
2f7d791997-03-25Mirar (Pontus Hagland) **! returns the new image object */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void image_invert(INT32 args) {
03ddf12006-04-08Henrik Grubbström (Grubba)  size_t sz;
6add5b2006-04-08Henrik Grubbström (Grubba)  char *s,*d;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  struct object *o; struct image *img;
48b1512018-02-22Martin Nilsson  CHECK_INIT();
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
e709751997-03-12Fredrik Hübinette (Hubbe)  o=clone_object(image_program,0);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  img=(struct image*)o->storage; *img=*THIS;
03ddf12006-04-08Henrik Grubbström (Grubba)  sz = sizeof(rgb_group)*THIS->xsize * THIS->ysize;
20d0552009-04-22Martin Stjernholm  if (!(img->img=malloc(sz + RGB_VEC_PAD)))
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  { free_object(o);
20d0552009-04-22Martin Stjernholm  SIMPLE_OUT_OF_MEMORY_ERROR("invert", sz + RGB_VEC_PAD);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  }
6add5b2006-04-08Henrik Grubbström (Grubba)  d = (char *)img->img; s = (char *)THIS->img;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  THREADS_ALLOW();
03ddf12006-04-08Henrik Grubbström (Grubba)  if (sz >= sizeof(INT_TYPE))
6add5b2006-04-08Henrik Grubbström (Grubba)  { INT_TYPE *dd = (INT_TYPE *)d; INT_TYPE *ss = (INT_TYPE *)s; do { *(dd++) = ~*(ss++);
03ddf12006-04-08Henrik Grubbström (Grubba)  sz -= sizeof(INT_TYPE); } while (sz >= sizeof(INT_TYPE));
6add5b2006-04-08Henrik Grubbström (Grubba)  d = (char *)dd; s = (char *)ss; }
03ddf12006-04-08Henrik Grubbström (Grubba)  while (sz--)
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  {
6add5b2006-04-08Henrik Grubbström (Grubba)  *(d++) = ~*(s++);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } THREADS_DISALLOW(); pop_n_elems(args); push_object(o); }
2f7d791997-03-25Mirar (Pontus Hagland) /*
68b67c1997-05-30Mirar (Pontus Hagland) **! method object threshold()
2158f21999-07-02Mirar (Pontus Hagland) **! method object threshold(int level)
68b67c1997-05-30Mirar (Pontus Hagland) **! method object threshold(int r,int g,int b)
7383191999-06-21Mirar (Pontus Hagland) **! method object threshold(Color color)
13670c2015-05-25Martin Nilsson **! Makes a black-white image.
2f7d791997-03-25Mirar (Pontus Hagland) **!
7383191999-06-21Mirar (Pontus Hagland) **! If any of red, green, blue parts of a pixel **! is larger then the given value, the pixel will become
2f7d791997-03-25Mirar (Pontus Hagland) **! white, else black. **! **! This method works fine with the grey method. **!
7383191999-06-21Mirar (Pontus Hagland) **! If no arguments are given, it will paint all non-black **! pixels white. (Ie, default is 0,0,0.)
68b67c1997-05-30Mirar (Pontus Hagland) **! **! <table><tr valign=center> **! <td><illustration> return lena(); </illustration></td>
2158f21999-07-02Mirar (Pontus Hagland) **! <td><illustration> return lena()->threshold(100); </illustration></td>
68b67c1997-05-30Mirar (Pontus Hagland) **! <td><illustration> return lena()->threshold(90,100,110); </illustration></td> **! </tr><tr valign=center> **! <td>original</td>
2158f21999-07-02Mirar (Pontus Hagland) **! <td>->threshold(100);</td> **! <td>->threshold(0,100,0);</td>
68b67c1997-05-30Mirar (Pontus Hagland) **! </tr></table>
2f7d791997-03-25Mirar (Pontus Hagland) **! **! returns the new image object **! **! see also: grey
7383191999-06-21Mirar (Pontus Hagland) **!
2158f21999-07-02Mirar (Pontus Hagland) **! note
7383191999-06-21Mirar (Pontus Hagland) **! The above statement "any ..." was changed from "all ..." **! in Pike 0.7 (9906). It also uses 0,0,0 as default input, **! instead of current color. This is more useful.
2f7d791997-03-25Mirar (Pontus Hagland) */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void image_threshold(INT32 args) {
65a5492000-08-10Per Hedbor  INT_TYPE x;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  rgb_group *s,*d,rgb; struct object *o; struct image *img;
65a5492000-08-10Per Hedbor  INT_TYPE level=-1;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
48b1512018-02-22Martin Nilsson  CHECK_INIT();
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
017b572011-10-28Henrik Grubbström (Grubba)  if (args==1 && TYPEOF(sp[-args]) == T_INT) {
391ac52018-08-05Martin Nilsson  get_all_args(NULL,args,"%i",&level);
170f4c2005-12-12Martin Nilsson  level*=3; rgb.r=rgb.g=rgb.b=0; }
bf4d372018-02-16Martin Nilsson  else if (!getrgb(THIS,0,args,args,"threshold"))
7383191999-06-21Mirar (Pontus Hagland)  rgb.r=rgb.g=rgb.b=0;
c71a482005-08-14Martin Nilsson  else rgb=THIS->rgb;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
e709751997-03-12Fredrik Hübinette (Hubbe)  o=clone_object(image_program,0);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  img=(struct image*)o->storage; *img=*THIS;
20d0552009-04-22Martin Stjernholm  if (!(img->img=malloc(sizeof(rgb_group)*THIS->xsize*THIS->ysize+RGB_VEC_PAD)))
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  { free_object(o);
7d60af2004-05-19Martin Nilsson  SIMPLE_OUT_OF_MEMORY_ERROR("threshold",
20d0552009-04-22Martin Stjernholm  sizeof(rgb_group)*THIS->xsize*THIS->ysize+RGB_VEC_PAD);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } d=img->img; s=THIS->img; x=THIS->xsize*THIS->ysize; THREADS_ALLOW();
2158f21999-07-02Mirar (Pontus Hagland)  if (level==-1) while (x--) { if (s->r>rgb.r || s->g>rgb.g || s->b>rgb.b) d->r=d->g=d->b=255; else d->r=d->g=d->b=0;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
2158f21999-07-02Mirar (Pontus Hagland)  d++; s++; } else while (x--) { if (s->r+s->g+s->b>level) d->r=d->g=d->b=255; else d->r=d->g=d->b=0; d++; s++; }
13670c2015-05-25Martin Nilsson 
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  THREADS_DISALLOW(); pop_n_elems(args); push_object(o); }
e8369d1997-05-14Per Hedbor /*
5379b21997-05-30Mirar (Pontus Hagland) **! method object rgb_to_hsv()
e8369d1997-05-14Per Hedbor **! method object hsv_to_rgb() **! Converts RGB data to HSV data, or the other way around. **! When converting to HSV, the resulting data is stored like this: **! pixel.r = h; pixel.g = s; pixel.b = v; **! **! When converting to RGB, the input data is asumed to be placed in **! the pixels as above. **!
2c8d131997-05-30Mirar (Pontus Hagland) **! <table><tr valign=center> **! <td><illustration> return lena(); </illustration></td> **! <td><illustration> return lena()->hsv_to_rgb(); </illustration></td>
5379b21997-05-30Mirar (Pontus Hagland) **! <td><illustration> return lena()->rgb_to_hsv(); </illustration></td> **! </tr><tr valign=center> **! <td>original</td> **! <td>->hsv_to_rgb();</td> **! <td>->rgb_to_hsv();</td> **! </tr><tr valign=center> **! <td><illustration>
5804752006-01-04Marek Habersack **! return Image.Image(67,67)->tuned_box(0,0, 67,67,
5379b21997-05-30Mirar (Pontus Hagland) **! ({ ({ 255,255,128 }), ({ 0,255,128 }), **! ({ 255,255,255 }), ({ 0,255,255 })})); **! </illustration></td>
2c8d131997-05-30Mirar (Pontus Hagland) **! <td><illustration>
5804752006-01-04Marek Habersack **! return Image.Image(67,67)->tuned_box(0,0, 67,67,
2c8d131997-05-30Mirar (Pontus Hagland) **! ({ ({ 255,255,128 }), ({ 0,255,128 }), **! ({ 255,255,255 }), ({ 0,255,255 })})) **! ->hsv_to_rgb(); **! </illustration></td>
5379b21997-05-30Mirar (Pontus Hagland) **! <td><illustration>
5804752006-01-04Marek Habersack **! return Image.Image(67,67)->tuned_box(0,0, 67,67,
5379b21997-05-30Mirar (Pontus Hagland) **! ({ ({ 255,255,128 }), ({ 0,255,128 }), **! ({ 255,255,255 }), ({ 0,255,255 })})) **! ->rgb_to_hsv(); **! </illustration></td>
2c8d131997-05-30Mirar (Pontus Hagland) **! </tr><tr valign=center>
5379b21997-05-30Mirar (Pontus Hagland) **! <td>tuned box (below)</td>
2c8d131997-05-30Mirar (Pontus Hagland) **! <td>the rainbow (below)</td>
5379b21997-05-30Mirar (Pontus Hagland) **! <td>same, but rgb_to_hsv()</td>
2c8d131997-05-30Mirar (Pontus Hagland) **! </tr></table> **! **!
e8369d1997-05-14Per Hedbor **! HSV to RGB calculation: **! <pre> **! in = input pixel **! out = destination pixel **! h=-pos*c_angle*3.1415/(float)NUM_SQUARES; **! out.r=(in.b+in.g*cos(in.r)); **! out.g=(in.b+in.g*cos(in.r + pi*2/3)); **! out.b=(in.b+in.g*cos(in.r + pi*4/3)); **! </pre> **! **! RGB to HSV calculation: Hmm. **! <pre> **! </pre> **! **! Example: Nice rainbow.
2c8d131997-05-30Mirar (Pontus Hagland) **! <pre>
02c2d21999-04-13Mirar (Pontus Hagland) **! object i = Image.Image(200,200);
e8369d1997-05-14Per Hedbor **! i = i->tuned_box(0,0, 200,200, **! ({ ({ 255,255,128 }), ({ 0,255,128 }), **! ({ 255,255,255 }), ({ 0,255,255 })})) **! ->hsv_to_rgb();
2c8d131997-05-30Mirar (Pontus Hagland) **! </pre>
e8369d1997-05-14Per Hedbor **! returns the new image object */ void image_hsv_to_rgb(INT32 args) { INT32 i; rgb_group *s,*d; struct object *o; struct image *img;
2421f31997-09-05Henrik Grubbström (Grubba)  char *err = NULL;
48b1512018-02-22Martin Nilsson  CHECK_INIT();
e8369d1997-05-14Per Hedbor  o=clone_object(image_program,0); img=(struct image*)o->storage; *img=*THIS;
20d0552009-04-22Martin Stjernholm  if (!(img->img=malloc(sizeof(rgb_group)*THIS->xsize*THIS->ysize+RGB_VEC_PAD)))
e8369d1997-05-14Per Hedbor  { free_object(o);
7d60af2004-05-19Martin Nilsson  SIMPLE_OUT_OF_MEMORY_ERROR("hsv_to_rgb",
20d0552009-04-22Martin Stjernholm  sizeof(rgb_group)*THIS->xsize*THIS->ysize+RGB_VEC_PAD);
e8369d1997-05-14Per Hedbor  } d=img->img; s=THIS->img; THREADS_ALLOW(); i=img->xsize*img->ysize; while (i--) { double h,sat,v;
9e53482000-08-06Henrik Grubbström (Grubba)  double r,g,b;
e8369d1997-05-14Per Hedbor  h = (s->r/255.0)*(360.0/60.0); sat = s->g/255.0; v = s->b/255.0;
13670c2015-05-25Martin Nilsson 
e8369d1997-05-14Per Hedbor  if(sat==0.0) { r = g = b = v; } else { #define i floor(h) #define f (h-i) #define p (v * (1 - sat)) #define q (v * (1 - (sat * f))) #define t (v * (1 - (sat * (1 -f))))
f6b3b52016-02-12Martin Nilsson  switch((int)(i))
881ccc1998-02-18Mirar (Pontus Hagland)  { case 6: /* 360 degrees. Same as 0.. */ case 0: r = v; g = t; b = p; break; case 1: r = q; g = v; b = p; break; case 2: r = p; g = v; b = t; break; case 3: r = p; g = q; b = v; break; case 4: r = t; g = p; b = v; break; case 5: r = v; g = p; b = q; break; default: err = "Nope. Not possible"; goto exit_loop; }
e8369d1997-05-14Per Hedbor  } #undef i #undef f #undef p #undef q #undef t
f6b3b52016-02-12Martin Nilsson #define FIX(X) ((X)<0.0?0:(X)>=1.0?255:(int)((X)*255.0))
e8369d1997-05-14Per Hedbor  d->r = FIX(r); d->g = FIX(g); d->b = FIX(b); s++; d++; }
2421f31997-09-05Henrik Grubbström (Grubba) exit_loop:
765e7e1997-10-25Henrik Grubbström (Grubba)  ; /* Needed to keep some compilers happy. */
e8369d1997-05-14Per Hedbor  THREADS_DISALLOW();
2421f31997-09-05Henrik Grubbström (Grubba)  if (err) {
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("%s\n", err);
2421f31997-09-05Henrik Grubbström (Grubba)  }
e8369d1997-05-14Per Hedbor  pop_n_elems(args); push_object(o); }
a431de1997-05-30Per Hedbor #ifndef MAX3
7210191997-12-22Fredrik Hübinette (Hubbe) #define MAX3(X,Y,Z) MAXIMUM(MAXIMUM(X,Y),Z)
a431de1997-05-30Per Hedbor #endif #ifndef MIN3
7210191997-12-22Fredrik Hübinette (Hubbe) #define MIN3(X,Y,Z) MINIMUM(MINIMUM(X,Y),Z)
a431de1997-05-30Per Hedbor #endif void image_rgb_to_hsv(INT32 args) { INT32 i; rgb_group *s,*d; struct object *o; struct image *img;
48b1512018-02-22Martin Nilsson  CHECK_INIT();
a431de1997-05-30Per Hedbor  o=clone_object(image_program,0); img=(struct image*)o->storage; *img=*THIS;
20d0552009-04-22Martin Stjernholm  if (!(img->img=malloc(sizeof(rgb_group)*THIS->xsize*THIS->ysize+RGB_VEC_PAD)))
a431de1997-05-30Per Hedbor  { free_object(o);
7d60af2004-05-19Martin Nilsson  SIMPLE_OUT_OF_MEMORY_ERROR("rgb_to_hsv",
20d0552009-04-22Martin Stjernholm  sizeof(rgb_group)*THIS->xsize*THIS->ysize+RGB_VEC_PAD);
a431de1997-05-30Per Hedbor  } d=img->img; s=THIS->img; THREADS_ALLOW(); i=img->xsize*img->ysize; while (i--) {
636bc52014-11-01Martin Nilsson  int r,g,b; int v, delta; int h;
3cf2691998-03-11Mirar (Pontus Hagland)  r = s->r; g = s->g; b = s->b; v = MAX3(r,g,b); delta = v - MIN3(r,g,b);
f6b3b52016-02-12Martin Nilsson  if(r==v) h = (int)(((g-b)/(double)delta)*(255.0/6.0)); else if(g==v) h = (int)((2.0+(b-r)/(double)delta)*(255.0/6.0)); else h = (int)((4.0+(r-g)/(double)delta)*(255.0/6.0));
3cf2691998-03-11Mirar (Pontus Hagland)  if(h<0) h+=255; /* printf("hsv={ %d,%d,%d }\n", h, (int)((delta/(float)v)*255), v);*/
f6b3b52016-02-12Martin Nilsson  d->r = (int)h; d->g = (int)((delta/(double)v)*255.0);
9e53482000-08-06Henrik Grubbström (Grubba)  d->b = v;
3cf2691998-03-11Mirar (Pontus Hagland)  s++; d++;
a431de1997-05-30Per Hedbor  } THREADS_DISALLOW(); pop_n_elems(args); push_object(o); }
e8369d1997-05-14Per Hedbor 
2f7d791997-03-25Mirar (Pontus Hagland) /*
9e2b662004-07-08Marcus Comstedt **! method object rgb_to_yuv() **! method object yuv_to_rgb() **! Converts RGB data to YUV (YCrCb) data, or the other way around. **! When converting to YUV, the resulting data is stored like this: **! pixel.r = v (cr); pixel.g = y; pixel.b = u (cb); **! **! When converting to RGB, the input data is asumed to be placed in **! the pixels as above. **! **! <table><tr valign=center> **! <td><illustration> return lena(); </illustration></td> **! <td><illustration> return lena()->yuv_to_rgb(); </illustration></td> **! <td><illustration> return lena()->rgb_to_yuv(); </illustration></td> **! </tr><tr valign=center> **! <td>original</td> **! <td>->yuv_to_rgb();</td> **! <td>->rgb_to_yuv();</td> **! </tr><tr valign=center> **! <td><illustration>
5804752006-01-04Marek Habersack **! return Image.Image(67,67)->tuned_box(0,0, 67,67,
9e2b662004-07-08Marcus Comstedt **! ({ ({ 255,255,128 }), ({ 0,255,128 }), **! ({ 255,255,255 }), ({ 0,255,255 })})); **! </illustration></td> **! <td><illustration>
5804752006-01-04Marek Habersack **! return Image.Image(67,67)->tuned_box(0,0, 67,67,
9e2b662004-07-08Marcus Comstedt **! ({ ({ 255,255,128 }), ({ 0,255,128 }), **! ({ 255,255,255 }), ({ 0,255,255 })})) **! ->yuv_to_rgb(); **! </illustration></td> **! <td><illustration>
5804752006-01-04Marek Habersack **! return Image.Image(67,67)->tuned_box(0,0, 67,67,
9e2b662004-07-08Marcus Comstedt **! ({ ({ 255,255,128 }), ({ 0,255,128 }), **! ({ 255,255,255 }), ({ 0,255,255 })})) **! ->rgb_to_yuv(); **! </illustration></td> **! </tr><tr valign=center> **! <td>tuned box (below)</td> **! <td>the rainbow (below)</td> **! <td>same, but rgb_to_yuv()</td> **! </tr></table> **! **! **! RGB to YUB calculation (this follows CCIR.601): **! <pre> **! in = input pixel **! out = destination pixel **! Ey = 0.299*in.r+0.587*in.g+0.114*in.b **! Ecr = 0.713*(in.r - Ey) = 0.500*in.r-0.419*in.g-0.081*in.b **! Ecb = 0.564*(in.b - Ey) = -0.169*in.r-0.331*in.g+0.500*in.b **! out.r=0.875*Ecr+128 **! out.g=0.86*Ey+16 **! out.b=0.875*Ecb+128 **! </pre> **! **! Example: Nice rainbow. **! <pre> **! object i = Image.Image(200,200); **! i = i->tuned_box(0,0, 200,200, **! ({ ({ 255,255,128 }), ({ 0,255,128 }), **! ({ 255,255,255 }), ({ 0,255,255 })})) **! ->yuv_to_rgb(); **! </pre> **! returns the new image object */ #define CLAMP(v,l,h) ((v)<(l)? (l) : ((v)>(h)? (h) : (v))) #define DENORM_Y(y) ((((y)*220)/256)+16) #define DENORM_C(c) ((((c)*112)/128)+128) #define NORM_Y(y) ((((y)-16)*256)/220) #define NORM_C(c) ((((c)-128)*128)/112) void image_yuv_to_rgb(INT32 args) { INT32 i; rgb_group *s,*d; struct object *o; struct image *img;
48b1512018-02-22Martin Nilsson  CHECK_INIT();
9e2b662004-07-08Marcus Comstedt  o=clone_object(image_program,0); img=(struct image*)o->storage; *img=*THIS;
20d0552009-04-22Martin Stjernholm  if (!(img->img=malloc(sizeof(rgb_group)*THIS->xsize*THIS->ysize+RGB_VEC_PAD)))
9e2b662004-07-08Marcus Comstedt  { free_object(o); SIMPLE_OUT_OF_MEMORY_ERROR("yuv_to_rgb",
20d0552009-04-22Martin Stjernholm  sizeof(rgb_group)*THIS->xsize*THIS->ysize+RGB_VEC_PAD);
9e2b662004-07-08Marcus Comstedt  } d=img->img; s=THIS->img; THREADS_ALLOW(); i=img->xsize*img->ysize; while (i--) { double y,cr,cb; int r,g,b; y = NORM_Y((double)s->g); cr = NORM_C((double)s->r); cb = NORM_C((double)s->b); r = y+1.402*cr; g = y-0.714*cr-0.344*cb; b = y+1.772*cb; d->r = CLAMP(r, 0, 255); d->g = CLAMP(g, 0, 255); d->b = CLAMP(b, 0, 255); s++; d++; } exit_loop: ; /* Needed to keep some compilers happy. */ THREADS_DISALLOW(); pop_n_elems(args); push_object(o); } void image_rgb_to_yuv(INT32 args) { INT32 i; rgb_group *s,*d; struct object *o; struct image *img;
48b1512018-02-22Martin Nilsson  CHECK_INIT();
9e2b662004-07-08Marcus Comstedt  o=clone_object(image_program,0); img=(struct image*)o->storage; *img=*THIS;
20d0552009-04-22Martin Stjernholm  if (!(img->img=malloc(sizeof(rgb_group)*THIS->xsize*THIS->ysize+RGB_VEC_PAD)))
9e2b662004-07-08Marcus Comstedt  { free_object(o); SIMPLE_OUT_OF_MEMORY_ERROR("rgb_to_yuv",
20d0552009-04-22Martin Stjernholm  sizeof(rgb_group)*THIS->xsize*THIS->ysize+RGB_VEC_PAD);
9e2b662004-07-08Marcus Comstedt  } d=img->img; s=THIS->img; THREADS_ALLOW(); i=img->xsize*img->ysize; while (i--) { int y,cr,cb; y = DENORM_Y(0.299*s->r+0.587*s->g+0.114*s->b); cr = DENORM_C(0.500*s->r-0.419*s->g-0.081*s->b); cb = DENORM_C(-0.169*s->r-0.331*s->g+0.500*s->b); d->g = CLAMP(y, 16, 235); d->r = CLAMP(cr, 16, 239); d->b = CLAMP(cb, 16, 239); s++; d++; } THREADS_DISALLOW(); pop_n_elems(args); push_object(o); } #undef NORM_Y #undef NORM_C #undef DENORM_Y #undef DENORM_C #undef CLAMP /*
2f7d791997-03-25Mirar (Pontus Hagland) **! method object distancesq() **! method object distancesq(int r,int g,int b) **! Makes an grey-scale image, for alpha-channel use.
13670c2015-05-25Martin Nilsson **!
2f7d791997-03-25Mirar (Pontus Hagland) **! The given value (or current color) are used for coordinates
13670c2015-05-25Martin Nilsson **! in the color cube. Each resulting pixel is the
2f7d791997-03-25Mirar (Pontus Hagland) **! distance from this point to the source pixel color, **! in the color cube, squared, rightshifted 8 steps: **! **! <pre> **! p = pixel color **! o = given color **! d = destination pixel **! d.red=d.blue=d.green= **! ((o.red-p.red)²+(o.green-p.green)²+(o.blue-p.blue)²)>>8 **! </pre> **!
2c8d131997-05-30Mirar (Pontus Hagland) **! <table><tr valign=center> **! <td><illustration> return lena(); </illustration></td>
8626fb1998-04-16Mirar (Pontus Hagland) **! <td><illustration> return lena()->distancesq(0,255,255); </illustration></td> **! <td><illustration> return lena()->distancesq(255,0,255); </illustration></td> **! <td><illustration> return lena()->distancesq(255,255,0); </illustration></td>
2c8d131997-05-30Mirar (Pontus Hagland) **! </tr><tr valign=center> **! <td>original</td>
8626fb1998-04-16Mirar (Pontus Hagland) **! <td>distance² to cyan</td> **! <td>...to purple</td> **! <td>...to yellow</td>
2c8d131997-05-30Mirar (Pontus Hagland) **! </tr></table> **! **!
2f7d791997-03-25Mirar (Pontus Hagland) **! returns the new image object **! **! arg int r **! arg int g **! arg int b **! red, green, blue coordinates **! **! see also: select_from */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void image_distancesq(INT32 args) { INT32 i; rgb_group *s,*d,rgb; struct object *o; struct image *img;
48b1512018-02-22Martin Nilsson  CHECK_INIT();
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
bf4d372018-02-16Martin Nilsson  getrgb(THIS,0,args,args,"distancesq");
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
e709751997-03-12Fredrik Hübinette (Hubbe)  o=clone_object(image_program,0);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  img=(struct image*)o->storage; *img=*THIS;
20d0552009-04-22Martin Stjernholm  if (!(img->img=malloc(sizeof(rgb_group)*THIS->xsize*THIS->ysize+RGB_VEC_PAD)))
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  { free_object(o);
7d60af2004-05-19Martin Nilsson  SIMPLE_OUT_OF_MEMORY_ERROR("distancesq",
20d0552009-04-22Martin Stjernholm  sizeof(rgb_group)*THIS->xsize*THIS->ysize+RGB_VEC_PAD);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } d=img->img; s=THIS->img; rgb=THIS->rgb; THREADS_ALLOW(); i=img->xsize*img->ysize; while (i--) {
e375a11997-09-01Per Hedbor  int dist;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) #define DISTANCE(A,B) \
e375a11997-09-01Per Hedbor  (sq((long)(A).r-(B).r)+sq((long)(A).g-(B).g)+sq((long)(A).b-(B).b)) dist = DISTANCE(*s,rgb)>>8; d->r=d->g=d->b=testrange(dist);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  d++; s++; } THREADS_DISALLOW(); pop_n_elems(args); push_object(o); } /*#define DEBUG_ISF*/ #define ISF_LEFT 4 #define ISF_RIGHT 8 void isf_seek(int mode,int ydir,INT32 low_limit,INT32 x1,INT32 x2,INT32 y, rgb_group *src,rgb_group *dest,INT32 xsize,INT32 ysize, rgb_group rgb,int reclvl) { INT32 x,xr; INT32 j; #ifdef DEBUG_ISF fprintf(stderr,"isf_seek reclvl=%d mode=%d, ydir=%d, low_limit=%d, x1=%d, x2=%d, y=%d, src=%lx, dest=%lx, xsize=%d, ysize=%d, rgb=%d,%d,%d\n",reclvl, mode,ydir,low_limit,x1,x2,y,src,dest,xsize,ysize,rgb.r,rgb.g,rgb.b); #endif #define MARK_DISTANCE(_dest,_value) \
7210191997-12-22Fredrik Hübinette (Hubbe)  ((_dest).r=(_dest).g=(_dest).b=(MAXIMUM(1,255-(_value>>8))))
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if ( mode&ISF_LEFT ) /* scan left from x1 */ { x=x1; while (x>0) { x--; #ifdef DEBUG_ISF fprintf(stderr,"<-- %d (",DISTANCE(rgb,src[x+y*xsize])); fprintf(stderr," %d,%d,%d)\n",src[x+y*xsize].r,src[x+y*xsize].g,src[x+y*xsize].b); #endif if ( (j=DISTANCE(rgb,src[x+y*xsize])) >low_limit) { x++; break; } else { if (dest[x+y*xsize].r) { x++; break; } /* been there */ MARK_DISTANCE(dest[x+y*xsize],j); } } if (x1>x) { isf_seek(ISF_LEFT,-ydir,low_limit, x,x1-1,y,src,dest,xsize,ysize,rgb,reclvl+1); } x1=x; } if ( mode&ISF_RIGHT ) /* scan right from x2 */ { x=x2; while (x<xsize-1) { x++; #ifdef DEBUG_ISF fprintf(stderr,"--> %d (",DISTANCE(rgb,src[x+y*xsize])); fprintf(stderr," %d,%d,%d)\n",src[x+y*xsize].r,src[x+y*xsize].g,src[x+y*xsize].b); #endif if ( (j=DISTANCE(rgb,src[x+y*xsize])) >low_limit) { x--; break; } else { if (dest[x+y*xsize].r) { x--; break; } /* done that */ MARK_DISTANCE(dest[x+y*xsize],j); } } if (x2<x) { isf_seek(ISF_RIGHT,-ydir,low_limit, x2+1,x,y,src,dest,xsize,ysize,rgb,reclvl+1); } x2=x; } xr=x=x1; y+=ydir; if (y<0 || y>=ysize) return; while (x<=x2) { #ifdef DEBUG_ISF fprintf(stderr,"==> %d (",DISTANCE(rgb,src[x+y*xsize])); fprintf(stderr," %d,%d,%d)\n",src[x+y*xsize].r,src[x+y*xsize].g,src[x+y*xsize].b); #endif if ( dest[x+y*xsize].r || /* seen that */
13670c2015-05-25Martin Nilsson  (j=DISTANCE(rgb,src[x+y*xsize])) >low_limit)
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  { if (xr<x) isf_seek(ISF_LEFT*(xr==x1),ydir,low_limit, xr,x-1,y,src,dest,xsize,ysize,rgb,reclvl+1); while (++x<=x2) if ( (j=DISTANCE(rgb,src[x+y*xsize])) <=low_limit) break; xr=x;
2f7d791997-03-25Mirar (Pontus Hagland) /* x++; hokuspokus /mirar */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) /* nån dag ska jag försöka begripa varför... */ if (x>x2) return; continue; } MARK_DISTANCE(dest[x+y*xsize],j); x++; } if (x>xr) isf_seek((ISF_LEFT*(xr==x1))|ISF_RIGHT,ydir,low_limit, xr,x-1,y,src,dest,xsize,ysize,rgb,reclvl+1); }
2f7d791997-03-25Mirar (Pontus Hagland) /* **! method object select_from(int x,int y) **! method object select_from(int x,int y,int edge_value) **! Makes an grey-scale image, for alpha-channel use.
13670c2015-05-25Martin Nilsson **!
2f7d791997-03-25Mirar (Pontus Hagland) **! This is very close to a floodfill.
13670c2015-05-25Martin Nilsson **!
2f7d791997-03-25Mirar (Pontus Hagland) **! The image is scanned from the given pixel, **! filled with 255 if the color is the same, **! or 255 minus distance in the colorcube, squared, rightshifted **! 8 steps (see <ref>distancesq</ref>). **! **! When the edge distance is reached, the scan is stopped. **! Default edge value is 30.
13670c2015-05-25Martin Nilsson **! This value is squared and compared with the square of the
2f7d791997-03-25Mirar (Pontus Hagland) **! distance above. **!
1e725e2003-07-23Martin Nilsson **! <table><tr valign=center> **! <td><illustration> return lena()->select_from(35,35,16); </illustration></td> **! <td><illustration> return lena()->select_from(35,35,32); </illustration></td> **! <td><illustration> return lena()->select_from(35,35,64); </illustration></td> **! <td><illustration> return lena()->select_from(35,35,96); </illustration></td> **! <td><illustration> return lena()->select_from(35,35,128); </illustration></td> **! <td><illustration> return lena()->select_from(35,35,192); </illustration></td> **! <td><illustration> return lena()->select_from(35,35,256); </illustration></td> **! </tr><tr> **! <td>35, 35, 16</td> **! <td>35, 35, 32</td> **! <td>35, 35, 64</td> **! <td>35, 35, 96</td> **! <td>35, 35, 128</td> **! <td>35, 35, 192</td> **! <td>35, 35, 256</td> **! </tr></table> **! **! <table><tr valign=center> **! <td><illustration> return lena(); </illustration></td> **! <td><illustration> return lena()*lena()->select_from(35,35,200); </illustration></td> **! </tr><tr> **! <td>original</td> **! <td>original * select_from(35,35,200)</td> **! </tr></table> **!
2f7d791997-03-25Mirar (Pontus Hagland) **! returns the new image object **! **! arg int x **! arg int y **! originating pixel in the image **! **! see also: distancesq */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void image_select_from(INT32 args) { struct object *o; struct image *img;
118f582018-02-22Martin Nilsson  int x,y,low_limit=30;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
48b1512018-02-22Martin Nilsson  CHECK_INIT();
391ac52018-08-05Martin Nilsson  get_all_args(NULL, args, "%d%d.%d", &x, &y, &low_limit);
118f582018-02-22Martin Nilsson  if( low_limit<0 ) low_limit=0;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  low_limit=low_limit*low_limit;
e709751997-03-12Fredrik Hübinette (Hubbe)  o=clone_object(image_program,0);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  img=(struct image*)o->storage; *img=*THIS;
20d0552009-04-22Martin Stjernholm  if (!(img->img=malloc(sizeof(rgb_group)*THIS->xsize*THIS->ysize+RGB_VEC_PAD)))
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  { free_object(o);
7d60af2004-05-19Martin Nilsson  SIMPLE_OUT_OF_MEMORY_ERROR("select_from",
20d0552009-04-22Martin Stjernholm  sizeof(rgb_group)*THIS->xsize*THIS->ysize+RGB_VEC_PAD);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  }
21b12a2014-09-03Martin Nilsson  memset(img->img,0,sizeof(rgb_group)*img->xsize*img->ysize);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
118f582018-02-22Martin Nilsson  if (x>=0 && x<img->xsize && y>=0 && y<img->ysize)
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  {
118f582018-02-22Martin Nilsson  isf_seek(ISF_LEFT|ISF_RIGHT,1,low_limit,x,x,y,
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  THIS->img,img->img,img->xsize,img->ysize,
118f582018-02-22Martin Nilsson  pixel(THIS,x,y),0); isf_seek(ISF_LEFT|ISF_RIGHT,-1,low_limit,x,x,y,
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  THIS->img,img->img,img->xsize,img->ysize,
118f582018-02-22Martin Nilsson  pixel(THIS,x,y),0);
aac3961997-05-28Mirar (Pontus Hagland) 
118f582018-02-22Martin Nilsson  MARK_DISTANCE(pixel(img,x,y),0);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } pop_n_elems(args); push_object(o); }
2f7d791997-03-25Mirar (Pontus Hagland)  /*
d6c5352000-04-09Per Hedbor **! method object bitscale(float factor) **! method object bitscale(float xfactor,float yfactor) **! scales the image with a factor, without smoothing. **! This routine is faster than scale, but gives less correct **! results
1e725e2003-07-23Martin Nilsson **! **! <table><tr valign=center> **! <td><illustration> return lena(); </illustration></td> **! <td><illustration> return lena()->bitscale(0.75); </illustration></td> **! <td><illustration> return lena()->scale(0.75); </illustration></td> **! </tr><tr> **! <td>original</td> **! <td>bitscale(0.75)</td> **! <td>scale(0.75)</td> **! </tr></table> **!
d6c5352000-04-09Per Hedbor **! returns the new image object **! arg float factor **! factor to use for both x and y **! arg float xfactor **! arg float yfactor **! separate factors for x and y **! **! method object bitscale(int newxsize,int newysize) **! method object bitscale(0,int newysize) **! method object bitscale(int newxsize,0) **! scales the image to a specified new size, **! if one of newxsize or newysize is 0, **! the image aspect ratio is preserved. **! returns the new image object **! arg int newxsize **! arg int newysize **! new image size in pixels **! **! note **! resulting image will be 1x1 pixels, at least */ void image_bitscale( INT32 args ) { int newx=1, newy=1; int oldx, oldy;
340c562001-06-13Henrik Grubbström (Grubba)  int x, y;
d6c5352000-04-09Per Hedbor  struct object *ro; rgb_group *s, *d; oldx = THIS->xsize; oldy = THIS->ysize; if( args == 1 ) {
017b572011-10-28Henrik Grubbström (Grubba)  if( TYPEOF(sp[-1]) == T_INT )
d6c5352000-04-09Per Hedbor  { newx = oldx * sp[-1].u.integer; newy = oldy * sp[-1].u.integer;
017b572011-10-28Henrik Grubbström (Grubba)  } else if( TYPEOF(sp[-1]) == T_FLOAT ) {
f6b3b52016-02-12Martin Nilsson  newx = (int)(oldx * sp[-1].u.float_number); newy = (int)(oldy * sp[-1].u.float_number);
13670c2015-05-25Martin Nilsson  } else
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("The scale factor must be an integer less than 2^32, or a float\n");
d6c5352000-04-09Per Hedbor  } else if( args == 2 ) {
017b572011-10-28Henrik Grubbström (Grubba)  if( TYPEOF(sp[-1]) != TYPEOF(sp[-2]) )
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Wrong type of argument\n");
017b572011-10-28Henrik Grubbström (Grubba)  if( TYPEOF(sp[-2]) == T_INT )
d6c5352000-04-09Per Hedbor  (newx = sp[-2].u.integer),(newy = sp[-1].u.integer);
017b572011-10-28Henrik Grubbström (Grubba)  else if( TYPEOF(sp[-2]) == T_FLOAT )
d6c5352000-04-09Per Hedbor  {
f6b3b52016-02-12Martin Nilsson  newx = (int)(oldx*sp[-2].u.float_number); newy = (int)(oldy*sp[-1].u.float_number);
d6c5352000-04-09Per Hedbor  } else
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error( "Wrong type of arguments\n");
d6c5352000-04-09Per Hedbor  } /* Not really nessesary if I use floats below.. */ /* FIXME */ if( newx > 65536 || newy > 65536 || oldx > 65536 || oldy > 65536)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Image too big.\n");
d6c5352000-04-09Per Hedbor  if( newx < 1 ) newx = 1; if( newy < 1 ) newy = 1; pop_n_elems( args ); push_int( newx ); push_int( newy ); ro = clone_object( image_program, 2 ); d=((struct image *)get_storage( ro, image_program))->img;
13670c2015-05-25Martin Nilsson 
d6c5352000-04-09Per Hedbor  for( y = 0; y<newy; y++ ) { s = THIS->img + (y * oldy / newy) * THIS->xsize; for( x = 0; x<newx; x++ ) *(d++) = *(s+x*oldx/newx); } push_object( ro ); } /*
2f7d791997-03-25Mirar (Pontus Hagland) **! method object apply_matrix(array(array(int|array(int))) matrix) **! method object apply_matrix(array(array(int|array(int))) matrix,int r,int g,int b) **! method object apply_matrix(array(array(int|array(int))) matrix,int r,int g,int b,int|float div) **! Applies a pixel-transform matrix, or filter, to the image.
13670c2015-05-25Martin Nilsson **!
2f7d791997-03-25Mirar (Pontus Hagland) **! <pre> **! 2 2
13670c2015-05-25Martin Nilsson **! pixel(x,y)= base+ k ( sum sum pixel(x+k-1,y+l-1)*matrix(k,l) ) **! k=0 l=0
2f7d791997-03-25Mirar (Pontus Hagland) **! </pre>
13670c2015-05-25Martin Nilsson **!
2f7d791997-03-25Mirar (Pontus Hagland) **! 1/k is sum of matrix, or sum of matrix multiplied with div. **! base is given by r,g,b and is normally black. **!
2c8d131997-05-30Mirar (Pontus Hagland) **! <table><tr><td rowspan=2>
2f7d791997-03-25Mirar (Pontus Hagland) **! blur (ie a 2d gauss function): **! <pre> **! ({({1,2,1}), **! ({2,5,2}), **! ({1,2,1})}) **! </pre>
2c8d131997-05-30Mirar (Pontus Hagland) **! </td><td> **! <illustration> **! return lena()->apply_matrix( **! ({({1,2,1}), **! ({2,5,2}), **! ({1,2,1})}) **! ); **! </illustration> **! </td><td> **! <illustration> **! return lena(); **! </illustration>
e45d821997-11-10Mirar (Pontus Hagland) **! </td></tr> **! <tr><td></td><td>original</td></tr>
13670c2015-05-25Martin Nilsson **!
2c8d131997-05-30Mirar (Pontus Hagland) **! <tr><td>
2f7d791997-03-25Mirar (Pontus Hagland) **! sharpen (k>8, preferably 12 or 16): **! <pre> **! ({({-1,-1,-1}), **! ({-1, k,-1}), **! ({-1,-1,-1})}) **! </pre>
2c8d131997-05-30Mirar (Pontus Hagland) **! </td><td> **! <illustration> **! return lena()->apply_matrix( **! ({({-1,-1,-1}), **! ({-1,14,-1}), **! ({-1,-1,-1})}) **! ); **! </illustration>
e45d821997-11-10Mirar (Pontus Hagland) **! </td></tr>
2f7d791997-03-25Mirar (Pontus Hagland) **!
2c8d131997-05-30Mirar (Pontus Hagland) **! <tr><td>
2f7d791997-03-25Mirar (Pontus Hagland) **! edge detect: **! <pre> **! ({({1, 1,1}), **! ({1,-8,1}), **! ({1, 1,1})}) **! </pre>
2c8d131997-05-30Mirar (Pontus Hagland) **! </td><td> **! <illustration> **! return lena()->apply_matrix( **! ({({1, 1,1}), **! ({1,-8,1}), **! ({1, 1,1})}) **! ); **! </illustration>
e45d821997-11-10Mirar (Pontus Hagland) **! </td></tr>
2f7d791997-03-25Mirar (Pontus Hagland) **!
2c8d131997-05-30Mirar (Pontus Hagland) **! <tr><td>
2f7d791997-03-25Mirar (Pontus Hagland) **! horisontal edge detect (get the idea): **! <pre>
2c8d131997-05-30Mirar (Pontus Hagland) **! ({({0, 0,0}), **! ({1,-2,1}),
2f7d791997-03-25Mirar (Pontus Hagland) **! ({0, 0,0})}) **! </pre>
2c8d131997-05-30Mirar (Pontus Hagland) **! </td><td> **! <illustration> **! return lena()->apply_matrix( **! ({({0, 0,0}), **! ({1,-2,1}), **! ({0, 0,0})}) **! ); **! </illustration>
e45d821997-11-10Mirar (Pontus Hagland) **! </td></tr>
2f7d791997-03-25Mirar (Pontus Hagland) **!
2c8d131997-05-30Mirar (Pontus Hagland) **! <tr><td rowspan=2>
2f7d791997-03-25Mirar (Pontus Hagland) **! emboss (might prefer to begin with a <ref>grey</ref> image): **! <pre>
2c8d131997-05-30Mirar (Pontus Hagland) **! ({({2, 1, 0}),
2f7d791997-03-25Mirar (Pontus Hagland) **! ({1, 0,-1}),
2c8d131997-05-30Mirar (Pontus Hagland) **! ({0,-1,-2})}), 128,128,128, 3
2f7d791997-03-25Mirar (Pontus Hagland) **! </pre>
2c8d131997-05-30Mirar (Pontus Hagland) **! </td><td> **! <illustration> **! return lena()->apply_matrix( **! ({({2, 1, 0}), **! ({1, 0,-1}), **! ({0,-1,-2})}), 128,128,128, 3 **! ); **! </illustration> **! </td><td> **! <illustration> **! return lena()->grey()->apply_matrix( **! ({({2, 1, 0}), **! ({1, 0,-1}), **! ({0,-1,-2})}), 128,128,128, 3 **! ); **! </illustration>
e45d821997-11-10Mirar (Pontus Hagland) **! </td></tr>
2974bc1997-11-10Mirar (Pontus Hagland) **! <tr><td></td><td>greyed</td></tr></table>
2f7d791997-03-25Mirar (Pontus Hagland) **!
e45d821997-11-10Mirar (Pontus Hagland) **! This function is not very fast.
e3cb4b1997-04-03Mirar (Pontus Hagland) **!
2f7d791997-03-25Mirar (Pontus Hagland) **! returns the new image object **! **! arg array(array(int|array(int))) **! the matrix; innermost is a value or an array with red, green, blue **! values for red, green, blue separation.
e3cb4b1997-04-03Mirar (Pontus Hagland) **! arg int r **! arg int g **! arg int b **! base level of result, default is zero **! arg int|float div **! division factor, default is 1.0.
2f7d791997-03-25Mirar (Pontus Hagland) */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void image_apply_matrix(INT32 args) { int width,height,i,j; rgbd_group *matrix; rgb_group default_rgb; struct object *o; double div;
7d60af2004-05-19Martin Nilsson  ONERROR o_err, matrix_err;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  CHRONO("apply_matrix"); if (args<1 ||
017b572011-10-28Henrik Grubbström (Grubba)  TYPEOF(sp[-args]) != T_ARRAY)
118f582018-02-22Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("apply_matrix", 1, "array");
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
de22f72014-08-25Martin Nilsson  if (args>3)
118f582018-02-22Martin Nilsson  { struct array *a;
7ae0442018-03-16Henrik Grubbström (Grubba)  int r, g, b;
391ac52018-08-05Martin Nilsson  get_all_args(NULL, args, "%a%d%d%d", &a, &r, &g, &b);
7ae0442018-03-16Henrik Grubbström (Grubba)  default_rgb.r = r; default_rgb.g = g; default_rgb.b = b;
118f582018-02-22Martin Nilsson  }
13670c2015-05-25Martin Nilsson  else
45e55c1998-01-25Mirar (Pontus Hagland)  {
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  default_rgb.r=0; default_rgb.g=0; default_rgb.b=0; }
017b572011-10-28Henrik Grubbström (Grubba)  if (args>4 && TYPEOF(sp[4-args]) == T_INT)
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  { div=sp[4-args].u.integer; if (!div) div=1; }
017b572011-10-28Henrik Grubbström (Grubba)  else if (args>4 && TYPEOF(sp[4-args]) == T_FLOAT)
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  { div=sp[4-args].u.float_number; if (!div) div=1; } else div=1;
13670c2015-05-25Martin Nilsson 
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  height=sp[-args].u.array->size; width=-1; for (i=0; i<height; i++) {
64cbc12007-08-10Henrik Grubbström (Grubba)  struct svalue *s = sp[-args].u.array->item + i;
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(*s) != T_ARRAY)
bf4d372018-02-16Martin Nilsson  Pike_error("Illegal contents of (root) array.\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (width==-1)
64cbc12007-08-10Henrik Grubbström (Grubba)  width = s->u.array->size;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  else
64cbc12007-08-10Henrik Grubbström (Grubba)  if (width != s->u.array->size)
bf4d372018-02-16Martin Nilsson  Pike_error("Arrays has different size.\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } if (width==-1) width=0;
1a597d2005-08-15Henrik Grubbström (Grubba)  matrix=xalloc(sizeof(rgbd_group)*width*height+1);
30bb592004-05-04Martin Nilsson 
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  for (i=0; i<height; i++) {
64cbc12007-08-10Henrik Grubbström (Grubba)  struct svalue *s = sp[-args].u.array->item + i;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  for (j=0; j<width; j++) {
64cbc12007-08-10Henrik Grubbström (Grubba)  struct svalue *s2 = s->u.array->item + j;
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(*s2) == T_ARRAY && s2->u.array->size == 3)
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  {
64cbc12007-08-10Henrik Grubbström (Grubba)  struct svalue *s3 = s2->u.array->item;
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(*s3) == T_INT) matrix[j+i*width].r = (float)s3->u.integer;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  else matrix[j+i*width].r=0;
f744291998-02-11Mirar (Pontus Hagland) 
64cbc12007-08-10Henrik Grubbström (Grubba)  s3++;
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(*s3) == T_INT) matrix[j+i*width].g = (float)s3->u.integer;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  else matrix[j+i*width].g=0;
f744291998-02-11Mirar (Pontus Hagland) 
64cbc12007-08-10Henrik Grubbström (Grubba)  s3++;
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(*s3) == T_INT) matrix[j+i*width].b = (float)s3->u.integer;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  else matrix[j+i*width].b=0; }
017b572011-10-28Henrik Grubbström (Grubba)  else if (TYPEOF(*s2) == T_INT)
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  matrix[j+i*width].r=matrix[j+i*width].g=
64cbc12007-08-10Henrik Grubbström (Grubba)  matrix[j+i*width].b = (float)s2->u.integer;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  else matrix[j+i*width].r=matrix[j+i*width].g=
340c562001-06-13Henrik Grubbström (Grubba)  matrix[j+i*width].b = 0.0;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } }
e709751997-03-12Fredrik Hübinette (Hubbe)  o=clone_object(image_program,0);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
7d60af2004-05-19Martin Nilsson  SET_ONERROR(matrix_err, free, matrix); SET_ONERROR(o_err, my_free_object, o);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) CHRONO("apply_matrix, begin"); if (THIS->img) img_apply_matrix((struct image*)o->storage,THIS,
e581ea2002-03-08Henrik Grubbström (Grubba)  width,height,matrix,div,default_rgb);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  CHRONO("apply_matrix, end");
7d60af2004-05-19Martin Nilsson  UNSET_ONERROR(o_err); UNSET_ONERROR(matrix_err);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  free(matrix); pop_n_elems(args); push_object(o); }
2f7d791997-03-25Mirar (Pontus Hagland) /*
e14d1a1998-02-13Mirar (Pontus Hagland) **! 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. **!
13670c2015-05-25Martin Nilsson **! Default is to paint above, below, to the left and the right of
e14d1a1998-02-13Mirar (Pontus Hagland) **! 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.
13670c2015-05-25Martin Nilsson **!
8626fb1998-04-16Mirar (Pontus Hagland) **! <table><tr valign=center> **! <td><illustration> return lena(); </illustration></td> **! <td><illustration> return lena()*lena()->threshold(100,100,100)</illustration></td> **! <td><illustration> return (lena()*lena()->threshold(100,100,100))->outline(255,0,0)</illustration></td> **! </tr><tr> **! <td>original</td> **! <td>masked<br>through<br>threshold</td> **! <td>...and<br>outlined<br>with red</td> **! </tr></table>
13670c2015-05-25Martin Nilsson **! **!
e14d1a1998-02-13Mirar (Pontus Hagland) **! 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) {
0d765c2004-09-19Martin Nilsson  static const unsigned char defaultmatrix[9]={0,1,0,1,1,1,0,1,0};
d987122004-10-07Martin Nilsson  unsigned char *matrix = (unsigned char *)defaultmatrix;
e14d1a1998-02-13Mirar (Pontus Hagland)  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;
48b1512018-02-22Martin Nilsson  CHECK_INIT();
e14d1a1998-02-13Mirar (Pontus Hagland) 
017b572011-10-28Henrik Grubbström (Grubba)  if (args && TYPEOF(sp[-args]) == T_ARRAY)
e14d1a1998-02-13Mirar (Pontus Hagland)  { int i,j; height=sp[-args].u.array->size; width=-1; for (i=0; i<height; i++) {
64cbc12007-08-10Henrik Grubbström (Grubba)  struct svalue *s = sp[-args].u.array->item + i;
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(*s) != T_ARRAY)
bf4d372018-02-16Martin Nilsson  Pike_error("Illegal contents of (root) array.\n");
e14d1a1998-02-13Mirar (Pontus Hagland)  if (width==-1)
64cbc12007-08-10Henrik Grubbström (Grubba)  width=s->u.array->size;
e14d1a1998-02-13Mirar (Pontus Hagland)  else
64cbc12007-08-10Henrik Grubbström (Grubba)  if (width!=s->u.array->size)
bf4d372018-02-16Martin Nilsson  Pike_error("Arrays have different size.\n");
e14d1a1998-02-13Mirar (Pontus Hagland)  } if (width==-1) width=0;
1a597d2005-08-15Henrik Grubbström (Grubba)  matrix=xalloc(sizeof(int)*width*height+1);
30bb592004-05-04Martin Nilsson 
e14d1a1998-02-13Mirar (Pontus Hagland)  for (i=0; i<height; i++) {
64cbc12007-08-10Henrik Grubbström (Grubba)  struct svalue *s=sp[-args].u.array->item + i;
e14d1a1998-02-13Mirar (Pontus Hagland)  for (j=0; j<width; j++) {
64cbc12007-08-10Henrik Grubbström (Grubba)  struct svalue *s2 = s->u.array->item + j;
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(*s2) == T_INT)
64cbc12007-08-10Henrik Grubbström (Grubba)  matrix[j+i*width] = (unsigned char)s2->u.integer;
e14d1a1998-02-13Mirar (Pontus Hagland)  else
64cbc12007-08-10Henrik Grubbström (Grubba)  matrix[j+i*width] = 1;
e14d1a1998-02-13Mirar (Pontus Hagland)  } } ai=1; } push_int(THIS->xsize); push_int(THIS->ysize); o=clone_object(image_program,2); img=(struct image*)(o->storage);
049de51998-02-28Mirar (Pontus Hagland)  img->rgb=THIS->rgb;
e14d1a1998-02-13Mirar (Pontus Hagland) 
9c14f32014-04-27Martin Nilsson  tmp=calloc((THIS->xsize+width),(THIS->ysize+height+1));
30bb592004-05-04Martin Nilsson  if (!tmp) { free_object(o); if (matrix!=defaultmatrix) free(matrix);
7d60af2004-05-19Martin Nilsson  SIMPLE_OUT_OF_MEMORY_ERROR("outline",
1a597d2005-08-15Henrik Grubbström (Grubba)  (THIS->xsize+width)*(THIS->ysize+height)+1);
30bb592004-05-04Martin Nilsson  }
9c14f32014-04-27Martin Nilsson 
e14d1a1998-02-13Mirar (Pontus Hagland)  s=THIS->img; if (!mask) { if (args-ai==6) {
bf4d372018-02-16Martin Nilsson  getrgbl(&bkgl,ai+3,args,"outline");
e14d1a1998-02-13Mirar (Pontus Hagland)  pop_n_elems(args-(ai+3)); args=ai+3; } else if (args-ai==7) {
bf4d372018-02-16Martin Nilsson  getrgbl(&bkgl,ai+4,args,"outline");
e14d1a1998-02-13Mirar (Pontus Hagland)  pop_n_elems(args-(ai+4)); args=ai+4; } else { bkgl.r=s->r; bkgl.g=s->g; bkgl.b=s->b; }
bf4d372018-02-16Martin Nilsson  getrgb(img,ai,args,args,"outline");
e14d1a1998-02-13Mirar (Pontus Hagland)  } else { if (args-ai==4) {
bf4d372018-02-16Martin Nilsson  getrgbl(&bkgl,ai,args,"outline_mask");
e14d1a1998-02-13Mirar (Pontus Hagland)  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--) {
0d765c2004-09-19Martin Nilsson  static const rgb_group white={255,255,255}; static const rgb_group black={0,0,0};
e14d1a1998-02-13Mirar (Pontus Hagland)  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; }
98c1b12003-07-26Mirar (Pontus Hagland)  free(tmp);
e14d1a1998-02-13Mirar (Pontus Hagland)  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); } /*
2849652001-07-19Martin Nilsson **! method object modify_by_intensity(int r,int g,int b,int|array(int) ... vn)
2f7d791997-03-25Mirar (Pontus Hagland) **! Recolor an image from intensity values. **! **! For each color an intensity is calculated, from r, g and b factors **! (see <ref>grey</ref>), this gives a value between 0 and max. **! **! The color is then calculated from the values given, v1 representing **! the intensity value of 0, vn representing max, and colors between **! representing intensity values between, linear. **!
2c8d131997-05-30Mirar (Pontus Hagland) **! <table><tr valign=center> **! <td><illustration> return lena(); </illustration></td> **! <td><illustration> return lena()->grey()->modify_by_intensity(1,0,0,0,({255,0,0}),({0,255,0})); </illustration></td> **! </tr><tr valign=center> **! <td>original</td> **! <td>->grey()->modify_by_intensity(1,0,0, 0,({255,0,0}),({0,255,0}));</td> **! </tr></table> **!
2f7d791997-03-25Mirar (Pontus Hagland) **! returns the new image object **! **! arg int r **! arg int g **! arg int b **! red, green, blue intensity factors **! arg int|array(int) v1 **! arg int|array(int) vn **! destination color **! **! see also: grey, `*, color */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void image_modify_by_intensity(INT32 args) {
844eae1997-11-07Mirar (Pontus Hagland)  INT32 x,y;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  rgbl_group rgb; rgb_group *list; rgb_group *s,*d; struct object *o; struct image *img;
542d6f2015-05-02Henrik Grubbström (Grubba)  unsigned int div;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
48b1512018-02-22Martin Nilsson  CHECK_INIT();
13670c2015-05-25Martin Nilsson  if (args<5)
bf4d372018-02-16Martin Nilsson  SIMPLE_WRONG_NUM_ARGS_ERROR("modify_by_intensity",5);
13670c2015-05-25Martin Nilsson 
bf4d372018-02-16Martin Nilsson  getrgbl(&rgb,0,args,"modify_by_intensity");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  div=rgb.r+rgb.g+rgb.b; if (!div) div=1;
20d0552009-04-22Martin Stjernholm  s=xalloc(sizeof(rgb_group)*(args-3)+RGB_VEC_PAD);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  for (x=0; x<args-3; x++) {
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(sp[3-args+x]) == T_INT)
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  s[x].r=s[x].g=s[x].b=testrange( sp[3-args+x].u.integer );
017b572011-10-28Henrik Grubbström (Grubba)  else if (TYPEOF(sp[3-args+x]) == T_ARRAY &&
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  sp[3-args+x].u.array->size >= 3) { struct svalue sv; array_index_no_free(&sv,sp[3-args+x].u.array,0);
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(sv) == T_INT) s[x].r=testrange( sv.u.integer );
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  else s[x].r=0; array_index(&sv,sp[3-args+x].u.array,1);
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(sv) == T_INT) s[x].g=testrange( sv.u.integer );
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  else s[x].g=0; array_index(&sv,sp[3-args+x].u.array,2);
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(sv) == T_INT) s[x].b=testrange( sv.u.integer );
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  else s[x].b=0; free_svalue(&sv); } else s[x].r=s[x].g=s[x].b=0; }
20d0552009-04-22Martin Stjernholm  list=malloc(sizeof(rgb_group)*256+RGB_VEC_PAD);
13670c2015-05-25Martin Nilsson  if (!list)
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  { free(s);
7d60af2004-05-19Martin Nilsson  SIMPLE_OUT_OF_MEMORY_ERROR("modify_by_intensity",
20d0552009-04-22Martin Stjernholm  sizeof(rgb_group)*256+RGB_VEC_PAD);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } for (x=0; x<args-4; x++) { INT32 p1,p2,r; p1=(255L*x)/(args-4); p2=(255L*(x+1))/(args-4); r=p2-p1; for (y=0; y<r; y++) {
cc7cf42015-10-14Martin Nilsson  list[y+p1].r = (COLORTYPE)((((long)s[x].r)*(r-y)+((long)s[x+1].r)*(y))/r); list[y+p1].g = (COLORTYPE)((((long)s[x].g)*(r-y)+((long)s[x+1].g)*(y))/r); list[y+p1].b = (COLORTYPE)((((long)s[x].b)*(r-y)+((long)s[x+1].b)*(y))/r);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } } list[255]=s[x]; free(s);
e709751997-03-12Fredrik Hübinette (Hubbe)  o=clone_object(image_program,0);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  img=(struct image*)o->storage; *img=*THIS;
20d0552009-04-22Martin Stjernholm  if (!(img->img=malloc(sizeof(rgb_group)*THIS->xsize*THIS->ysize+RGB_VEC_PAD)))
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  { free_object(o);
30bb592004-05-04Martin Nilsson  free(list);
7d60af2004-05-19Martin Nilsson  SIMPLE_OUT_OF_MEMORY_ERROR("modify_by_intensity",
20d0552009-04-22Martin Stjernholm  sizeof(rgb_group)*THIS->xsize*THIS->ysize+RGB_VEC_PAD);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } d=img->img; s=THIS->img; x=THIS->xsize*THIS->ysize; THREADS_ALLOW(); while (x--) {
542d6f2015-05-02Henrik Grubbström (Grubba)  unsigned int q = (s->r*rgb.r + s->g*rgb.g + s->b*rgb.b)/div;
e375a11997-09-01Per Hedbor  *(d++)=list[testrange( q )];
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  s++; } THREADS_DISALLOW(); free(list); pop_n_elems(args); push_object(o); }
624bc31998-04-18Mirar (Pontus Hagland) /*
0f61e92000-07-27Per Hedbor **! method object apply_curve( array(int(0..255)) curve_r, array(int(0..255)) curve_g, array(int(0..255)) curve_b ) **! method object apply_curve( array(int(0..255)) curve ) **! method object apply_curve( string channel, array(int(0..255)) curve ) **! **! Apply a lookup-table on all pixels in an image. **! If only one curve is passed, use the same curve for red, green and blue. **! If 'channel' is specified, the curve is only applied to the **! specified channel.
13670c2015-05-25Martin Nilsson **!
0f61e92000-07-27Per Hedbor **! returns a new image object
13670c2015-05-25Martin Nilsson **!
0f61e92000-07-27Per Hedbor **! arg array(int(0..255)) curve_r **! arg array(int(0..255)) curve_g **! arg array(int(0..255)) curve_b **! arg array(int(0..255)) curve **! An array with 256 elements, each between 0 and 255. **! It is used as a look-up table, if the pixel value is 2 and **! curve[2] is 10, the new pixel value will be 10. **! **! arg string channel **! one of "red", "green", "blue", "value", "saturation" and "hue". **! **! see also: gamma, `*, modify_by_intensity */ static void image_apply_curve_3( unsigned char curve[3][256] ) {
340c562001-06-13Henrik Grubbström (Grubba)  int i;
0f61e92000-07-27Per Hedbor  struct object *o; rgb_group *s = THIS->img, *d; push_int( THIS->xsize ); push_int( THIS->ysize ); o = clone_object( image_program, 2 );
13b5ed2014-05-26Per Hedbor  d = ((struct image*)get_storage( o, image_program ))->img;
0f61e92000-07-27Per Hedbor  i = THIS->xsize*THIS->ysize;
13670c2015-05-25Martin Nilsson 
0f61e92000-07-27Per Hedbor  THREADS_ALLOW(); for( ; i>0; i-- ) { d->r = curve[0][s->r]; d->g = curve[1][s->g]; (d++)->b = curve[2][(s++)->b]; } THREADS_DISALLOW(); push_object( o ); } static void image_apply_curve_1( unsigned char curve[256] ) {
340c562001-06-13Henrik Grubbström (Grubba)  int i;
0f61e92000-07-27Per Hedbor  struct object *o; rgb_group *s = THIS->img, *d; push_int( THIS->xsize ); push_int( THIS->ysize ); o = clone_object( image_program, 2 );
13b5ed2014-05-26Per Hedbor  d = ((struct image*)get_storage( o, image_program ))->img;
0f61e92000-07-27Per Hedbor  i = THIS->xsize*THIS->ysize; THREADS_ALLOW(); for( ; i>0; i-- ) { d->r = curve[s->r]; d->g = curve[s->g]; (d++)->b = curve[(s++)->b]; } THREADS_DISALLOW(); push_object( o ); }
13670c2015-05-25Martin Nilsson static void image_apply_curve_2( struct object *o, int channel,
0f61e92000-07-27Per Hedbor  unsigned char curve[256] ) {
340c562001-06-13Henrik Grubbström (Grubba)  int i;
0f61e92000-07-27Per Hedbor  rgb_group *d;
13b5ed2014-05-26Per Hedbor  d = ((struct image*)get_storage(o,image_program))->img;
0f61e92000-07-27Per Hedbor  i = THIS->xsize*THIS->ysize; THREADS_ALLOW();
13670c2015-05-25Martin Nilsson  switch( channel )
0f61e92000-07-27Per Hedbor  {
a4a1722000-12-05Per Hedbor  case 0: for( ; i>0; i--,d++ ) d->r = curve[d->r]; break; case 1: for( ; i>0; i--,d++ ) d->g = curve[d->g]; break; case 2: for( ; i>0; i--,d++ ) d->b = curve[d->b]; break;
0f61e92000-07-27Per Hedbor  } THREADS_DISALLOW(); push_object( o ); }
f178822004-05-02Martin Nilsson struct pike_string *s_red, *s_green, *s_blue; struct pike_string *s_saturation, *s_value, *s_hue;
0f61e92000-07-27Per Hedbor static void image_apply_curve( INT32 args ) { int i, j; switch( args ) { case 3: { unsigned char curve[3][256]; for( i = 0; i<3; i++ )
017b572011-10-28Henrik Grubbström (Grubba)  if( TYPEOF(sp[-args+i]) != T_ARRAY ||
0f61e92000-07-27Per Hedbor  sp[-args+i].u.array->size != 256 )
de22f72014-08-25Martin Nilsson  bad_arg_error("apply_curve",
212c392018-02-25Martin Nilsson  args, i+1, "array(int(8bit))", sp-args,
d010342017-10-11Henrik Grubbström (Grubba)  "Bad argument to apply_curve.\n");
0f61e92000-07-27Per Hedbor  else
d010342017-10-11Henrik Grubbström (Grubba)  for( j = 0; j<256; j++ ) { if( TYPEOF(sp[-args+i].u.array->item[j]) != T_INT ) { bad_arg_error("apply_curve",
212c392018-02-25Martin Nilsson  args, i+1, "array(int(8bit))", sp-args,
d010342017-10-11Henrik Grubbström (Grubba)  "Bad argument to apply_curve.\n"); } curve[i][j]=MINIMUM(sp[-args+i].u.array->item[j].u.integer,255); }
0f61e92000-07-27Per Hedbor  pop_n_elems( args ); image_apply_curve_3( curve ); return; } case 2: { unsigned char curve[256]; int chan = 0, co = 0; struct object *o;
017b572011-10-28Henrik Grubbström (Grubba)  if( TYPEOF(sp[-args]) != T_STRING )
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("apply_curve", 1, "string");
017b572011-10-28Henrik Grubbström (Grubba)  if( TYPEOF(sp[-args+1]) != T_ARRAY ||
0f61e92000-07-27Per Hedbor  sp[-args+1].u.array->size != 256 )
d010342017-10-11Henrik Grubbström (Grubba)  bad_arg_error("apply_curve",
212c392018-02-25Martin Nilsson  args, 2, "array(int(8bit))", sp-args,
d010342017-10-11Henrik Grubbström (Grubba)  "Bad argument to apply_curve.\n"); for( j = 0; j<256; j++ ) { if( TYPEOF(sp[-args+1].u.array->item[j]) != T_INT ) { bad_arg_error("apply_curve",
212c392018-02-25Martin Nilsson  args, 2, "array(int(8bit))", sp-args,
d010342017-10-11Henrik Grubbström (Grubba)  "Bad argument to apply_curve.\n"); } curve[j] = MINIMUM(sp[-args+1].u.array->item[j].u.integer,255); }
f178822004-05-02Martin Nilsson 
b6a3e02004-05-04Martin Nilsson  MAKE_CONST_STRING(s_red,"red"); MAKE_CONST_STRING(s_green,"green"); MAKE_CONST_STRING(s_blue,"blue"); MAKE_CONST_STRING(s_saturation,"saturation"); MAKE_CONST_STRING(s_value,"value"); MAKE_CONST_STRING(s_hue,"hue");
0f61e92000-07-27Per Hedbor  if( sp[-args].u.string == s_red ) { co = 1; chan = 0; } else if( sp[-args].u.string == s_green ) { co = 1; chan = 1; } else if( sp[-args].u.string == s_blue ) { co = 1; chan = 2; } else if( sp[-args].u.string == s_hue ) { chan = 0; co = 0; } else if( sp[-args].u.string == s_saturation ) { chan = 1; co = 0; } else if( sp[-args].u.string == s_value ) { chan = 2; co = 0; }
f178822004-05-02Martin Nilsson  else Pike_error("Unknown channel in argument 1.\n");
0f61e92000-07-27Per Hedbor  if( co )
13670c2015-05-25Martin Nilsson  {
0f61e92000-07-27Per Hedbor  push_int( THIS->xsize ); push_int( THIS->ysize ); o = clone_object( image_program, 2 );
13670c2015-05-25Martin Nilsson  memcpy( ((struct image*)get_storage(o,image_program))->img, THIS->img,
0f61e92000-07-27Per Hedbor  THIS->xsize*THIS->ysize*sizeof(rgb_group) ); } else { image_rgb_to_hsv( 0 ); o = sp[-1].u.object; sp--; } image_apply_curve_2( o, chan, curve ); if( !co ) { apply( sp[-1].u.object, "hsv_to_rgb", 0 ); stack_swap(); pop_stack(); } return; } case 1: { unsigned char curve[256];
017b572011-10-28Henrik Grubbström (Grubba)  if( TYPEOF(sp[-args]) != T_ARRAY ||
0f61e92000-07-27Per Hedbor  sp[-args].u.array->size != 256 )
de22f72014-08-25Martin Nilsson  bad_arg_error("apply_curve",
212c392018-02-25Martin Nilsson  args, 0, "array(int(8bit))", sp-args,
d010342017-10-11Henrik Grubbström (Grubba)  "Bad argument to apply_curve.\n" );
0f61e92000-07-27Per Hedbor  else
d010342017-10-11Henrik Grubbström (Grubba)  for( j = 0; j<256; j++ ) { if(TYPEOF(sp[-args].u.array->item[j]) != T_INT) { bad_arg_error("apply_curve",
212c392018-02-25Martin Nilsson  args, 0, "array(int(8bit))", sp-args,
d010342017-10-11Henrik Grubbström (Grubba)  "Bad argument to apply_curve.\n"); } curve[j] = MINIMUM(sp[-args].u.array->item[j].u.integer,255); }
0f61e92000-07-27Per Hedbor  pop_n_elems( args ); image_apply_curve_1( curve ); return; } } } /*
624bc31998-04-18Mirar (Pontus Hagland) **! method object gamma(float g)
2849652001-07-19Martin Nilsson **! method object gamma(float gred, float ggreen, float gblue)
624bc31998-04-18Mirar (Pontus Hagland) **! Calculate pixels in image by gamma curve. **! **! Intensity of new pixels are calculated by:<br> **! <i>i</i>' = <i>i</i>^<i>g</i> **! **! For example, you are viewing your image on a screen **! with gamma 2.2. To correct your image to the correct **! gamma value, do something like: **! **! <tt>my_display_image(my_image()->gamma(1/2.2);</tt> **! **! returns a new image object **! **! arg int g **! arg int gred **! arg int ggreen **! arg int gblue **! gamma value **! **! see also: grey, `*, color */ static void img_make_gammatable(COLORTYPE *d,double gamma) { static COLORTYPE last_gammatable[256];
9e53482000-08-06Henrik Grubbström (Grubba)  static double last_gamma;
624bc31998-04-18Mirar (Pontus Hagland)  static int had_gamma=0; if (had_gamma && last_gamma==gamma)
59fc9e2014-09-03Martin Nilsson  memcpy(d,last_gammatable,sizeof(COLORTYPE)*256);
624bc31998-04-18Mirar (Pontus Hagland)  else { int i; COLORTYPE *dd=d; double q=1/255.0; for (i=0; i<256; i++) { double d=pow(i*q,gamma)*255; *(dd++)=testrange(d); }
59fc9e2014-09-03Martin Nilsson  memcpy(last_gammatable,d,sizeof(COLORTYPE)*256);
624bc31998-04-18Mirar (Pontus Hagland)  last_gamma=gamma; had_gamma=1; } } void image_gamma(INT32 args) { INT32 x; rgb_group *s,*d; struct object *o; struct image *img; COLORTYPE _newg[256],_newb[256],*newg,*newb;
36a00c2000-08-15Henrik Grubbström (Grubba)  double gammar=0.0, gammab=0.0, gammag=0.0;
624bc31998-04-18Mirar (Pontus Hagland)  COLORTYPE newr[256];
48b1512018-02-22Martin Nilsson  CHECK_INIT();
30bb592004-05-04Martin Nilsson  if (args==1) {
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(sp[-args]) == T_INT)
8a80a82000-08-08Henrik Grubbström (Grubba)  gammar=gammab=gammag=(double)sp[-args].u.integer;
017b572011-10-28Henrik Grubbström (Grubba)  else if (TYPEOF(sp[-args]) == T_FLOAT)
624bc31998-04-18Mirar (Pontus Hagland)  gammar=gammab=gammag=sp[-args].u.float_number;
30bb592004-05-04Martin Nilsson  else
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("gamma",1,"int|float");
30bb592004-05-04Martin Nilsson  }
624bc31998-04-18Mirar (Pontus Hagland)  else if (args==3) {
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(sp[-args]) == T_INT) gammar=(double)sp[-args].u.integer; else if (TYPEOF(sp[-args]) == T_FLOAT) gammar=sp[-args].u.float_number;
f982742016-01-26Martin Nilsson  else SIMPLE_ARG_TYPE_ERROR("gamma",1,"int|float");
30bb592004-05-04Martin Nilsson 
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(sp[1-args]) == T_INT) gammag=(double)sp[1-args].u.integer; else if (TYPEOF(sp[1-args]) == T_FLOAT) gammag=sp[1-args].u.float_number;
f982742016-01-26Martin Nilsson  else SIMPLE_ARG_TYPE_ERROR("gamma",2,"int|float");
30bb592004-05-04Martin Nilsson 
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(sp[2-args]) == T_INT) gammab=(double)sp[2-args].u.integer; else if (TYPEOF(sp[2-args]) == T_FLOAT) gammab=sp[2-args].u.float_number;
f982742016-01-26Martin Nilsson  else SIMPLE_ARG_TYPE_ERROR("gamma",3,"int|float");
624bc31998-04-18Mirar (Pontus Hagland)  } else
bf4d372018-02-16Martin Nilsson  Pike_error("Illegal number of arguments.\n");
624bc31998-04-18Mirar (Pontus Hagland)  if (gammar==gammab && gammab==gammag) { if (gammar==1.0) /* just copy */ { pop_n_elems(args); image_clone(0); return; } img_make_gammatable(newb=newg=newr,gammar); } else { img_make_gammatable(newr,gammar); img_make_gammatable(newg=_newg,gammag); img_make_gammatable(newb=_newb,gammab); }
13670c2015-05-25Martin Nilsson 
624bc31998-04-18Mirar (Pontus Hagland)  o=clone_object(image_program,0); img=(struct image*)o->storage; *img=*THIS;
20d0552009-04-22Martin Stjernholm  if (!(img->img=malloc(sizeof(rgb_group)*THIS->xsize*THIS->ysize+RGB_VEC_PAD)))
624bc31998-04-18Mirar (Pontus Hagland)  { free_object(o);
7d60af2004-05-19Martin Nilsson  SIMPLE_OUT_OF_MEMORY_ERROR("gamma",
20d0552009-04-22Martin Stjernholm  sizeof(rgb_group)*THIS->xsize*THIS->ysize+RGB_VEC_PAD);
624bc31998-04-18Mirar (Pontus Hagland)  } d=img->img; s=THIS->img; x=THIS->xsize*THIS->ysize; THREADS_ALLOW(); while (x--) { d->r=newr[s->r]; d->g=newg[s->g]; d->b=newb[s->b]; d++; s++; } THREADS_DISALLOW(); pop_n_elems(args); push_object(o); }
6e9d591997-10-24Mirar (Pontus Hagland) /* **! method object write_lsb_rgb(string what) **! method object write_lsb_grey(string what) **! method string read_lsb_rgb() **! method string read_lsb_grey() **! These functions read/write in the least significant bit **! of the image pixel values. The _rgb() functions **! read/write on each of the red, green and blue values, **! and the grey keeps the same lsb on all three. **! **! The string is nullpadded or cut to fit. **! **! returns the current object or the read string **! **! arg string what **! the hidden message */ void image_write_lsb_rgb(INT32 args) {
9e53482000-08-06Henrik Grubbström (Grubba)  int n,b; ptrdiff_t l;
6e9d591997-10-24Mirar (Pontus Hagland)  rgb_group *d; char *s;
391ac52018-08-05Martin Nilsson  get_all_args(NULL, args, "%c", &s);
6e9d591997-10-24Mirar (Pontus Hagland)  l=sp[-args].u.string->len; n=THIS->xsize * THIS->ysize; d=THIS->img; b=128; if (d) while (n--) { if (b==0) { b=128; l--; s++; } if (l>0) d->r=(d->r&254)|(((*s)&b)?1:0); else d->r&=254; b>>=1; if (b==0) { b=128; l--; s++; } if (l>0) d->g=(d->r&254)|(((*s)&b)?1:0); else d->g&=254; b>>=1; if (b==0) { b=128; l--; s++; } if (l>0) d->b=(d->r&254)|(((*s)&b)?1:0); else d->b&=254; b>>=1; d++; } pop_n_elems(args);
13670c2015-05-25Martin Nilsson 
d6ac731998-04-20Henrik Grubbström (Grubba)  ref_push_object(THISOBJ);
6e9d591997-10-24Mirar (Pontus Hagland) } void image_read_lsb_rgb(INT32 args) { int n,b; rgb_group *s; char *d; struct pike_string *ps;
6ee4801998-01-08Mirar (Pontus Hagland)  ps=begin_shared_string((THIS->xsize*THIS->ysize*sizeof(rgb_group)+7)>>3);
6e9d591997-10-24Mirar (Pontus Hagland)  d=ps->str; n=THIS->xsize * THIS->ysize; s=THIS->img; b=128;
21b12a2014-09-03Martin Nilsson  memset(d,0,(THIS->xsize*THIS->ysize*sizeof(rgb_group)+7)>>3);
6e9d591997-10-24Mirar (Pontus Hagland)  if (s) while (n--) { if (b==0) { b=128; d++; } *d|=(s->r&1)*b; b>>=1; if (b==0) { b=128; d++; } *d|=(s->g&1)*b; b>>=1; if (b==0) { b=128; d++; } *d|=(s->b&1)*b; b>>=1; s++; } pop_n_elems(args); push_string(end_shared_string(ps)); } void image_write_lsb_grey(INT32 args) {
9e53482000-08-06Henrik Grubbström (Grubba)  int n,b; ptrdiff_t l;
6e9d591997-10-24Mirar (Pontus Hagland)  rgb_group *d; char *s;
391ac52018-08-05Martin Nilsson  get_all_args(NULL, args, "%c", &s);
6e9d591997-10-24Mirar (Pontus Hagland)  l=sp[-args].u.string->len; n=THIS->xsize * THIS->ysize; d=THIS->img; b=128; if (d) while (n--) { if (b==0) { b=128; l--; s++; }
13670c2015-05-25Martin Nilsson  if (l>0)
6e9d591997-10-24Mirar (Pontus Hagland)  {
13670c2015-05-25Martin Nilsson  d->r=(d->r&254)|(((*s)&b)?1:0); d->g=(d->g&254)|(((*s)&b)?1:0); d->b=(d->b&254)|(((*s)&b)?1:0);
6e9d591997-10-24Mirar (Pontus Hagland)  }
13670c2015-05-25Martin Nilsson  else
6e9d591997-10-24Mirar (Pontus Hagland)  { d->r&=254; d->g&=254; d->b&=254; } b>>=1; d++; } pop_n_elems(args);
13670c2015-05-25Martin Nilsson 
d6ac731998-04-20Henrik Grubbström (Grubba)  ref_push_object(THISOBJ);
6e9d591997-10-24Mirar (Pontus Hagland) } void image_read_lsb_grey(INT32 args) { int n,b; rgb_group *s; char *d; struct pike_string *ps; ps=begin_shared_string((THIS->xsize*THIS->ysize+7)>>3); d=ps->str; n=THIS->xsize * THIS->ysize; s=THIS->img; b=128;
21b12a2014-09-03Martin Nilsson  memset(d,0,(THIS->xsize*THIS->ysize+7)>>3);
6e9d591997-10-24Mirar (Pontus Hagland)  if (s) while (n--) {
a4dacc2001-01-03Mirar (Pontus Hagland)  int q=(s->r&1)+(s->g&1)+(s->b&1); /* vote */
6e9d591997-10-24Mirar (Pontus Hagland)  if (b==0) { b=128; d++; }
a4dacc2001-01-03Mirar (Pontus Hagland)  *d|=(q>1)*b; b>>=1;
6e9d591997-10-24Mirar (Pontus Hagland)  s++; } pop_n_elems(args); push_string(end_shared_string(ps)); }
2d87fb1999-04-12Mirar (Pontus Hagland) /*
7a74cc2014-08-26Per Hedbor **! method string|array cast(string type)
2d87fb1999-04-12Mirar (Pontus Hagland) **! Cast the image to another datatype. Currently supported
13670c2015-05-25Martin Nilsson **! are string ("rgbrgbrgb...") and array (double array
448c201999-04-13Mirar (Pontus Hagland) **! of <ref>Image.Color</ref> objects). **! see also: Image.Color,Image.X
2d87fb1999-04-12Mirar (Pontus Hagland) */ void image_cast(INT32 args) {
68ec3f2014-08-18Martin Nilsson  struct pike_string *type;
7d60af2004-05-19Martin Nilsson 
391ac52018-08-05Martin Nilsson  get_all_args(NULL, args, "%n", &type);
48b1512018-02-22Martin Nilsson  CHECK_INIT();
2d87fb1999-04-12Mirar (Pontus Hagland) 
68ec3f2014-08-18Martin Nilsson  if (type == literal_array_string) { int i,j; rgb_group *s=THIS->img;
2d87fb1999-04-12Mirar (Pontus Hagland) 
68ec3f2014-08-18Martin Nilsson  for (i=0; i<THIS->ysize; i++) { for (j=0; j<THIS->xsize; j++)
2d87fb1999-04-12Mirar (Pontus Hagland)  {
68ec3f2014-08-18Martin Nilsson  _image_make_rgb_color(s->r,s->g,s->b); s++;
2d87fb1999-04-12Mirar (Pontus Hagland)  }
68ec3f2014-08-18Martin Nilsson  f_aggregate(THIS->xsize); } f_aggregate(THIS->ysize);
2d87fb1999-04-12Mirar (Pontus Hagland)  }
68ec3f2014-08-18Martin Nilsson  else if (type == literal_string_string) { push_string(make_shared_binary_string((char *)THIS->img, THIS->xsize*THIS->ysize *sizeof(rgb_group))); } else push_undefined();
2d87fb1999-04-12Mirar (Pontus Hagland) }
3552021997-03-18Mirar (Pontus Hagland) 
bf57c82000-09-10Per Hedbor static void image__sprintf( INT32 args ) { int x;
391ac52018-08-05Martin Nilsson  get_all_args(NULL, args, "%d", &x);
bf57c82000-09-10Per Hedbor  pop_n_elems( 2 ); switch( x ) { case 't':
5e9fc02015-08-18Per Hedbor  push_static_text("Image.Image");
bf57c82000-09-10Per Hedbor  return; case 'O':
5e9fc02015-08-18Per Hedbor  push_static_text( "Image.Image( %d x %d /* %.1fKb */)" );
bf57c82000-09-10Per Hedbor  push_int( THIS->xsize ); push_int( THIS->ysize );
cc7cf42015-10-14Martin Nilsson  push_float( (FLOAT_TYPE)((THIS->xsize * THIS->ysize) / 1024.0 * 3.0) );
bf57c82000-09-10Per Hedbor  f_sprintf( 4 ); return; default: push_int(0); return; } }
e1cc472003-06-07Martin Nilsson /* **! method object grey_blur(int no_pass) **! Works like blur, but only operates on the r color channel.
1e725e2003-07-23Martin Nilsson **! A faster alternative to blur for grey scale images. @[no_pass] **! is the number of times the blur matrix is applied. **! **! <table><tr valign=center> **! <td><illustration> return lena(); </illustration></td> **! <td><illustration> return lena()->grey_blur(1); </illustration></td> **! <td><illustration> return lena()->grey_blur(5); </illustration></td> **! </tr><tr> **! <td>original</td> **! <td>grey_blur(1)</td> **! <td>grey_blur(5)</td> **! </tr></table> **!
e1cc472003-06-07Martin Nilsson **! see also: blur */
d973932001-04-03Per Hedbor static void image_grey_blur( INT32 args ) { /* Basically a exactly like blur, but only uses the r color channel. */ INT_TYPE t; int x, y, cnt; int xe = THIS->xsize; int ye = THIS->ysize; rgb_group *rgb = THIS->img;
017b572011-10-28Henrik Grubbström (Grubba) 
391ac52018-08-05Martin Nilsson  get_all_args(NULL, args, "%I", &t);
118f582018-02-22Martin Nilsson  CHECK_INIT();
d973932001-04-03Per Hedbor  for( cnt=0; cnt<t; cnt++ ) { rgb_group *ro1=NULL, *ro2=NULL, *ro3=rgb; for( y=0; y<ye; y++ ) { ro1 = ro2; ro2 = ro3; ro3 = ( y < ye-1 ) ? rgb+xe*(y+1) : 0; for( x=0; x<xe; x++ ) { int tmp = 0; int n = 0; if( ro1 ) { if( x > 1 ) {n++;tmp += ro1[x-1].r;}; tmp += ro1[x].r; n++; if( x < xe-1 ) {n++;tmp += ro1[x+1].r;}; } if( x > 1 ) {n++;tmp += ro2[x-1].r;}; tmp += ro2[x].r; n++; if( x < xe-1 ) {n++;tmp += ro2[x+1].r;}; if( ro3 ) { if( x > 1 ) {n++;tmp += ro3[x-1].r;}; tmp += ro3[x].r; n++; if( x < xe-1 ) {n++;tmp += ro3[x+1].r;}; } ro2[x].r = ro2[x].g = ro2[x].b = tmp/n; } } } pop_n_elems( args ); ref_push_object( THISOBJ ); }
e1cc472003-06-07Martin Nilsson /* **! method string blur(int no_pass) **! A special case of apply_matrix that creates a blur effect. **! About four times faster than the generic apply_matrix.
1e725e2003-07-23Martin Nilsson **! @[no_pass] is the number of times the blur matrix is applied. **! **! <table><tr valign=center> **! <td><illustration> return lena(); </illustration></td> **! <td><illustration> return lena()->blur(1); </illustration></td> **! <td><illustration> return lena()->blur(5); </illustration></td> **! </tr><tr> **! <td>original</td> **! <td>blur(1)</td> **! <td>blur(5)</td> **! </tr></table> **!
e1cc472003-06-07Martin Nilsson **! see also: apply_matrix, grey_blur */
d973932001-04-03Per Hedbor  static void image_blur( INT32 args ) /* about four times faster than the generic apply matrix for this * special case. */ { INT_TYPE t; int x, y, cnt; int xe = THIS->xsize; int ye = THIS->ysize; rgb_group *rgb = THIS->img; if( args != 1 )
06bd612016-01-26Martin Nilsson  SIMPLE_WRONG_NUM_ARGS_ERROR("blur",1);
d973932001-04-03Per Hedbor  if( !rgb ) Pike_error("This object is not initialized\n");
017b572011-10-28Henrik Grubbström (Grubba) 
de22f72014-08-25Martin Nilsson  if (TYPEOF(sp[-args]) != T_INT)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("blur", 0, "int");
d973932001-04-03Per Hedbor  t = sp[-args].u.integer; /* times */ for( cnt=0; cnt<t; cnt++ ) { rgb_group *ro1=NULL, *ro2=NULL, *ro3=rgb; for( y=0; y<ye; y++ ) { ro1 = ro2; ro2 = ro3; ro3 = ( y < ye-1 ) ? rgb+xe*(y+1) : 0; for( x=0; x<xe; x++ ) { int tmpr=0, tmpg=0, tmpb=0; int n=0; if( ro1 ) { if( x > 1 ) { n++; tmpr += ro1[x-1].r; tmpg += ro1[x-1].g; tmpb += ro1[x-1].b; }; n++; tmpr += ro1[x].r; tmpg += ro1[x].g; tmpb += ro1[x].b; if( x < xe-1 ) { n++; tmpr += ro1[x+1].r; tmpg += ro1[x+1].g; tmpb += ro1[x+1].b; }; } if( x > 1 ) { n++; tmpr += ro2[x-1].r; tmpg += ro2[x-1].g; tmpb += ro2[x-1].b; } n++; tmpr += ro2[x].r; tmpg += ro2[x].g; tmpb += ro2[x].b; if( x < xe-1 ) { n++; tmpr += ro2[x+1].r; tmpg += ro2[x+1].g; tmpb += ro2[x+1].b; } if( ro3 ) { if( x > 1 ) { n++; tmpr += ro3[x-1].r; tmpg += ro3[x-1].g; tmpb += ro3[x-1].b; } n++; tmpr += ro3[x].r; tmpg += ro3[x].g; tmpb += ro3[x].b; if( x < xe-1 ) { n++; tmpr += ro3[x+1].r; tmpg += ro3[x+1].g; tmpb += ro3[x+1].b; } } ro2[x].r = tmpr/n; ro2[x].g = tmpg/n; ro2[x].b = tmpb/n; } } } pop_n_elems( args ); ref_push_object( THISOBJ ); }
fc9d0d1999-06-09Mirar (Pontus Hagland) void image_tobitmap(INT32 args) { int xs; int i,j,left,bit,dbits; struct pike_string *res; unsigned char *d; rgb_group *s;
48b1512018-02-22Martin Nilsson  CHECK_INIT();
fc9d0d1999-06-09Mirar (Pontus Hagland)  pop_n_elems(args); xs=(THIS->xsize+7)>>3; res=begin_shared_string(xs*THIS->ysize); d=(unsigned char *)res->str; s=THIS->img; j=THIS->ysize; while (j--) { i=THIS->xsize; while (i) { left=8; bit=1; dbits=0; while (left-- && i) { if (s->r||s->g||s->b) dbits|=bit; bit<<=1; s++; i--; } *(d++)=(unsigned char)dbits; } } push_string(end_shared_string(res)); }
b13d5d2005-03-15Per Hedbor  /***************** Serialization methods ***********************/
2d07362006-09-11Martin Nilsson 
74dfe82012-12-30Jonas Walldén void image__encode( INT32 UNUSED(args) )
b13d5d2005-03-15Per Hedbor { push_int( THIS->xsize ); push_int( THIS->ysize ); push_string( make_shared_binary_string((char *)THIS->img, THIS->xsize*THIS->ysize *sizeof(rgb_group)) ); f_aggregate( 3 ); } void image__decode( INT32 args ) { struct array *a;
aa420b2005-03-18Henrik Grubbström (Grubba)  int w, h;
64cbc12007-08-10Henrik Grubbström (Grubba)  if( args != 1 ||
017b572011-10-28Henrik Grubbström (Grubba)  TYPEOF(Pike_sp[-1]) != PIKE_T_ARRAY ||
b13d5d2005-03-15Per Hedbor  Pike_sp[-1].u.array->size != 3 ||
017b572011-10-28Henrik Grubbström (Grubba)  TYPEOF((a=Pike_sp[-1].u.array)->item[2]) != PIKE_T_STRING || TYPEOF(a->item[0]) != PIKE_T_INT || TYPEOF(a->item[1]) != PIKE_T_INT )
de22f72014-08-25Martin Nilsson  Pike_error( "Illegal arguments to decode\n");
b13d5d2005-03-15Per Hedbor 
aa420b2005-03-18Henrik Grubbström (Grubba)  w = a->item[0].u.integer; h = a->item[1].u.integer;
b13d5d2005-03-15Per Hedbor 
2d76f22005-05-20Martin Stjernholm  if( w*h*(ptrdiff_t) sizeof(rgb_group) != a->item[2].u.string->len )
b13d5d2005-03-15Per Hedbor  Pike_error("Illegal image data\n"); if( THIS->img ) free( THIS->img ); THIS->xsize = w; THIS->ysize = h;
20d0552009-04-22Martin Stjernholm  THIS->img = xalloc( sizeof(rgb_group)*w*h+RGB_VEC_PAD );
b13d5d2005-03-15Per Hedbor  memcpy( THIS->img, a->item[2].u.string->str, a->item[2].u.string->len ); }
dffabf2014-02-24Per Hedbor static void image__size_object(INT32 UNUSED(args))
a3a0072013-09-18Per Hedbor { INT_TYPE sz = 0; if( THIS->img ) sz = THIS->xsize*THIS->ysize*sizeof(rgb_group)+RGB_VEC_PAD; push_int(sz); }
ab6aec1997-02-11Fredrik Hübinette (Hubbe) /***************** global init etc *****************************/
db75b01999-05-20Mirar (Pontus Hagland) #define tRGB tOr3(tColor,tVoid,tInt) tOr(tInt,tVoid) tOr(tInt,tVoid)
8db2c31999-05-23Mirar (Pontus Hagland) void init_image_image(void)
ab6aec1997-02-11Fredrik Hübinette (Hubbe) {
fd4bcb1999-05-24David Hedbor  int i;
13670c2015-05-25Martin Nilsson  for (i=0; i<CIRCLE_STEPS; i++)
f6b3b52016-02-12Martin Nilsson  circle_sin_table[i]=(int)(4096*sin(((double)i)*2.0* 3.141592653589793/ (double)CIRCLE_STEPS));
f7aabc1999-05-24Mirar (Pontus Hagland) 
90e9781999-01-31Fredrik Hübinette (Hubbe)  ADD_STORAGE(struct image);
13670c2015-05-25Martin Nilsson 
bf57c82000-09-10Per Hedbor  ADD_FUNCTION("_sprintf", image__sprintf, tFunc(tInt , tString), 0 );
a3a0072013-09-18Per Hedbor  ADD_FUNCTION("_size_object", image__size_object, tFunc(tVoid,tInt), 0);
b13d5d2005-03-15Per Hedbor  ADD_FUNCTION("_encode", image__encode, tFunc(tVoid,tArray), 0 ); ADD_FUNCTION("_decode", image__decode, tFunc(tArray,tVoid), 0 );
db75b01999-05-20Mirar (Pontus Hagland)  ADD_FUNCTION("create",image_create,
a63c362011-11-11Henrik Grubbström (Grubba)  tOr3(tFunc(tOr(tInt,tVoid) tOr(tInt,tVoid) tRGB,tVoid), tFunc(tObj, tVoid), tFuncV(tInt tInt tString,tMixed,tVoid)),0);
db75b01999-05-20Mirar (Pontus Hagland)  ADD_FUNCTION("clone",image_clone,
f7eec11999-11-26Per Hedbor  tOr3(tFunc(tInt tInt tInt tInt tRGB,tObj), tFunc(tRGB,tObj), tFunc(tNone,tObj)),0);
db75b01999-05-20Mirar (Pontus Hagland)  ADD_FUNCTION("new",image_clone, /* alias */
39fc651999-11-25Martin Stjernholm  tFunc(tOr(tInt,tVoid) tOr(tInt,tVoid) tRGB,tObj),0);
db75b01999-05-20Mirar (Pontus Hagland)  ADD_FUNCTION("clear",image_clear, tFunc(tRGB,tObj),0);
a7a3c91999-05-24Mirar (Pontus Hagland) 
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("cast",image_cast,
7a74cc2014-08-26Per Hedbor  tFunc(tStr,tOr(tArray,tStr)),ID_PROTECTED);
07228a1999-06-19Fredrik Hübinette (Hubbe)  ADD_FUNCTION("tobitmap",image_tobitmap,tFunc(tNone,tStr),0);
aba33e1997-03-20Mirar (Pontus Hagland) 
aa71011997-03-18Mirar (Pontus Hagland) 
db75b01999-05-20Mirar (Pontus Hagland)  ADD_FUNCTION("copy",image_copy,
13670c2015-05-25Martin Nilsson  tFunc(tOr(tVoid,tInt) tOr(tVoid,tInt) tOr(tVoid,tInt)
db75b01999-05-20Mirar (Pontus Hagland)  tOr(tVoid,tInt) tRGB,tObj),0);
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("autocrop",image_autocrop,
45f8cd2000-12-03Mirar (Pontus Hagland)  tFuncV(tNone,tOr(tVoid,tInt),tObj),0);
7383191999-06-21Mirar (Pontus Hagland)  ADD_FUNCTION("find_autocrop",image_find_autocrop,
45f8cd2000-12-03Mirar (Pontus Hagland)  tFuncV(tNone,tOr(tVoid,tInt),tArr(tInt)),0);
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("scale",image_scale, tFunc(tOr(tInt,tFlt) tOr3(tInt,tFlt,tVoid),tObj),0);
d6c5352000-04-09Per Hedbor  ADD_FUNCTION("bitscale",image_bitscale, tFunc(tOr(tInt,tFlt) tOr3(tInt,tFlt,tVoid),tObj),0);
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("translate",image_translate, tFunc(tOr(tInt,tFlt) tOr(tInt,tFlt),tObj),0); ADD_FUNCTION("translate_expand",image_translate_expand, tFunc(tOr(tInt,tFlt) tOr(tInt,tFlt),tObj),0); ADD_FUNCTION("paste",image_paste, tFunc(tObj tOr(tInt,tVoid) tOr(tInt,tVoid),tObj),0); ADD_FUNCTION("paste_alpha",image_paste_alpha, tFunc(tObj tInt tOr(tInt,tVoid) tOr(tInt,tVoid),tObj),0); ADD_FUNCTION("paste_mask",image_paste_mask, tFunc(tObj tObj tOr(tInt,tVoid) tOr(tInt,tVoid),tObj),0); ADD_FUNCTION("paste_alpha_color",image_paste_alpha_color,
f6dbf61999-05-20Mirar (Pontus Hagland)  tOr6(tFunc(tObj tInt tInt,tObj), tFunc(tObj tInt tInt tInt,tObj), tFunc(tObj tInt tInt tInt tInt tInt,tObj), tFunc(tObj tColor tInt tInt,tObj), tFunc(tObj tColor,tObj), tFunc(tObj,tObj)),0);
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("setcolor",image_setcolor,
f7eec11999-11-26Per Hedbor  tFunc(tInt tInt tInt tOr(tInt,tVoid),tObj),0);
db75b01999-05-20Mirar (Pontus Hagland)  ADD_FUNCTION("setpixel",image_setpixel, tFunc(tInt tInt tRGB,tObj),0);
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("getpixel",image_getpixel, tFunc(tInt tInt,tArr(tInt)),0);
db75b01999-05-20Mirar (Pontus Hagland)  ADD_FUNCTION("line",image_line, tFunc(tInt tInt tInt tInt tRGB,tObj),0); ADD_FUNCTION("circle",image_circle, tFunc(tInt tInt tInt tInt tRGB,tObj),0); ADD_FUNCTION("box",image_box, tFunc(tInt tInt tInt tInt tRGB,tObj),0);
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("tuned_box",image_tuned_box, tFunc(tInt tInt tInt tInt tArray,tObj),0); ADD_FUNCTION("gradients",image_gradients,
07228a1999-06-19Fredrik Hübinette (Hubbe)  tFuncV(tNone,tOr(tArr(tInt),tFlt),tObj),0);
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("polygone",image_polyfill,
07228a1999-06-19Fredrik Hübinette (Hubbe)  tFuncV(tNone,tArr(tOr(tFlt,tInt)),tObj),0);
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("polyfill",image_polyfill,
07228a1999-06-19Fredrik Hübinette (Hubbe)  tFuncV(tNone,tArr(tOr(tFlt,tInt)),tObj),0);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
db75b01999-05-20Mirar (Pontus Hagland)  ADD_FUNCTION("gray",image_grey, tFunc(tRGB,tObj),0); ADD_FUNCTION("grey",image_grey, tFunc(tRGB,tObj),0); ADD_FUNCTION("color",image_color, tFunc(tRGB,tObj),0); ADD_FUNCTION("change_color",image_change_color, tOr(tFunc(tInt tInt tInt tRGB,tObj), tFunc(tColor tRGB,tObj)),0); ADD_FUNCTION("invert",image_invert, tFunc(tRGB,tObj),0); ADD_FUNCTION("threshold",image_threshold,
7fee4b1999-07-04Mirar (Pontus Hagland)  tFunc(tOr(tInt,tRGB),tObj),0);
db75b01999-05-20Mirar (Pontus Hagland)  ADD_FUNCTION("distancesq",image_distancesq, tFunc(tRGB,tObj),0);
e8369d1997-05-14Per Hedbor 
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("rgb_to_hsv",image_rgb_to_hsv, tFunc(tVoid,tObj),0); ADD_FUNCTION("hsv_to_rgb",image_hsv_to_rgb, tFunc(tVoid,tObj),0);
9e2b662004-07-08Marcus Comstedt  ADD_FUNCTION("rgb_to_yuv",image_rgb_to_yuv, tFunc(tVoid,tObj),0); ADD_FUNCTION("yuv_to_rgb",image_yuv_to_rgb, tFunc(tVoid,tObj),0);
e8369d1997-05-14Per Hedbor 
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("select_from",image_select_from,
394ac22002-04-04Henrik Grubbström (Grubba)  tFunc(tInt tInt tOr(tInt, tVoid),tObj),0);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("apply_matrix",image_apply_matrix, tFuncV(tArr(tArr(tOr(tInt,tArr(tInt)))),tOr(tVoid,tInt),tObj),0);
d973932001-04-03Per Hedbor  ADD_FUNCTION("grey_blur",image_grey_blur,tFunc(tInt,tObj),0); ADD_FUNCTION("blur",image_blur,tFunc(tInt,tObj),0);
13670c2015-05-25Martin Nilsson 
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("outline",image_outline, tOr5(tFunc(tOr(tVoid,tArr(tArr(tInt))),tObj), tFunc(tArr(tArr(tInt)) tInt tInt tInt tOr(tVoid,tInt),tObj), tFunc(tArr(tArr(tInt)) tInt tInt tInt tInt tInt tInt tOr(tVoid,tInt),tObj), tFunc(tInt tInt tInt tOr(tVoid,tInt),tObj), tFunc(tInt tInt tInt tInt tInt tInt tOr(tVoid,tInt),tObj)),0); ADD_FUNCTION("outline_mask",image_outline_mask, tOr(tFunc(tOr(tVoid,tArr(tArr(tInt))),tObj), tFunc(tArr(tArr(tInt)) tInt tInt tInt,tObj)),0); ADD_FUNCTION("modify_by_intensity",image_modify_by_intensity,
e568552000-09-15Mirar (Pontus Hagland)  tFuncV(tInt tInt tInt tOr(tInt,tColor) tOr(tInt,tColor), tOr(tInt,tColor),tObj),0);
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("gamma",image_gamma, tOr(tFunc(tOr(tFlt,tInt),tObj), tFunc(tOr(tFlt,tInt) tOr(tFlt,tInt) tOr(tFlt,tInt),tObj)),0);
0f61e92000-07-27Per Hedbor  ADD_FUNCTION("apply_curve",image_apply_curve, tOr3( tFunc(tArr(tInt) tArr(tInt) tArr(tInt),tObj), tFunc(tArr(tInt),tObj), tFunc(tString tArr(tInt),tObj) ), 0);
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("rotate_ccw",image_ccw,
07228a1999-06-19Fredrik Hübinette (Hubbe)  tFunc(tNone,tObj),0);
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("rotate_cw",image_cw,
07228a1999-06-19Fredrik Hübinette (Hubbe)  tFunc(tNone,tObj),0);
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("mirrorx",image_mirrorx,
07228a1999-06-19Fredrik Hübinette (Hubbe)  tFunc(tNone,tObj),0);
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("mirrory",image_mirrory,
07228a1999-06-19Fredrik Hübinette (Hubbe)  tFunc(tNone,tObj),0);
db75b01999-05-20Mirar (Pontus Hagland)  ADD_FUNCTION("skewx",image_skewx, tFunc(tOr(tInt,tFlt) tRGB,tObj),0); ADD_FUNCTION("skewy",image_skewy, tFunc(tOr(tInt,tFlt) tRGB,tObj),0); ADD_FUNCTION("skewx_expand",image_skewx_expand, tFunc(tOr(tInt,tFlt) tRGB,tObj),0); ADD_FUNCTION("skewy_expand",image_skewy_expand, tFunc(tOr(tInt,tFlt) tRGB,tObj),0); ADD_FUNCTION("rotate",image_rotate, tFunc(tOr(tInt,tFlt) tRGB,tObj),0); ADD_FUNCTION("rotate_expand",image_rotate_expand, tFunc(tOr(tInt,tFlt) tRGB,tObj),0);
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("xsize",image_xsize,
07228a1999-06-19Fredrik Hübinette (Hubbe)  tFunc(tNone,tInt),0);
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("ysize",image_ysize,
07228a1999-06-19Fredrik Hübinette (Hubbe)  tFunc(tNone,tInt),0);
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("noise",image_noise, tFunc(tArr(tOr3(tInt,tFloat,tColor))
13670c2015-05-25Martin Nilsson  tOr(tFlt,tVoid) tOr(tFlt,tVoid)
29bbf21999-04-13Mirar (Pontus Hagland)  tOr(tFlt,tVoid) tOr(tFlt,tVoid),tObj),0); ADD_FUNCTION("turbulence",image_turbulence, tFunc(tArr(tOr3(tInt,tFloat,tColor))
13670c2015-05-25Martin Nilsson  tOr(tInt,tVoid) tOr(tFlt,tVoid)
29bbf21999-04-13Mirar (Pontus Hagland)  tOr(tFlt,tVoid) tOr(tFlt,tVoid) tOr(tFlt,tVoid),tObj),0); ADD_FUNCTION("random",image_random, tFunc(tOr(tVoid,tInt),tObj),0);
8a4dbb1999-07-16Mirar (Pontus Hagland)  ADD_FUNCTION("randomgrey",image_randomgrey, tFunc(tOr(tVoid,tInt),tObj),0);
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("dct",image_dct,
07228a1999-06-19Fredrik Hübinette (Hubbe)  tFunc(tNone,tObj),0);
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("`-",image_operator_minus, tFunc(tOr3(tObj,tArr(tInt),tInt),tObj),0); ADD_FUNCTION("`+",image_operator_plus, tFunc(tOr3(tObj,tArr(tInt),tInt),tObj),0); ADD_FUNCTION("`*",image_operator_multiply, tFunc(tOr3(tObj,tArr(tInt),tInt),tObj),0);
2a406a1999-04-21Mirar (Pontus Hagland)  ADD_FUNCTION("`/",image_operator_divide, tFunc(tOr3(tObj,tArr(tInt),tInt),tObj),0);
8e39901999-04-22Mirar (Pontus Hagland)  ADD_FUNCTION("`%",image_operator_rest, tFunc(tOr3(tObj,tArr(tInt),tInt),tObj),0);
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("`&",image_operator_minimum, tFunc(tOr3(tObj,tArr(tInt),tInt),tObj),0); ADD_FUNCTION("`|",image_operator_maximum, tFunc(tOr3(tObj,tArr(tInt),tInt),tObj),0); ADD_FUNCTION("`==",image_operator_equal, tFunc(tOr3(tObj,tArr(tInt),tInt),tInt),0); ADD_FUNCTION("`<",image_operator_lesser, tFunc(tOr3(tObj,tArr(tInt),tInt),tInt),0); ADD_FUNCTION("`>",image_operator_greater, tFunc(tOr3(tObj,tArr(tInt),tInt),tInt),0); ADD_FUNCTION("min",image_min,
07228a1999-06-19Fredrik Hübinette (Hubbe)  tFunc(tNone,tArr(tInt)),0);
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("max",image_max,
07228a1999-06-19Fredrik Hübinette (Hubbe)  tFunc(tNone,tArr(tInt)),0);
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("sum",image_sum,
07228a1999-06-19Fredrik Hübinette (Hubbe)  tFunc(tNone,tArr(tInt)),0);
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("sumf",image_sumf,
07228a1999-06-19Fredrik Hübinette (Hubbe)  tFunc(tNone,tArr(tInt)),0);
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("average",image_average,
07228a1999-06-19Fredrik Hübinette (Hubbe)  tFunc(tNone,tArr(tInt)),0);
13670c2015-05-25Martin Nilsson 
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("find_min",image_find_min,
07228a1999-06-19Fredrik Hübinette (Hubbe)  tOr(tFunc(tNone,tArr(tInt)),
29bbf21999-04-13Mirar (Pontus Hagland)  tFunc(tInt tInt tInt,tArr(tInt))),0); ADD_FUNCTION("find_max",image_find_max,
07228a1999-06-19Fredrik Hübinette (Hubbe)  tOr(tFunc(tNone,tArr(tInt)),
29bbf21999-04-13Mirar (Pontus Hagland)  tFunc(tInt tInt tInt,tArr(tInt))),0);
13670c2015-05-25Martin Nilsson 
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("read_lsb_rgb",image_read_lsb_rgb,
a4dacc2001-01-03Mirar (Pontus Hagland)  tFunc(tNone,tString),0);
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("write_lsb_rgb",image_write_lsb_rgb,
a4dacc2001-01-03Mirar (Pontus Hagland)  tFunc(tString,tObj),0); ADD_FUNCTION("read_lsb_grey",image_read_lsb_grey, tFunc(tNone,tString),0); ADD_FUNCTION("write_lsb_grey",image_write_lsb_grey, tFunc(tString,tObj),0);
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("orient4",image_orient4,
07228a1999-06-19Fredrik Hübinette (Hubbe)  tFunc(tNone,tArr(tObj)),0);
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("orient",image_orient,
07228a1999-06-19Fredrik Hübinette (Hubbe)  tFunc(tNone,tObj),0);
13670c2015-05-25Martin Nilsson 
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("phaseh",image_phaseh,
07228a1999-06-19Fredrik Hübinette (Hubbe)  tFunc(tNone,tObj),0);
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("phasev",image_phasev,
07228a1999-06-19Fredrik Hübinette (Hubbe)  tFunc(tNone,tObj),0);
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("phasehv",image_phasehv,
07228a1999-06-19Fredrik Hübinette (Hubbe)  tFunc(tNone,tObj),0);
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("phasevh",image_phasevh,
07228a1999-06-19Fredrik Hübinette (Hubbe)  tFunc(tNone,tObj),0);
db75b01999-05-20Mirar (Pontus Hagland) 
abb4541999-03-03Mirar (Pontus Hagland)  ADD_FUNCTION("match_phase",image_match_phase,
29bbf21999-04-13Mirar (Pontus Hagland)  tOr4(tFunc(tOr(tInt,tFloat) tObj,tObj), tFunc(tOr(tInt,tFloat) tObj tObj tObj,tObj), tFunc(tOr(tInt,tFloat) tObj tObj tInt,tObj), tFunc(tOr(tInt,tFloat) tObj tObj tObj tObj tInt,tObj)),0);
abb4541999-03-03Mirar (Pontus Hagland)  ADD_FUNCTION("match_norm",image_match_norm,
29bbf21999-04-13Mirar (Pontus Hagland)  tOr4(tFunc(tOr(tInt,tFloat) tObj,tObj), tFunc(tOr(tInt,tFloat) tObj tObj tObj,tObj), tFunc(tOr(tInt,tFloat) tObj tObj tInt,tObj), tFunc(tOr(tInt,tFloat) tObj tObj tObj tObj tInt,tObj)),0);
abb4541999-03-03Mirar (Pontus Hagland)  ADD_FUNCTION("match_norm_corr",image_match_norm_corr,
29bbf21999-04-13Mirar (Pontus Hagland)  tOr4(tFunc(tOr(tInt,tFloat) tObj,tObj), tFunc(tOr(tInt,tFloat) tObj tObj tObj,tObj), tFunc(tOr(tInt,tFloat) tObj tObj tInt,tObj), tFunc(tOr(tInt,tFloat) tObj tObj tObj tObj tInt,tObj)),0);
abb4541999-03-03Mirar (Pontus Hagland)  ADD_FUNCTION("match",image_match,
29bbf21999-04-13Mirar (Pontus Hagland)  tOr4(tFunc(tOr(tInt,tFloat) tObj,tObj), tFunc(tOr(tInt,tFloat) tObj tObj tObj,tObj), tFunc(tOr(tInt,tFloat) tObj tObj tInt,tObj), tFunc(tOr(tInt,tFloat) tObj tObj tObj tObj tInt,tObj)),0);
13670c2015-05-25Martin Nilsson 
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("apply_max",image_apply_max, tFuncV(tArr(tArr(tOr(tInt,tArr(tInt)))), tOr(tVoid,tInt),tObj),0); ADD_FUNCTION("make_ascii",image_make_ascii, tFunc(tObj tObj tObj tObj tOr(tInt,tVoid),tStr),0);
13670c2015-05-25Martin Nilsson 
29bbf21999-04-13Mirar (Pontus Hagland)  ADD_FUNCTION("test",image_test, tFunc(tOr(tVoid,tInt),tObj),0);
286fef1998-02-15Henrik Wallin 
3df84b2017-07-19Martin Nilsson #ifdef PIKE_NULL_IS_SPECIAL
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  set_init_callback(init_image_struct);
3df84b2017-07-19Martin Nilsson #endif
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  set_exit_callback(exit_image_struct);
1c31fd2002-05-10Per Hedbor  #ifndef FAKE_DYNAMIC_LOAD /* Added by per: Export all functions needed by _Image_GIF */
f58ff62002-05-11Per Hedbor  PIKE_MODULE_EXPORT(Image, image_lay ); PIKE_MODULE_EXPORT(Image, image_colortable_write_rgb ); PIKE_MODULE_EXPORT(Image, image_colortable_size ); PIKE_MODULE_EXPORT(Image, image_colortable_index_8bit_image ); PIKE_MODULE_EXPORT(Image, image_colortable_internal_floyd_steinberg );
1c31fd2002-05-10Per Hedbor #endif
f178822004-05-02Martin Nilsson  s_red=0; s_green=0; s_blue=0; s_value=0; s_saturation=0; s_hue=0;
aa67372004-05-03Martin Nilsson  s_grey=0; s_rgb=0; s_cmyk=0;
fa63d92006-09-20Henrik Grubbström (Grubba)  s_adjusted_cmyk=0;
aa67372004-05-03Martin Nilsson  s_cmy=0; s_test=0; s_gradients=0; s_noise=0; s_turbulence=0; s_random=0; s_randomgrey=0; s_tuned_box=0;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) }
13670c2015-05-25Martin Nilsson void exit_image_image(void)
a8df691999-04-15Henrik Grubbström (Grubba) {
ab6aec1997-02-11Fredrik Hübinette (Hubbe) }