#include "php.h"
#include "php_imlib.h"
#define php_filter_init php_hsbcolor_LTX_php_filter_init
#define php_filter_deinit php_hsbcolor_LTX_php_filter_deinit
#define php_filter_exec php_hsbcolor_LTX_php_filter_exec
#define php_filter_getfiltercount php_hsbcolor_LTX_php_filter_getfiltercount
#define php_filter_getfilternames php_hsbcolor_LTX_php_filter_getfilternames
#define php_filter_getextinfo php_hsbcolor_LTX_php_filter_getextinfo
#define php_filter_getparams php_hsbcolor_LTX_php_filter_getparams
static void _php_hsbcolor_rgb2hsb(DATA32 argb, double *h, double *s, double *v)
{
int r,g,b;
float hue, saturation, brightness;
int cmax, cmin;
r=(argb&0x00ff0000)>>16;
g=(argb&0x0000ff00)>>8;
b=(argb&0x000000ff);
cmax = (r > g) ? r : g;
if (b > cmax) cmax = b;
cmin = (r < g) ? r : g;
if (b < cmin) cmin = b;
brightness = ((float) cmax) / 255.0f;
if (cmax != 0)
saturation = ((float) (cmax - cmin)) / ((float) cmax);
else
saturation = 0;
if (saturation == 0)
hue = 0;
else {
float redc = ((float) (cmax - r)) / ((float) (cmax - cmin));
float greenc = ((float) (cmax - g)) / ((float) (cmax - cmin));
float bluec = ((float) (cmax - b)) / ((float) (cmax - cmin));
if (r == cmax)
hue = bluec - greenc;
else if (g == cmax)
hue = 2.0f + redc - bluec;
else
hue = 4.0f + greenc - redc;
hue = hue / 6.0f;
if (hue < 0)
hue = hue + 1.0f;
}
*h = hue;
*s = saturation;
*v = brightness;
}
static void _php_hsbcolor_hsb2rgb(double hue, double saturation, double brightness, DATA32 *argb)
{
int r,g,b;
if (saturation == 0) {
r = g = b = (int) (brightness * 255);
} else {
double h = hue * 6.0;
double f = h - floor(h);
double p = brightness * (1.0 - saturation);
double q = brightness * (1.0 - saturation * f);
double t = brightness * (1.0 - (saturation * (1.0 - f)));
switch ((int) h) {
case 0:
r = (int) (brightness * 255);
g = (int) (t * 255);
b = (int) (p * 255);
break;
case 1:
r = (int) (q * 255);
g = (int) (brightness * 255);
b = (int) (p * 255);
break;
case 2:
r = (int) (p * 255);
g = (int) (brightness * 255);
b = (int) (t * 255);
break;
case 3:
r = (int) (p * 255);
g = (int) (q * 255);
b = (int) (brightness * 255);
break;
case 4:
r = (int) (t * 255);
g = (int) (p * 255);
b = (int) (brightness * 255);
break;
case 5:
r = (int) (brightness * 255);
g = (int) (p * 255);
b = (int) (q * 255);
break;
}
}
*argb=(*argb&0xff000000) | (r<<16) | (g<<8) | b;
}
static int
_php_hsbcolor_exec(Imlib_Image im, HashTable* params)
{
HashPosition pos;
double h_add = 0, s_add = 0, b_add = 0;
double h_mul = 1.0, s_mul = 1.0, b_mul = 1.0;
int w,h,imgw,imgh,x=0,y=0;
imlib_context_set_image( im );
w = imgw = imlib_image_get_width();
h = imgh = imlib_image_get_height();
zend_hash_internal_pointer_reset_ex(params,&pos);
while (pos)
{
char *str_index;
ulong num_index;
int retval;
retval=zend_hash_get_current_key_ex(params,&str_index,NULL,&num_index,0,&pos);
if (retval==HASH_KEY_IS_STRING)
{
zval **data;
zend_hash_get_current_data_ex(params,(void*)&data,&pos);
if (!strcmp(str_index,"x")) { convert_to_long_ex(data); x=Z_LVAL_PP(data); };
if (!strcmp(str_index,"y")) { convert_to_long_ex(data); y=Z_LVAL_PP(data); };
if (!strcmp(str_index,"w")) { convert_to_long_ex(data); w=Z_LVAL_PP(data); };
if (!strcmp(str_index,"h")) { convert_to_long_ex(data); h=Z_LVAL_PP(data); };
if (!strcmp(str_index,"h_add")) { convert_to_double_ex(data); h_add=Z_DVAL_PP(data); };
if (!strcmp(str_index,"s_add")) { convert_to_double_ex(data); s_add=Z_DVAL_PP(data); };
if (!strcmp(str_index,"b_add")) { convert_to_double_ex(data); b_add=Z_DVAL_PP(data); };
if (!strcmp(str_index,"h_mul")) { convert_to_double_ex(data); h_mul=Z_DVAL_PP(data); };
if (!strcmp(str_index,"s_mul")) { convert_to_double_ex(data); s_mul=Z_DVAL_PP(data); };
if (!strcmp(str_index,"b_mul")) { convert_to_double_ex(data); b_mul=Z_DVAL_PP(data); };
}
zend_hash_move_forward_ex(params,&pos);
}
if (x<0) x=0;
if (y<0) y=0;
if (w<0) w=0;
if (h<0) h=0;
if (x>=imgw) x=imgw-1;
if (y>=imgh) y=imgh-1;
if ((x+w)>imgw) w=imgw-x;
if ((y+h)>imgh) h=imgh-y;
{
DATA32 *img_ptr,*old_ptr;
int i,j;
old_ptr = img_ptr = imlib_image_get_data();
img_ptr+=x+y*imgw;
for (j=y;j<(y+h);j++)
{
for (i=x;i<(x+w);i++)
{
double h,s,v;
_php_hsbcolor_rgb2hsb(*img_ptr,&h,&s,&v);
h*=h_mul;
h+=h_add;
s*=s_mul;
s+=s_add;
v*=b_mul;
v+=b_add;
h=fmod(h,1);
if (h<0) h+=1;
if (s<0) s=0;
if (s>1) s=1;
if (v<0) v=0;
if (v>1) v=1;
_php_hsbcolor_hsb2rgb(h,s,v,img_ptr);
img_ptr++;
}
img_ptr+=imgw-w;
}
imlib_image_put_back_data(old_ptr);
}
return SUCCESS;
}
int
php_filter_init()
{
return SUCCESS;
}
void
php_filter_deinit()
{
return;
}
int
php_filter_exec(Imlib_Image im, char *filter, HashTable *params)
{
if (!strcmp(filter, "hsbcolor"))
{
return _php_hsbcolor_exec(im,params);
}
return FAILURE;
}
int
php_filter_getfiltercount()
{
return 1;
}
void
php_filter_getfilternames(char** filternames)
{
filternames[0]="hsbcolor";
}
void
php_filter_getextinfo(char** info)
{
info[0]="HSB Color";
info[1]="Provides HSB space color modifications.";
info[2]="Piotr Pawlow (pp@siedziba.pl)";
}
char*
php_filter_getparams(char* filter)
{
if (!strcmp(filter, "hsbcolor")) return "int x=0, int y=0, int w=image_width, int h=image_height, double h_add=0, double s_add=0, double b_add=0, double h_mul=1, double s_mul=1, double b_mul=1";
return NULL;
}