#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,&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; }