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.
2ba9202004-03-06Martin Nilsson || $Id: dct.c,v 1.25 2004/03/05 23:04:02 nilsson Exp $
e576bb2002-10-11Martin Nilsson */
e3cb4b1997-04-03Mirar (Pontus Hagland)  /* **! module Image
448c201999-04-13Mirar (Pontus Hagland) **! class Image
e3cb4b1997-04-03Mirar (Pontus Hagland) */
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  #include "global.h" #include <math.h> #include <ctype.h> #include "global.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"
b2d3e42000-12-01Fredrik Hübinette (Hubbe) #include "pike_error.h"
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  #include "image.h"
6dc2772000-07-28Fredrik Hübinette (Hubbe) 
d569182002-05-11Martin Nilsson #define sp Pike_sp
ab6aec1997-02-11Fredrik Hübinette (Hubbe) extern struct program *image_program;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) #ifdef THIS #undef THIS /* Needed for NT */ #endif
d569182002-05-11Martin Nilsson #define THIS ((struct image *)(Pike_fp->current_storage)) #define THISOBJ (Pike_fp->current_object)
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
7210191997-12-22Fredrik Hübinette (Hubbe) #define testrange(x) MAXIMUM(MINIMUM((x),255),0)
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  static const double c0=0.70710678118654752440; static const double pi=3.14159265358979323846;
e3cb4b1997-04-03Mirar (Pontus Hagland) /* **! method object dct(int newx,int newy) **! Scales the image to a new size. **! **! Method for scaling is rather complex; **! the image is transformed via a cosine transform, **! and then resampled back. **! **! This gives a quality-conserving upscale, **! but the algorithm used is n*n+n*m, where n **! and m is pixels in the original and new image. **! **! Recommended wrapping algorithm is to scale **! overlapping parts of the image-to-be-scaled. **! **! This functionality is actually added as an **! true experiment, but works...
ba09c21997-04-30Mirar (Pontus Hagland) **! **! note **! Do NOT use this function if you don't know what **! you're dealing with! Read some signal theory first...
204bdf1999-04-22Mirar (Pontus Hagland) **! **! It write's dots on stderr, to indicate some sort **! of progress. It doesn't use any fct (compare: fft) **! algorithms.
e3cb4b1997-04-03Mirar (Pontus Hagland) **! returns the new image object **! arg int newx **! arg int newy **! new image size in pixels **! */
ab6aec1997-02-11Fredrik Hübinette (Hubbe) void image_dct(INT32 args) { rgbd_group *area,*val; struct object *o; struct image *img; INT32 x,y,u,v; double xsz2,ysz2,enh,xp,yp,dx,dy; double *costbl; rgb_group *pix;
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  if (!THIS->img) Pike_error("Called Image.Image object is not initialized\n");;
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
1c38832003-08-21Martin Nilsson #ifdef DCT_DEBUG
b829861997-03-10Henrik Grubbström (Grubba)  fprintf(stderr,"%lu bytes, %lu bytes\n",
8778a72000-08-10Henrik Grubbström (Grubba)  DO_NOT_WARN((unsigned long)(sizeof(rgbd_group)*THIS->xsize*THIS->ysize)), DO_NOT_WARN((unsigned long)(sizeof(rgb_group)*THIS->xsize*THIS->ysize+1)));
1c38832003-08-21Martin Nilsson #endif
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (!(area=malloc(sizeof(rgbd_group)*THIS->xsize*THIS->ysize+1)))
80f30b1999-06-18Mirar (Pontus Hagland)  resource_error(NULL,0,0,"memory",0,"Out of memory.\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  if (!(costbl=malloc(sizeof(double)*THIS->xsize+1))) { free(area);
80f30b1999-06-18Mirar (Pontus Hagland)  resource_error(NULL,0,0,"memory",0,"Out of memory.\n");
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; if (args>=2 && sp[-args].type==T_INT && sp[1-args].type==T_INT) {
7210191997-12-22Fredrik Hübinette (Hubbe)  img->xsize=MAXIMUM(1,sp[-args].u.integer); img->ysize=MAXIMUM(1,sp[1-args].u.integer);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  }
80f30b1999-06-18Mirar (Pontus Hagland)  else bad_arg_error("image->dct",sp-args,args,0,"",sp-args, "Bad arguments to image->dct()\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe) 
e3cb4b1997-04-03Mirar (Pontus Hagland)  if (!(img->img=(rgb_group*)malloc(sizeof(rgb_group)* img->xsize*img->ysize+1)))
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  { free(area); free(costbl); free_object(o);
80f30b1999-06-18Mirar (Pontus Hagland)  resource_error(NULL,0,0,"memory",0,"Out of memory.\n");
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } xsz2=THIS->xsize*2.0; ysz2=THIS->ysize*2.0; enh=(8.0/THIS->xsize)*(8.0/THIS->ysize); for (u=0; u<THIS->xsize; u++) { double d,z0; rgbd_group sum; for (v=0; v<THIS->ysize; v++) { d=(u?1:c0)*(v?1:c0)/4.0; sum.r=sum.g=sum.b=0; pix=THIS->img; for (x=0; x<THIS->xsize; x++) costbl[x]=cos( (2*x+1)*u*pi/xsz2 ); for (y=0; y<THIS->ysize; y++) { z0=cos( (2*y+1)*v*pi/ysz2 ); for (x=0; x<THIS->xsize; x++) { double z; z = costbl[x] * z0;
3d94d12001-07-12Henrik Grubbström (Grubba)  sum.r += (float)(pix->r*z); sum.g += (float)(pix->g*z); sum.b += (float)(pix->b*z);
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  pix++; } }
3d94d12001-07-12Henrik Grubbström (Grubba)  sum.r *= (float)d; sum.g *= (float)d; sum.b *= (float)d;
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  area[u+v*THIS->xsize]=sum; }
1c38832003-08-21Martin Nilsson #ifdef DCT_DEBUG
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  fprintf(stderr,"."); fflush(stderr);
1c38832003-08-21Martin Nilsson #endif
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  }
1c38832003-08-21Martin Nilsson #ifdef DCT_DEBUG
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  fprintf(stderr,"\n");
1c38832003-08-21Martin Nilsson #endif
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  dx=((double)(THIS->xsize-1))/(img->xsize); dy=((double)(THIS->ysize-1))/(img->ysize); pix=img->img; for (y=0,yp=0; y<img->ysize; y++,yp+=dy) { double z0; rgbd_group sum; for (x=0,xp=0; x<img->xsize; x++,xp+=dx) { sum.r=sum.g=sum.b=0; val=area; for (u=0; u<THIS->xsize; u++) costbl[u]=cos( (2*xp+1)*u*pi/xsz2 ); for (v=0; v<THIS->ysize; v++) { z0=cos( (2*yp+1)*v*pi/ysz2 )*(v?1:c0)/4.0; for (u=0; u<THIS->xsize; u++) { double z; z = (u?1:c0) * costbl[u] * z0;
9e3e5a2001-09-24Henrik Grubbström (Grubba)  sum.r += DO_NOT_WARN((float)(val->r*z)); sum.g += DO_NOT_WARN((float)(val->g*z)); sum.b += DO_NOT_WARN((float)(val->b*z));
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  val++; } }
3d94d12001-07-12Henrik Grubbström (Grubba)  sum.r *= (float)enh; sum.g *= (float)enh; sum.b *= (float)enh;
8778a72000-08-10Henrik Grubbström (Grubba)  pix->r=testrange((DOUBLE_TO_INT(sum.r+0.5))); pix->g=testrange((DOUBLE_TO_INT(sum.g+0.5))); pix->b=testrange((DOUBLE_TO_INT(sum.b+0.5)));
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  pix++; }
1c38832003-08-21Martin Nilsson #ifdef DCT_DEBUG
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  fprintf(stderr,"."); fflush(stderr);
1c38832003-08-21Martin Nilsson #endif
ab6aec1997-02-11Fredrik Hübinette (Hubbe)  } free(area); free(costbl); pop_n_elems(args); push_object(o); }