Last commit for filters/php_colormatrix.c: a2f603174ce34359dde60b6227d138b5bf330503

Revert "Quick and dirty PHP7 port."

Piotr Pawłow [2016-09-14 15:21:01]
Revert "Quick and dirty PHP7 port."

This reverts commit 87380c76cb1eb3644da7291d842281caaae63f2d.
There are much more differences between PHP5 and 7 than I anticipated.
The code doesn't work right.
#include "php.h"
#include "php_imlib.h"

#define php_filter_init			php_colormatrix_LTX_php_filter_init
#define php_filter_deinit		php_colormatrix_LTX_php_filter_deinit
#define php_filter_exec			php_colormatrix_LTX_php_filter_exec
#define php_filter_getfiltercount	php_colormatrix_LTX_php_filter_getfiltercount
#define php_filter_getfilternames	php_colormatrix_LTX_php_filter_getfilternames
#define php_filter_getextinfo		php_colormatrix_LTX_php_filter_getextinfo
#define php_filter_getparams		php_colormatrix_LTX_php_filter_getparams

#define RLUM    (0.3086)
#define GLUM    (0.6094)
#define BLUM    (0.0820)

/*
 *	identmat -
 *		make an identity matrix
 */
static void _php_colormatrix_identmat(double *matrix)
{
    *matrix++ = 1.0;    /* row 1        */
    *matrix++ = 0.0;
    *matrix++ = 0.0;
    *matrix++ = 0.0;
    *matrix++ = 0.0;    /* row 2        */
    *matrix++ = 1.0;
    *matrix++ = 0.0;
    *matrix++ = 0.0;
    *matrix++ = 0.0;    /* row 3        */
    *matrix++ = 0.0;
    *matrix++ = 1.0;
    *matrix++ = 0.0;
    *matrix++ = 0.0;    /* row 4        */
    *matrix++ = 0.0;
    *matrix++ = 0.0;
    *matrix++ = 1.0;
}

/*
 *	matrixmult -
 *		multiply two matricies
 */
static void _php_colormatrix_matrixmult(double a[16],double b[16],double c[16])
{
    int x, y;
    double tmp[16];

    for(y=0; y<4 ; y++)
    {
        for(x=0 ; x<4 ; x++)
        {
            tmp[(y<<2)+x] = b[(y<<2)+0] * a[(0<<2)+x]
                          + b[(y<<2)+1] * a[(1<<2)+x]
                          + b[(y<<2)+2] * a[(2<<2)+x]
                          + b[(y<<2)+3] * a[(3<<2)+x];
        }
    }
    memcpy(c,tmp,sizeof(double)*16);
}

/*
 *	xformpnt -
 *		transform a 3D point using a matrix
 */
static void _php_colormatrix_xformpnt(double matrix[16],double x,double y,double z,double *tx,double *ty,double *tz)
{
    *tx = x*matrix[0] + y*matrix[4] + z*matrix[8] + matrix[12];
    *ty = x*matrix[1] + y*matrix[5] + z*matrix[9] + matrix[13];
    *tz = x*matrix[2] + y*matrix[6] + z*matrix[10] + matrix[14];
}

/*
 *	xrotate -
 *		rotate about the x (red) axis
 */
static void _php_colormatrix_xrotatemat(double mat[16],double rs,double rc)
{
    double mmat[16];

    mmat[0] = 1.0;
    mmat[1] = 0.0;
    mmat[2] = 0.0;
    mmat[3] = 0.0;

    mmat[4] = 0.0;
    mmat[5] = rc;
    mmat[6] = rs;
    mmat[7] = 0.0;

    mmat[8] = 0.0;
    mmat[9] = -rs;
    mmat[10] = rc;
    mmat[11] = 0.0;

    mmat[12] = 0.0;
    mmat[13] = 0.0;
    mmat[14] = 0.0;
    mmat[15] = 1.0;
    _php_colormatrix_matrixmult(mmat,mat,mat);
}

/*
 *	yrotate -
 *		rotate about the y (green) axis
 */
static void _php_colormatrix_yrotatemat(double mat[16],double rs,double rc)
{
    double mmat[16];

    mmat[0] = rc;
    mmat[1] = 0.0;
    mmat[2] = -rs;
    mmat[3] = 0.0;

    mmat[4] = 0.0;
    mmat[5] = 1.0;
    mmat[6] = 0.0;
    mmat[7] = 0.0;

    mmat[8] = rs;
    mmat[9] = 0.0;
    mmat[10] = rc;
    mmat[11] = 0.0;

    mmat[12] = 0.0;
    mmat[13] = 0.0;
    mmat[14] = 0.0;
    mmat[15] = 1.0;
    _php_colormatrix_matrixmult(mmat,mat,mat);
}

