|
|
|
|
|
|
|
|
|
|
|
|
#include "global.h" |
|
#include <math.h> |
#include <ctype.h> |
|
#include "global.h" |
#include "pike_macros.h" |
#include "object.h" |
#include "interpret.h" |
#include "svalue.h" |
#include "pike_error.h" |
|
#include "image.h" |
|
|
#define sp Pike_sp |
|
extern struct program *image_program; |
#ifdef THIS |
#undef THIS /* Needed for NT */ |
#endif |
#define THIS ((struct image *)(Pike_fp->current_storage)) |
#define THISOBJ (Pike_fp->current_object) |
|
#define testrange(x) MAXIMUM(MINIMUM((x),255),0) |
|
static const double c0=0.70710678118654752440; |
static const double pi=3.14159265358979323846; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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; |
|
if (!THIS->img) Pike_error("Called Image.Image object is not initialized\n");; |
|
#ifdef DCT_DEBUG |
fprintf(stderr,"%lu bytes, %lu bytes\n", |
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))); |
#endif |
|
if (!(area=malloc(sizeof(rgbd_group)*THIS->xsize*THIS->ysize+1))) |
resource_error(NULL,0,0,"memory",0,"Out of memory.\n"); |
|
if (!(costbl=malloc(sizeof(double)*THIS->xsize+1))) |
{ |
free(area); |
resource_error(NULL,0,0,"memory",0,"Out of memory.\n"); |
} |
|
o=clone_object(image_program,0); |
img=(struct image*)(o->storage); |
*img=*THIS; |
|
if (args>=2 |
&& sp[-args].type==T_INT |
&& sp[1-args].type==T_INT) |
{ |
img->xsize=MAXIMUM(1,sp[-args].u.integer); |
img->ysize=MAXIMUM(1,sp[1-args].u.integer); |
} |
else bad_arg_error("image->dct",sp-args,args,0,"",sp-args, |
"Bad arguments to image->dct()\n"); |
|
if (!(img->img=(rgb_group*)malloc(sizeof(rgb_group)* |
img->xsize*img->ysize+1))) |
{ |
free(area); |
free(costbl); |
free_object(o); |
resource_error(NULL,0,0,"memory",0,"Out of memory.\n"); |
} |
|
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; |
sum.r += (float)(pix->r*z); |
sum.g += (float)(pix->g*z); |
sum.b += (float)(pix->b*z); |
pix++; |
} |
} |
sum.r *= (float)d; |
sum.g *= (float)d; |
sum.b *= (float)d; |
area[u+v*THIS->xsize]=sum; |
} |
#ifdef DCT_DEBUG |
fprintf(stderr,"."); fflush(stderr); |
#endif |
} |
#ifdef DCT_DEBUG |
fprintf(stderr,"\n"); |
#endif |
|
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; |
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)); |
val++; |
} |
} |
sum.r *= (float)enh; |
sum.g *= (float)enh; |
sum.b *= (float)enh; |
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))); |
pix++; |
} |
#ifdef DCT_DEBUG |
fprintf(stderr,"."); fflush(stderr); |
#endif |
} |
|
free(area); |
free(costbl); |
|
pop_n_elems(args); |
push_object(o); |
} |
|
|