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. */
286fef1998-02-15Henrik Wallin  /* **! module Image
448c201999-04-13Mirar (Pontus Hagland) **! class Image
286fef1998-02-15Henrik Wallin */ #include "global.h" #include <math.h> #include <ctype.h> #include "pike_macros.h" #include "object.h" #include "interpret.h" #include "svalue.h"
3cf2691998-03-11Mirar (Pontus Hagland) #include "threads.h"
b2d3e42000-12-01Fredrik Hübinette (Hubbe) #include "pike_error.h"
286fef1998-02-15Henrik Wallin  #include "image.h" #include <builtin_functions.h>
6dc2772000-07-28Fredrik Hübinette (Hubbe) 
6ad2372002-05-11Martin Nilsson #define sp Pike_sp
286fef1998-02-15Henrik Wallin extern struct program *image_program; #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)
286fef1998-02-15Henrik Wallin  #define testrange(x) MAXIMUM(MINIMUM((x),255),0) static const double c0=0.70710678118654752440;
d0224e1998-02-15Mirar (Pontus Hagland) static const double my_PI=3.14159265358979323846;
286fef1998-02-15Henrik Wallin 
3b8dcd1998-03-19Fredrik Hübinette (Hubbe) #if 0
3cf2691998-03-11Mirar (Pontus Hagland) #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, (long)r.ru_utime.tv_sec,(long)r.ru_utime.tv_usec,
13670c2015-05-25Martin Nilsson 
3cf2691998-03-11Mirar (Pontus Hagland)  (long)(((r.ru_utime.tv_usec-rold.ru_utime.tv_usec<0)?-1:0) +r.ru_utime.tv_sec-rold.ru_utime.tv_sec), (long)(((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
286fef1998-02-15Henrik Wallin /*
2849652001-07-19Martin Nilsson **! method object orient(void|array(object) something)
3cf2691998-03-11Mirar (Pontus Hagland) **! method array(object) orient4() **! Draws images describing the orientation **! of the current image.
286fef1998-02-15Henrik Wallin **!
e3e3821998-03-23Henrik Wallin **! <tt>orient</tt> gives an HSV image
3cf2691998-03-11Mirar (Pontus Hagland) **! (run a <ref>hsv_to_rgb</ref> pass on it **! to get a viewable image). **! corresponding to the angle of the **! orientation: **! <pre> | / - \
e3e3821998-03-23Henrik Wallin **! hue= 0 64 128 192 (=red in an hsv image)
3cf2691998-03-11Mirar (Pontus Hagland) **! purple cyan green red **! </pre> **! Red, green and blue channels are added **! and not compared separately.
13670c2015-05-25Martin Nilsson **!
e3e3821998-03-23Henrik Wallin **! If you first use orient4 you can give its **! output as input to this function.
286fef1998-02-15Henrik Wallin **!
3cf2691998-03-11Mirar (Pontus Hagland) **! The <tt>orient4</tt> function gives back **! 4 image objects, corresponding to the **! amount of different directions, see above.
286fef1998-02-15Henrik Wallin **!
e3e3821998-03-23Henrik Wallin **! returns an image or an array of the four new image objects
286fef1998-02-15Henrik Wallin **!
3cf2691998-03-11Mirar (Pontus Hagland) **! note **! experimental status; may not be exact the same **! output in later versions
286fef1998-02-15Henrik Wallin */
01b9212016-01-12Per Hedbor static inline int my_abs(int a) { return (a<0)?-a:a; }
3cf2691998-03-11Mirar (Pontus Hagland)  static void _image_orient(struct image *source,
2a2bc02007-01-17Henrik Grubbström (Grubba)  struct object *o[5], struct image *img[5])
3cf2691998-03-11Mirar (Pontus Hagland) { int i; struct { int x,y; } or[4]={ {1,0}, {1,1}, {0,1}, {-1,1} }; int x,y; for (i=0; i<5; i++) { push_int(source->xsize); push_int(source->ysize); o[i]=clone_object(image_program,2);
13b5ed2014-05-26Per Hedbor  img[i]=get_storage(o[i],image_program);
3cf2691998-03-11Mirar (Pontus Hagland)  push_object(o[i]); }
13670c2015-05-25Martin Nilsson THREADS_ALLOW();
3cf2691998-03-11Mirar (Pontus Hagland) CHRONO("start"); for (i=0; i<4; i++) /* four directions */ { rgb_group *d=img[i]->img; rgb_group *s=source->img; int xz=source->xsize; int yz=source->ysize; int xd=or[i].x; int yd=or[i].y; for(x=1; x<xz-1; x++) for(y=1; y<yz-1; y++) { #define FOOBAR(CO) \ d[x+y*xz].CO \ = \ (COLORTYPE) \
07228a1999-06-19Fredrik Hübinette (Hubbe)  my_abs( s[(x+xd)+(y+yd)*xz].CO - s[(x-xd)+(y-yd)*xz].CO )
3cf2691998-03-11Mirar (Pontus Hagland)  FOOBAR(r); FOOBAR(g); FOOBAR(b); #undef FOOBAR } } CHRONO("end");
13670c2015-05-25Martin Nilsson THREADS_DISALLOW();
3cf2691998-03-11Mirar (Pontus Hagland) }
286fef1998-02-15Henrik Wallin  void image_orient(INT32 args) {
3cf2691998-03-11Mirar (Pontus Hagland)  struct object *o[5];
e3e3821998-03-23Henrik Wallin  struct image *img[5],*this,*img1;
3cf2691998-03-11Mirar (Pontus Hagland)  int n; rgb_group *d,*s1,*s2,*s3,*s0;
4e73012000-08-09Henrik Grubbström (Grubba)  double mag;
e3e3821998-03-23Henrik Wallin  int i, w, h;
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  if (!THIS->img) { Pike_error("Called Image.Image object is not initialized\n");; return; }
3cf2691998-03-11Mirar (Pontus Hagland)  this=THIS;
e3e3821998-03-23Henrik Wallin  if (args) {
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(sp[-args]) == T_INT)
e3e3821998-03-23Henrik Wallin  mag=sp[-args].u.integer;
017b572011-10-28Henrik Grubbström (Grubba)  else if (TYPEOF(sp[-args]) == T_FLOAT)
e3e3821998-03-23Henrik Wallin  mag=sp[-args].u.float_number;
1783ea1998-04-13Henrik Grubbström (Grubba)  else {
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("orient",1,"int|float");
9282fd2015-09-27Martin Nilsson  UNREACHABLE(mag=0.0);
1783ea1998-04-13Henrik Grubbström (Grubba)  }
e3e3821998-03-23Henrik Wallin  } else mag=1.0; if (args==1) pop_n_elems(args);
3cf2691998-03-11Mirar (Pontus Hagland) 
e3e3821998-03-23Henrik Wallin  if (args>1) {
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(sp[1-args]) != T_ARRAY)
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("orient",2,"array");
e3e3821998-03-23Henrik Wallin  if (sp[1-args].u.array->size!=4)
de22f72014-08-25Martin Nilsson  Pike_error("The array given as argument 2 to orient do not have size 4\n");
e3e3821998-03-23Henrik Wallin  for(i=0; i<4; i++)
017b572011-10-28Henrik Grubbström (Grubba)  if ((TYPEOF(sp[1-args].u.array->item[i]) != T_OBJECT) ||
e3e3821998-03-23Henrik Wallin  (!(sp[1-args].u.array->item[i].u.object)) || (sp[1-args].u.array->item[i].u.object->prog!=image_program))
de22f72014-08-25Martin Nilsson  Pike_error("The array given as argument 2 to orient do not contain images\n");
e3e3821998-03-23Henrik Wallin  img1=(struct image*)sp[1-args].u.array->item[0].u.object->storage; w=this->xsize; h=this->ysize; for(i=0; i<4; i++) { img1=(struct image*)sp[1-args].u.array->item[i].u.object->storage; if ((img1->xsize!=w)|| (img1->ysize!=h))
de22f72014-08-25Martin Nilsson  Pike_error("The images in the array given as argument 2 to orient have different sizes\n");
e3e3821998-03-23Henrik Wallin  }
13670c2015-05-25Martin Nilsson  for(i=0; i<4; i++)
13b5ed2014-05-26Per Hedbor  img[i]=get_storage(sp[1-args].u.array->item[i].u.object,image_program);
e3e3821998-03-23Henrik Wallin  pop_n_elems(args); push_int(this->xsize); push_int(this->ysize); o[4]=clone_object(image_program,2);
13b5ed2014-05-26Per Hedbor  img[4]=get_storage(o[4],image_program);
e3e3821998-03-23Henrik Wallin  push_object(o[4]); w=1; } else { _image_orient(this,o,img); w=0; }
3cf2691998-03-11Mirar (Pontus Hagland)  s0=img[0]->img; s1=img[1]->img; s2=img[2]->img; s3=img[3]->img; d=img[4]->img;
13670c2015-05-25Martin Nilsson THREADS_ALLOW();
3cf2691998-03-11Mirar (Pontus Hagland) CHRONO("begin hsv..."); n=this->xsize*this->ysize; while (n--) { /* Första färg, sista mörkhet */
13670c2015-05-25Martin Nilsson  double j=(s0->r+s0->g+s0->b-s2->r-s2->g-s2->b)/3.0;
3cf2691998-03-11Mirar (Pontus Hagland)  /* riktning - - riktning | */
4e73012000-08-09Henrik Grubbström (Grubba)  double h=(s1->r+s1->g+s1->b-s3->r-s3->g-s3->b)/3.0;
3cf2691998-03-11Mirar (Pontus Hagland)  /* riktning \ - riktning / */ int z,w;
04a97d2016-02-12Martin Nilsson  if (my_abs((int)h) > my_abs((int)j))
bb7a842000-08-11Henrik Grubbström (Grubba)  if (h) {
04a97d2016-02-12Martin Nilsson  z = -(int)(32*(j/h)+(h>0)*128+64); w = my_abs((int)h);
bb7a842000-08-11Henrik Grubbström (Grubba)  }
3cf2691998-03-11Mirar (Pontus Hagland)  else z=0,w=0;
bb7a842000-08-11Henrik Grubbström (Grubba)  else {
f9105d2014-01-11Arne Goedeke  if (j) {
04a97d2016-02-12Martin Nilsson  z = -(int)(-32*(h/j)+(j>0)*128+128); w = my_abs((int)j);
f9105d2014-01-11Arne Goedeke  } else z=0,w=0;
bb7a842000-08-11Henrik Grubbström (Grubba)  }
3cf2691998-03-11Mirar (Pontus Hagland)  d->r=(COLORTYPE)z;
13670c2015-05-25Martin Nilsson  d->g=255;
bb7a842000-08-11Henrik Grubbström (Grubba)  d->b = MINIMUM(DOUBLE_TO_COLORTYPE(w*mag), 255);
3cf2691998-03-11Mirar (Pontus Hagland)  d++; s0++; s1++; s2++; s3++; } CHRONO("end hsv..."); THREADS_DISALLOW();
e3e3821998-03-23Henrik Wallin  if (!w) {
50ea682003-03-14Henrik Grubbström (Grubba)  add_ref(o[4]);
e3e3821998-03-23Henrik Wallin  pop_n_elems(5); push_object(o[4]); }
3cf2691998-03-11Mirar (Pontus Hagland) }
286fef1998-02-15Henrik Wallin 
3cf2691998-03-11Mirar (Pontus Hagland)  void image_orient4(INT32 args) { struct object *o[5]; struct image *img[5];
13670c2015-05-25Martin Nilsson 
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  if (!THIS->img) { Pike_error("Called Image.Image object is not initialized\n");; return; }
3cf2691998-03-11Mirar (Pontus Hagland)  pop_n_elems(args); _image_orient(THIS,o,img); pop_n_elems(1); f_aggregate(4);
286fef1998-02-15Henrik Wallin }