/*
 *	zrotate -
 *		rotate about the z (blue) axis
 */
static void _php_colormatrix_zrotatemat(double mat[16],double rs,double rc)
{
    double mmat[16];

    mmat[0] = rc;
    mmat[1] = rs;
    mmat[2] = 0.0;
    mmat[3] = 0.0;

    mmat[4] = -rs;
    mmat[5] = rc;
    mmat[6] = 0.0;
    mmat[7] = 0.0;

    mmat[8] = 0.0;
    mmat[9] = 0.0;
    mmat[10] = 1.0;
    mmat[11] = 0.0;

    mmat[12] = 0.0;
    mmat[13] = 0.0;
    mmat[14] = 0.0;
    mmat[15] = 1.0;
    _php_colormatrix_matrixmult(mmat,mat,mat);
}

/*
 *	zshear -
 *		shear z using x and y.
 */
static void _php_colormatrix_zshearmat(double mat[16],double dx,double dy)
{
    double mmat[16];

    mmat[0] = 1.0;
    mmat[1] = 0.0;
    mmat[2] = dx;
    mmat[3] = 0.0;

    mmat[4] = 0.0;
    mmat[5] = 1.0;
    mmat[6] = dy;
    mmat[7] = 0.0;

    mmat[8] = 0.0;
    mmat[9] = 0.0;
    mmat[10] = 1.0;
    mmat[11] = 0.0;

    mmat[12] = 0.0;
    mmat[13] = 0.0;
    mmat[14] = 0.0;
    mmat[15] = 1.0;
    _php_colormatrix_matrixmult(mmat,mat,mat);
}

/*
 *	huerotatemat -
 *		rotate the hue, while maintaining luminance.
 */
static void _php_colormatrix_huerotatemat(double mat[16],double rot)
{
    double mmat[16];
    double mag;
    double lx, ly, lz;
    double xrs, xrc;
    double yrs, yrc;
    double zrs, zrc;
    double zsx, zsy;

    _php_colormatrix_identmat(mmat);

/* rotate the grey vector into positive Z */
    mag = sqrt(2.0);
    xrs = 1.0/mag;
    xrc = 1.0/mag;
    _php_colormatrix_xrotatemat(mmat,xrs,xrc);
    mag = sqrt(3.0);
    yrs = -1.0/mag;
    yrc = sqrt(2.0)/mag;
    _php_colormatrix_yrotatemat(mmat,yrs,yrc);

/* shear the space to make the luminance plane horizontal */
    _php_colormatrix_xformpnt(mmat,RLUM,GLUM,BLUM,&lx,&ly,&lz);
    zsx = lx/lz;
    zsy = ly/lz;
    _php_colormatrix_zshearmat(mmat,zsx,zsy);

/* rotate the hue */
    zrs = sin(rot*M_PI/180.0);
    zrc = cos(rot*M_PI/180.0);
    _php_colormatrix_zrotatemat(mmat,zrs,zrc);

/* unshear the space to put the luminance plane back */
    _php_colormatrix_zshearmat(mmat,-zsx,-zsy);

/* rotate the grey vector back into place */
    _php_colormatrix_yrotatemat(mmat,-yrs,yrc);
    _php_colormatrix_xrotatemat(mmat,-xrs,xrc);

    _php_colormatrix_matrixmult(mmat,mat,mat);
}

/*
 *	saturatemat -
 *		make a saturation marix
 */
static void _php_colormatrix_saturatemat(double mat[16], double sat)
{
    mat[0] = (1.0-sat)*RLUM + sat;
    mat[1] = (1.0-sat)*RLUM;
    mat[2] = (1.0-sat)*RLUM;
    mat[3] = 0.0;

    mat[4] = (1.0-sat)*GLUM;
    mat[5] = (1.0-sat)*GLUM + sat;
    mat[6] = (1.0-sat)*GLUM;
    mat[7] = 0.0;

    mat[8] = (1.0-sat)*BLUM;
    mat[9] = (1.0-sat)*BLUM;
    mat[10] = (1.0-sat)*BLUM + sat;
    mat[11] = 0.0;

    mat[12] = 0.0;
    mat[13] = 0.0;
    mat[14] = 0.0;
    mat[15] = 1.0;
}

