[PHP-DEV] Suggestion: ImageCopyResizedBicubic From: Per-Olov Jernberg (jernberg <email protected>)
Date: 01/03/01

Here's the code for my ImageCopyResizedBicubic function, a function that implements bicubic interpolation within the image scale function.

--------------------------------------------------------------------------cut--------------------------------------------------------------------------
/* {{{ proto int imagecopyresizedbicubic(int dst_im, int src_im, int dst_x, int dst_y, int src_x, int src_y, int dst_w, int dst_h, int src_w, int src_h)
   Copy and resize part of an image */
PHP_FUNCTION(imagecopyresizedbicubic)
{
 zval **SIM, **DIM, **SX, **SY, **SW, **SH, **DX, **DY, **DW, **DH;
 gdImagePtr im_dst, im_src;
 int srcH, srcW, dstH, dstW, srcY, srcX, dstY, dstX;
 int i, j;
 int r, g, b, c1,c2,c3,c4,color;
 float sX, sY;
 float scaleX,scaleY,scaleX2,scaleY2;
 GDLS_FETCH();

 if (ZEND_NUM_ARGS() != 10 ||
  zend_get_parameters_ex(10, &DIM, &SIM, &DX, &DY, &SX, &SY, &DW, &DH, &SW, &SH) == FAILURE)
 {
  WRONG_PARAM_COUNT;
 }

 ZEND_FETCH_RESOURCE(im_dst, gdImagePtr, DIM, -1, "Image", le_gd);
 ZEND_FETCH_RESOURCE(im_src, gdImagePtr, SIM, -1, "Image", le_gd);

 convert_to_long_ex(SX);
 convert_to_long_ex(SY);
 convert_to_long_ex(SW);
 convert_to_long_ex(SH);
 convert_to_long_ex(DX);
 convert_to_long_ex(DY);
 convert_to_long_ex(DW);
 convert_to_long_ex(DH);

 srcX = Z_LVAL_PP(SX);
 srcY = Z_LVAL_PP(SY);
 srcH = Z_LVAL_PP(SH);
 srcW = Z_LVAL_PP(SW);
 dstX = Z_LVAL_PP(DX);
 dstY = Z_LVAL_PP(DY);
 dstH = Z_LVAL_PP(DH);
 dstW = Z_LVAL_PP(DW);

 // copy the palette (this is a bug since it doesnt seem to be possible to make a truecolor bitmap as output, so we just have to use the old palette)

 for( i=0; i<256; i++ ) {
  gdImageColorAllocate( im_dst, im_src->red[i], im_src->green[i], im_src->blue[i] );
 };

 // gdImageCopyResized(im_dst, im_src, dstX, dstY, srcX, srcY, dstW, dstH, srcW, srcH);

 scaleX = (float)(srcW-1) / (float)dstW;
 scaleY = (float)(srcH-1) / (float)dstH;

 scaleX2 = scaleX/2.0f;
 scaleY2 = scaleY/2.0f;

 for( j=0; j<dstH; j++ ) {
  for( i=0; i<dstW; i++ ) {

   sX = (float)i * scaleX;
   sY = (float)j * scaleY;

   c1 = gdImageGetPixel(im_src, (int)(sX), (int)(sY+scaleY2) );
   c2 = gdImageGetPixel(im_src, (int)(sX), (int)(sY) );
   c3 = gdImageGetPixel(im_src, (int)(sX+scaleX2), (int)(sY+scaleY2) );
   c4 = gdImageGetPixel(im_src, (int)(sX+scaleX2), (int)(sY) );

   r = (im_src->red[c1] + im_src->red[c2] + im_src->red[c3] + im_src->red[c4]) / 4;
   g = (im_src->green[c1] + im_src->green[c2] + im_src->green[c3] + im_src->green[c4]) / 4;
   b = (im_src->blue[c1] + im_src->blue[c2] + im_src->blue[c3] + im_src->blue[c4]) / 4;

   color=gdImageColorClosest(im_dst,r,g,b);
   gdImageSetPixel( im_dst, (i+dstX),(j+dstY), color );

  };
 };

 RETURN_TRUE;
}
--------------------------------------------------------------------------cut--------------------------------------------------------------------------

good result when scaling down images, result wont be good when scaling up a image since the palette is copied from the source-bitmap so, if the source bitmap is 4colors the resulting bitmap is also 4color :/ i dont know if it is possible to create a image with more than 256 colors in the gd lib since i didnt have the source ... but, hey, this works for scaling down images...

i'll try to fix the downscaling bug when i know how to allocate more than 256 colors... if anyone know how to do that, please contact me!