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. */
c43fc11999-03-01Henrik Wallin  /* **! module Image
448c201999-04-13Mirar (Pontus Hagland) **! class Image
c43fc11999-03-01Henrik Wallin */ #include "global.h" #include <math.h> #include <ctype.h> #include "stralloc.h" #include "pike_macros.h" #include "object.h" #include "interpret.h" #include "svalue.h" #include "threads.h"
b2d3e42000-12-01Fredrik Hübinette (Hubbe) #include "pike_error.h"
06e0102005-08-14Martin Nilsson #include "module_support.h"
c43fc11999-03-01Henrik Wallin  #include "image.h"
6dc2772000-07-28Fredrik Hübinette (Hubbe) 
6ad2372002-05-11Martin Nilsson #define sp Pike_sp
c43fc11999-03-01Henrik 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)
c43fc11999-03-01Henrik Wallin  static const double c0=0.70710678118654752440; static const double my_PI=3.14159265358979323846; #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, (long)r.ru_utime.tv_sec,(long)r.ru_utime.tv_usec,
13670c2015-05-25Martin Nilsson 
c43fc11999-03-01Henrik Wallin  (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 /* **! method object phaseh() **! method object phasev()
d3c84b1999-03-22Henrik Wallin **! method object phasevh() **! method object phasehv()
c43fc11999-03-01Henrik Wallin **! Draws images describing the phase **! of the current image. phaseh gives the **! horizontal phase and phasev the vertical **! phase. **! **! <tt>phaseh</tt> gives an image
2158f21999-07-02Mirar (Pontus Hagland) **! where
c43fc11999-03-01Henrik Wallin **! <pre> **! max falling min rising
13670c2015-05-25Martin Nilsson **! value= 0 64 128 192
c43fc11999-03-01Henrik Wallin **! </pre>
13670c2015-05-25Martin Nilsson **!
c43fc11999-03-01Henrik Wallin **! 0 is set if there is no way to determine **! if it is rising or falling. This is done **! for the every red, green and blue part of **! the image.
13670c2015-05-25Martin Nilsson **!
c43fc11999-03-01Henrik Wallin **! Phase images can be used to create ugly **! effects or to find meta-information **! in the orginal image.
2158f21999-07-02Mirar (Pontus Hagland) **! **! <table border=0> **! <tr> **! <td><illustration> return lena(); </illustration></td> **! <td><illustration> return lena()->phaseh(); </illustration></td> **! <td><illustration> return lena()->phasev(); </illustration></td> **! <td><illustration> return lena()->phasevh(); </illustration></td> **! <td><illustration> return lena()->phasehv(); </illustration></td> **! </tr> **! <tr> **! <td>original </td> **! <td>phaseh() </td> **! <td>phasev() </td> **! <td>phasevh()</td> **! <td>phasehv()</td> **! </tr> **! </table>
13670c2015-05-25Martin Nilsson **!
c43fc11999-03-01Henrik Wallin **! returns the new image object
65352b1999-04-12Mirar (Pontus Hagland) ** see also: match_phase
c43fc11999-03-01Henrik Wallin **! bugs **! 0 should not be set as explained above. **! note
2158f21999-07-02Mirar (Pontus Hagland) **! <b>experimental status</b>; may not be exact the same
c43fc11999-03-01Henrik Wallin **! output in later versions */
01b9212016-01-12Per Hedbor static inline int my_abs(int a) { return (a<0)?-a:a; }
c43fc11999-03-01Henrik Wallin  /* phase-image creating functions */ #define NEIG 1 #define IMAGE_PHASE image_phaseh
14571b1999-03-11Henrik Wallin #include "phase.h"
c43fc11999-03-01Henrik Wallin #undef NEIG #undef IMAGE_PHASE #define NEIG xz #define IMAGE_PHASE image_phasev
14571b1999-03-11Henrik Wallin #include "phase.h"
c43fc11999-03-01Henrik Wallin #undef NEIG #undef IMAGE_PHASE #define NEIG xz+1 #define IMAGE_PHASE image_phasehv
14571b1999-03-11Henrik Wallin #include "phase.h"
c43fc11999-03-01Henrik Wallin #undef NEIG #undef IMAGE_PHASE #define NEIG xz-1 #define IMAGE_PHASE image_phasevh
14571b1999-03-11Henrik Wallin #include "phase.h"
c43fc11999-03-01Henrik Wallin #undef NEIG #undef IMAGE_PHASE /* the match-functions */ /* **! method object match(int|float scale, object needle)
d3c84b1999-03-22Henrik Wallin **! method object match(int|float scale, object needle, object haystack_cert, object needle_cert) **! method object match(int|float scale, object needle, object haystack_avoid, int foo) **! method object match(int|float scale, object needle, object haystack_cert, object needle_cert, object haystack_avoid, int foo)
c43fc11999-03-01Henrik Wallin **! **! This method creates an image that describes the
13670c2015-05-25Martin Nilsson **! match in every pixel in the image and the
c43fc11999-03-01Henrik Wallin **! needle-Image. **! **! <pre>
13670c2015-05-25Martin Nilsson **! new pixel value =
07228a1999-06-19Fredrik Hübinette (Hubbe) **! sum( my_abs(needle_pixel-haystack_pixel))
c43fc11999-03-01Henrik Wallin **! </pre> **! **! The new image only have the red rgb-part set. **! **! **! arg int|float scale **! Every pixel is divided with this value. **! Note that a proper value here depends on **! the size of the neadle. **! **! arg object needle
13670c2015-05-25Martin Nilsson **! The image to use for the matching.
c43fc11999-03-01Henrik Wallin **! **! arg object haystack_cert **! This image should be the same size as **! the image itselves. A non-white-part of the **! haystack_cert-image modifies the output
13670c2015-05-25Martin Nilsson **! by lowering it.
c43fc11999-03-01Henrik Wallin **! **! arg object needle_cert **! The same, but for the needle-image. **! **! arg int foo **! arg object haystack_avoid **! This image should be the same size as **! the image itselves. If foo is less than the red **! value in haystack_avoid the corresponding **! matching-calculating is not calculated. The avoided parts **! are drawn in the color 0,100,0. **! **! returns the new image object **! see also: phasev,phaseh **! note
2158f21999-07-02Mirar (Pontus Hagland) **! <b>experimental status</b>; may not be exact the same **! output in later versions
c43fc11999-03-01Henrik Wallin */
12de551999-03-15Henrik Wallin #define SCALE_MODIFY(x) (x)
c43fc11999-03-01Henrik Wallin #define NAME "match" #define INAME image_match
1826491999-03-21Henrik Wallin #define PIXEL_VALUE_DISTANCE(CO) \
07228a1999-06-19Fredrik Hübinette (Hubbe)  (my_abs(haystacki[j].CO-needlei[ny*nxs+nx].CO))
14571b1999-03-11Henrik Wallin #include "match.h"
c43fc11999-03-01Henrik Wallin  #define NAME "match_phase" #define INAME image_match_phase
1826491999-03-21Henrik Wallin #define PIXEL_VALUE_DISTANCE(CO) \
b7b46a2000-12-06Henrik Grubbström (Grubba)  ((h=haystacki[j].CO),(n=needlei[ny*nxs+nx].CO), \ ((h>n)? MINIMUM((h-n),(255-h+n)) : MINIMUM((n-h),(255-n+h))))
14571b1999-03-11Henrik Wallin #include "match.h"
c43fc11999-03-01Henrik Wallin  #define NAME "match_norm" #define INAME image_match_norm
13670c2015-05-25Martin Nilsson #define NEEDLEAVRCODE
1826491999-03-21Henrik Wallin #define PIXEL_VALUE_DISTANCE(CO) \
07228a1999-06-19Fredrik Hübinette (Hubbe)  (my_abs(( haystacki[j].CO-tempavr )-( needlei[ny*nxs+nx].CO-needle_average)))
14571b1999-03-11Henrik Wallin #include "match.h"
c43fc11999-03-01Henrik Wallin  #define NAME "match_norm_corr" #define INAME image_match_norm_corr
13670c2015-05-25Martin Nilsson #undef SCALE_MODIFY
7f33ad1999-03-29Henrik Wallin #define SCALE_MODIFY(x) (1.0/MAXIMUM(1.0,x))
1826491999-03-21Henrik Wallin #define PIXEL_VALUE_DISTANCE(CO) \ (((haystacki[j].CO-tempavr)/2+128) \ * ( (needlei[ny*nxs+nx].CO-needle_average)/2+128 ))
14571b1999-03-11Henrik Wallin #include "match.h"
c43fc11999-03-01Henrik Wallin #undef NEEDLEAVRCODE #undef SUMCHECK /*
f9fde72004-05-04Martin Nilsson **! method string make_ascii(object orient1,object orient2,object orient3,object orient4,int|void tlevel,int|void xsize,int|void ysize)
c43fc11999-03-01Henrik Wallin **!
13670c2015-05-25Martin Nilsson **! This method creates a string that looks like
c43fc11999-03-01Henrik Wallin **! the image. Example: **! <pre> **! //Stina is an image with a cat. **! array(object) Stina4=Stina->orient4(); **! Stina4[1]*=215; **! Stina4[3]*=215; **! string foo=Stina->make_ascii(@Stina4,40,4,8); **! </pre> **!
e23c7a2017-10-05Chris Angelico **! returns some nice ASCII art.
c43fc11999-03-01Henrik Wallin **! see also: orient, orient4 **! note
2158f21999-07-02Mirar (Pontus Hagland) **! <b>experimental status</b>; may not be exact the same **! output in later versions
c43fc11999-03-01Henrik Wallin */
06e0102005-08-14Martin Nilsson /* FIXME: This functions does not depend on the actual image object
12642d2005-08-14Martin Nilsson  and should be removed from the object or reworked. */
c43fc11999-03-01Henrik Wallin void image_make_ascii(INT32 args) {
06e0102005-08-14Martin Nilsson  struct object *objs[4]; struct image *img[4];
13670c2015-05-25Martin Nilsson  INT32 xchar_size=0;
c43fc11999-03-01Henrik Wallin  INT32 ychar_size=0; INT32 tlevel=0;
f034872001-07-12Henrik Grubbström (Grubba)  int i, x, y,xy=0,y2=0, xmax=0,ymax=0,max;
c43fc11999-03-01Henrik Wallin  struct pike_string *s;
391ac52018-08-05Martin Nilsson  get_all_args(NULL, args, "%o%o%o%o.%d%d%d",
06e0102005-08-14Martin Nilsson  &objs[0], &objs[1], &objs[2], &objs[3], &tlevel, &xchar_size, &ychar_size);
f9fde72004-05-04Martin Nilsson  for(i=0; i<4; i++) {
13b5ed2014-05-26Per Hedbor  img[i]=get_storage(objs[i],image_program);
12642d2005-08-14Martin Nilsson  if(!img[i])
f982742016-01-26Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("make_ascii",i+1,"Image.Image");
12642d2005-08-14Martin Nilsson  if(i!=0 && img[0]->xsize!=img[i]->xsize && img[0]->ysize!=img[i]->ysize) Pike_error("make_ascii: Different sized images.\n");
c43fc11999-03-01Henrik Wallin  } if (!tlevel) tlevel=40; if (!xchar_size) xchar_size=5; if (!ychar_size) ychar_size=8; tlevel=tlevel*xchar_size*ychar_size; xmax=((img[0]->xsize-1)/xchar_size+2); ymax=((img[0]->ysize-1)/ychar_size+1); max=xmax*ymax; s=begin_shared_string(max);
13670c2015-05-25Martin Nilsson  THREADS_ALLOW();
c43fc11999-03-01Henrik Wallin  /*fix /n at each row*/ for(i=xmax-1; i<max; i+=xmax) s->str[i]='\n';
13670c2015-05-25Martin Nilsson 
c43fc11999-03-01Henrik Wallin  for(x=0; x<xmax-1; x++) { for(y=0; y<ymax-1; y++)
13670c2015-05-25Martin Nilsson  {
c43fc11999-03-01Henrik Wallin  int dir0,dir1,dir2,dir3; int xstop=0,ystop=0; char t=' '; dir0=0; dir1=0; dir2=0; dir3=0;
13670c2015-05-25Martin Nilsson 
c43fc11999-03-01Henrik Wallin  ystop=y*ychar_size+ychar_size; for(y2=y*ychar_size; y2<(ystop); y2++) { xy=y2*img[0]->xsize+x*xchar_size; xstop=xy+xchar_size; for(; xy<xstop; xy++) { dir0+=img[0]->img[xy].r; dir1+=img[1]->img[xy].r; dir2+=img[2]->img[xy].r; dir3+=img[3]->img[xy].r; } }
13670c2015-05-25Martin Nilsson 
c43fc11999-03-01Henrik Wallin  /*set a part of the string*/ if ((dir0<=tlevel)&& (dir1<=tlevel)&& (dir2<=tlevel)&& (dir3<=tlevel)) { t=' '; } else if ((dir0>tlevel)&& (dir1>tlevel)&& (dir2>tlevel)&& (dir3>tlevel)) { t='*'; } else if ((dir0>=dir1)&&(dir0>=dir2)&& (dir0>=dir3)) { if ((dir2>=tlevel)&& (dir2>dir1)&&(dir2>dir3)) t='+'; else t='|'; } else if ((dir1>=dir2)&&(dir1>=dir3)) { if ((dir3>=tlevel)&& (dir3>dir0)&&(dir3>dir2)) t='X'; else t='/'; } else if (dir2>=dir3) { if ((dir0>=tlevel)&& (dir0>dir1)&&(dir0>dir3)) t='+'; else t='-'; } else { if ((dir1>=tlevel)&& (dir1>dir0)&&(dir1>dir2)) t='X'; else t='\\'; }
13670c2015-05-25Martin Nilsson 
c43fc11999-03-01Henrik Wallin  s->str[y*xmax+x]=t;
13670c2015-05-25Martin Nilsson 
c43fc11999-03-01Henrik Wallin  } }
06e0102005-08-14Martin Nilsson  /* Temp fix to hide garbage */ for(x=0; x<xmax-1; x++) s->str[(ymax-1)*xmax+x] = ' ';
c43fc11999-03-01Henrik Wallin  /*fix end of rows*/
13670c2015-05-25Martin Nilsson 
c43fc11999-03-01Henrik Wallin  /*fix middle*/
13670c2015-05-25Martin Nilsson 
06e0102005-08-14Martin Nilsson  /*fix last row*/
13670c2015-05-25Martin Nilsson  /*fix last position*/
c43fc11999-03-01Henrik Wallin  /* **! <pre> | / - \ **! hue= 0 64 128 192 (=red in an hsv image)
65352b1999-04-12Mirar (Pontus Hagland) **! </pre>
c43fc11999-03-01Henrik Wallin  */
13670c2015-05-25Martin Nilsson 
c43fc11999-03-01Henrik Wallin  THREADS_DISALLOW();
f9fde72004-05-04Martin Nilsson  pop_n_elems(args);
c43fc11999-03-01Henrik Wallin  push_string(end_shared_string(s)); return; } /* End make_ascii */ /* **! method object apply_max(array(array(int|array(int))) matrix) **! method object apply_max(array(array(int|array(int))) matrix,int r,int g,int b) **! method object apply_max(array(array(int|array(int))) matrix,int r,int g,int b,int|float div) **! This is the same as apply_matrix, but it uses the maximum **! instead. **! **! This function is not very fast. **! **! 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. **! 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.
2158f21999-07-02Mirar (Pontus Hagland) **! note **! <b>experimental status</b>; may not be exact the same **! output in later versions
c43fc11999-03-01Henrik Wallin */
01b9212016-01-12Per Hedbor static inline rgb_group _pixel_apply_max(struct image *img,
c43fc11999-03-01Henrik Wallin  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;
ea7a4d2000-08-09Henrik Grubbström (Grubba)  double qdiv=1.0/div;
c43fc11999-03-01Henrik Wallin  /* NOTE: * This code MUST be MT-SAFE! */ HIDE_GLOBAL_VARIABLES(); sumr=sumg=sumb=0; r=g=b=0; bx=width/2; by=height/2; 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) {
f6b3b52016-02-12Martin Nilsson  r = (int)MAXIMUM(r, matrix[i+j*width].r * img->img[xp+yp*img->xsize].r); g = (int)MAXIMUM(g, matrix[i+j*width].g * img->img[xp+yp*img->xsize].g); b = (int)MAXIMUM(b, matrix[i+j*width].b * img->img[xp+yp*img->xsize].b);
c43fc11999-03-01Henrik Wallin #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
f6b3b52016-02-12Martin Nilsson  sumr = (int)MAXIMUM(sumr, matrix[i+j*width].r); sumg = (int)MAXIMUM(sumg, matrix[i+j*width].g); sumb = (int)MAXIMUM(sumb, matrix[i+j*width].b);
c43fc11999-03-01Henrik Wallin  }
7bc62b2000-08-18Henrik Grubbström (Grubba)  if (sumr)
8cc82a2016-02-12Martin Nilsson  res.r = (COLORTYPE)testrange(default_rgb.r + r/(sumr * div));
7bc62b2000-08-18Henrik Grubbström (Grubba)  else
8cc82a2016-02-12Martin Nilsson  res.r = (COLORTYPE)testrange(r * qdiv + default_rgb.r);
7bc62b2000-08-18Henrik Grubbström (Grubba)  if (sumg)
8cc82a2016-02-12Martin Nilsson  res.g = (COLORTYPE)testrange(default_rgb.g + g/(sumg * div));
7bc62b2000-08-18Henrik Grubbström (Grubba)  else
8cc82a2016-02-12Martin Nilsson  res.g = (COLORTYPE)testrange(g * qdiv + default_rgb.g);
7bc62b2000-08-18Henrik Grubbström (Grubba)  if (sumb)
58dc242018-08-10Henrik Grubbström (Grubba)  res.b = (COLORTYPE)testrange(default_rgb.b + b/(sumb * div));
7bc62b2000-08-18Henrik Grubbström (Grubba)  else
8cc82a2016-02-12Martin Nilsson  res.b = (COLORTYPE)testrange(b * qdiv + default_rgb.b);
c43fc11999-03-01Henrik Wallin #ifdef MATRIX_DEBUG fprintf(stderr,"->%d,%d,%d\n",res.r,res.g,res.b); #endif return res; REVEAL_GLOBAL_VARIABLES(); } void img_apply_max(struct image *dest, struct image *img, int width,int height, rgbd_group *matrix, rgb_group default_rgb, double div) { rgb_group *d,*ip,*dp; rgbd_group *mp; int i,x,y,bx,by,ex,ey,yp; int widthheight; double sumr,sumg,sumb; double qr,qg,qb;
636bc52014-11-01Martin Nilsson  double r=0,g=0,b=0;
c43fc11999-03-01Henrik Wallin 
20d0552009-04-22Martin Stjernholm  d=xalloc(sizeof(rgb_group)*img->xsize*img->ysize+RGB_VEC_PAD);
7d60af2004-05-19Martin Nilsson 
c43fc11999-03-01Henrik Wallin THREADS_ALLOW(); widthheight=width*height; sumr=sumg=sumb=0; for (i=0; i<widthheight;) { sumr=MAXIMUM(sumr, matrix[i].r); sumg=MAXIMUM(sumg, matrix[i].g); sumb=MAXIMUM(sumb, matrix[i++].b); }
c8622d2016-09-09Chris 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;
c43fc11999-03-01Henrik Wallin  bx=width/2; by=height/2; ex=width-bx; ey=height-by;
13670c2015-05-25Martin Nilsson 
c43fc11999-03-01Henrik Wallin  for (y=by; y<img->ysize-ey; y++) { dp=d+y*img->xsize+bx; for (x=bx; x<img->xsize-ex; x++) { r=g=b=0; mp=matrix; ip=img->img+(x-bx)+(y-by)*img->xsize; /* for (yp=y-by,j=0; j<height; j++,yp++) */ #ifdef MATRIX_DEBUG j=-1; #endif for (yp=y-by; yp<height+y-by; yp++) { #ifdef MATRIX_DEBUG j++; #endif for (i=0; i<width; i++) { r=MAXIMUM(r, ip->r*mp->r); g=MAXIMUM(g, ip->g*mp->g); b=MAXIMUM(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++; } ip+=img->xsize-width; } #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);
8cc82a2016-02-12Martin Nilsson  dp->r = (COLORTYPE)testrange(r);
f6b3b52016-02-12Martin Nilsson  g = default_rgb.g+(int)(g*qg+0.5);
8cc82a2016-02-12Martin Nilsson  dp->g = (COLORTYPE)testrange(g);
f6b3b52016-02-12Martin Nilsson  b = default_rgb.b+(int)(b*qb+0.5);
8cc82a2016-02-12Martin Nilsson  dp->b = (COLORTYPE)testrange(b);
c43fc11999-03-01Henrik Wallin  dp++; } } for (y=0; y<img->ysize; y++) { for (x=0; x<bx; x++) d[x+y*img->xsize]=_pixel_apply_max(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_max(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_max(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_max(img,x,y,width,height, matrix,default_rgb,div); } if (dest->img) free(dest->img); *dest=*img; dest->img=d; THREADS_DISALLOW(); } void image_apply_max(INT32 args) { int width,height,i,j; rgbd_group *matrix; rgb_group default_rgb; struct object *o; double div; if (args<1 ||
017b572011-10-28Henrik Grubbström (Grubba)  TYPEOF(sp[-args]) != T_ARRAY)
118f582018-02-22Martin Nilsson  SIMPLE_ARG_TYPE_ERROR("apply_max", 1, "array");
c43fc11999-03-01Henrik Wallin 
13670c2015-05-25Martin Nilsson  if (args>3)
118f582018-02-22Martin Nilsson  { struct array *a;
391ac52018-08-05Martin Nilsson  get_all_args(NULL, args, "%a%d%d%d", &a,
118f582018-02-22Martin Nilsson  &default_rgb.r, &default_rgb.g, &default_rgb.b); }
13670c2015-05-25Martin Nilsson  else
c43fc11999-03-01Henrik Wallin  { default_rgb.r=0; default_rgb.g=0; default_rgb.b=0; }
13670c2015-05-25Martin Nilsson  if (args>4
017b572011-10-28Henrik Grubbström (Grubba)  && TYPEOF(sp[4-args]) == T_INT)
c43fc11999-03-01Henrik Wallin  { div=sp[4-args].u.integer; if (!div) div=1; }
13670c2015-05-25Martin Nilsson  else if (args>4
017b572011-10-28Henrik Grubbström (Grubba)  && TYPEOF(sp[4-args]) == T_FLOAT)
c43fc11999-03-01Henrik Wallin  { div=sp[4-args].u.float_number; if (!div) div=1; } else div=1;
13670c2015-05-25Martin Nilsson 
c43fc11999-03-01Henrik Wallin  height=sp[-args].u.array->size; width=-1; for (i=0; i<height; i++) { struct svalue s=sp[-args].u.array->item[i];
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(s) != T_ARRAY)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Illegal contents of (root) array (Image.Image->apply_max)\n");
c43fc11999-03-01Henrik Wallin  if (width==-1) width=s.u.array->size; else if (width!=s.u.array->size)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Arrays has different size (Image.Image->apply_max)\n");
c43fc11999-03-01Henrik Wallin  } if (width==-1) width=0;
1a597d2005-08-15Henrik Grubbström (Grubba)  matrix=xalloc(sizeof(rgbd_group)*width*height+1);
7d60af2004-05-19Martin Nilsson 
c43fc11999-03-01Henrik Wallin  for (i=0; i<height; i++) { struct svalue s=sp[-args].u.array->item[i]; for (j=0; j<width; j++) { struct svalue s2=s.u.array->item[j];
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(s2) == T_ARRAY && s2.u.array->size == 3)
c43fc11999-03-01Henrik Wallin  { struct svalue s3; s3=s2.u.array->item[0];
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(s3) == T_INT) matrix[j+i*width].r = (float)s3.u.integer;
c43fc11999-03-01Henrik Wallin  else matrix[j+i*width].r=0; s3=s2.u.array->item[1];
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(s3) == T_INT) matrix[j+i*width].g = (float)s3.u.integer;
c43fc11999-03-01Henrik Wallin  else matrix[j+i*width].g=0; s3=s2.u.array->item[2];
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(s3) == T_INT) matrix[j+i*width].b = (float)s3.u.integer;
c43fc11999-03-01Henrik Wallin  else matrix[j+i*width].b=0; }
017b572011-10-28Henrik Grubbström (Grubba)  else if (TYPEOF(s2) == T_INT)
c43fc11999-03-01Henrik Wallin  matrix[j+i*width].r=matrix[j+i*width].g=
f034872001-07-12Henrik Grubbström (Grubba)  matrix[j+i*width].b = (float)s2.u.integer;
c43fc11999-03-01Henrik Wallin  else matrix[j+i*width].r=matrix[j+i*width].g= matrix[j+i*width].b=0; } } o=clone_object(image_program,0); if (THIS->img) img_apply_max((struct image*)o->storage,THIS, width,height,matrix,default_rgb,div); free(matrix); pop_n_elems(args); push_object(o); }