static void _php_colormatrix_usermat(double mat[16], zval** data)
{
	HashTable* mat_ht;
	HashPosition pos;

	convert_to_array_ex(data);

	mat_ht=(*data)->value.ht; // FIXME: should really use HASH_OF macro.
	                          // Filter API change needed to supply TSRMLS to filters
	zend_hash_internal_pointer_reset_ex(mat_ht,&pos);
	while (pos)
	{
	        char *str_index;
        	ulong num_index;
	        int retval;
		zval **value;

        	retval=zend_hash_get_current_key_ex(mat_ht,&str_index,NULL,&num_index,0,&pos);
		if (retval==HASH_KEY_IS_LONG)
		{
			if ((num_index>=0)&&(num_index<16))
			{
				zend_hash_get_current_data_ex(mat_ht,(void**)&value,&pos);
				convert_to_double_ex(value);
				mat[num_index]=Z_DVAL_PP(value);
			}
		}

		zend_hash_move_forward_ex(mat_ht,&pos);
	}
}

static int
_php_colormatrix_exec(Imlib_Image im, char* filter, HashTable* params)
{
      HashPosition pos;

      double mat[16];
      int x=0,y=0,w,h,imgw,imgh;

      _php_colormatrix_identmat(mat);

      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(filter,"cm_user"))
	  {
	          if (!strcmp(str_index,"matrix")) _php_colormatrix_usermat(mat,data);
	  }
          if (!strcmp(filter,"cm_saturation"))
	  {
	          if (!strcmp(str_index,"sat")) { convert_to_double_ex(data); _php_colormatrix_saturatemat(mat,Z_DVAL_PP(data)); };
	  }
          if (!strcmp(filter,"cm_huerot"))
	  {
	          if (!strcmp(str_index,"angle")) { convert_to_double_ex(data); _php_colormatrix_huerotatemat(mat,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++)
	  {
            int r,g,b,nr,ng,nb;
            DATA32 argb;

	    argb=*img_ptr;

            r=(argb&0x00ff0000)>>16;
            g=(argb&0x0000ff00)>>8;
            b=(argb&0x000000ff);

            nr = r*mat[0] + g*mat[4] + b*mat[8]  + mat[12];
	    ng = r*mat[1] + g*mat[5] + b*mat[9]  + mat[13];
	    nb = r*mat[2] + g*mat[6] + b*mat[10] + mat[14];
	    if (nr<0) nr=0;
	    if (nr>255) nr=255;
	    if (ng<0) ng=0;
	    if (ng>255) ng=255;
	    if (nb<0) nb=0;
	    if (nb>255) nb=255;

	    *img_ptr=(argb&0xff000000) | (nr<<16) | (ng<<8) | nb;

            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, "cm_user") || !strcmp(filter,"cm_saturation") || !strcmp(filter,"cm_huerot"))
	{
		return _php_colormatrix_exec(im,filter,params);
	}
	return FAILURE;
}

int
php_filter_getfiltercount()
{
	return 3;
}

void
php_filter_getfilternames(char** filternames)
{
	filternames[0]="cm_user";
	filternames[1]="cm_saturation";
	filternames[2]="cm_huerot";
}

void
php_filter_getextinfo(char** info)
{
	info[0]="Color Matrix";
	info[1]="Color processing using 4x4 matrices. Based on an article by Paul Haeberli.\n"
                "You can use built-in saturation and hue rotate filters (both filters maintain luminance), or supply your own matrix as a 16-element array. RGB values are computed as follows:\n"
                "r' = r*matrix[0] + g*matrix[4] + b*matrix[8]  + matrix[12]\n"
                "g' = r*matrix[1] + g*matrix[5] + b*matrix[9]  + matrix[13]\n"
                "b' = r*matrix[2] + g*matrix[6] + b*matrix[10] + matrix[14]";
	info[2]="Piotr Pawlow (pp@siedziba.pl)";
}

char*
php_filter_getparams(char* filter)
{
	if (!strcmp(filter, "cm_user")) return "int x=0, int y=0, int w=image_width, int h=image_height, array matrix=(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1)";
	if (!strcmp(filter, "cm_saturation")) return "int x=0, int y=0, int w=image_width, int h=image_height, double sat=1";
	if (!strcmp(filter, "cm_huerot")) return "int x=0, int y=0, int w=image_width, int h=image_height, double angle=0";
	return NULL;
}
ViewGit