diff options
author | Pierre Joye <pajoye@php.net> | 2009-05-26 12:50:40 +0000 |
---|---|---|
committer | Pierre Joye <pajoye@php.net> | 2009-05-26 12:50:40 +0000 |
commit | b682f429158cd7c9f142100d3a781db52aa13af3 (patch) | |
tree | f509ede4d5720377c88ae7f86fc5ebb4e3cba82f | |
parent | 8b63e5b0928f3565104dbd6bc03e4c2438c97bcc (diff) | |
download | php-git-b682f429158cd7c9f142100d3a781db52aa13af3.tar.gz |
- [DOC] always enable imagefilter and imageconvolution, even when built against system's gd
-rw-r--r-- | ext/gd/config.m4 | 4 | ||||
-rw-r--r-- | ext/gd/config.w32 | 2 | ||||
-rw-r--r-- | ext/gd/gd.c | 11 | ||||
-rw-r--r-- | ext/gd/libgd/gd.c | 456 | ||||
-rw-r--r-- | ext/gd/libgd/gd_compat.h | 49 | ||||
-rw-r--r-- | ext/gd/libgd/gd_filter.c | 462 | ||||
-rw-r--r-- | ext/gd/libgd/gd_intern.h | 13 | ||||
-rw-r--r-- | ext/gd/php_gd.h | 5 |
8 files changed, 532 insertions, 470 deletions
diff --git a/ext/gd/config.m4 b/ext/gd/config.m4 index 151881b72b..bc3ee37d92 100644 --- a/ext/gd/config.m4 +++ b/ext/gd/config.m4 @@ -269,7 +269,7 @@ if test "$PHP_GD" = "yes"; then libgd/gdxpm.c libgd/gdfontt.c libgd/gdfonts.c libgd/gdfontmb.c libgd/gdfontl.c \ libgd/gdfontg.c libgd/gdtables.c libgd/gdft.c libgd/gdcache.c libgd/gdkanji.c \ libgd/wbmp.c libgd/gd_wbmp.c libgd/gdhelpers.c libgd/gd_topal.c libgd/gd_gif_in.c \ - libgd/xbm.c libgd/gd_gif_out.c libgd/gd_security.c libgd/gd_pixelate.c" + libgd/xbm.c libgd/gd_gif_out.c libgd/gd_security.c libgd/gd_filter.c libgd/gd_pixelate.c" dnl check for fabsf and floorf which are available since C99 AC_CHECK_FUNCS(fabsf floorf) @@ -342,7 +342,7 @@ else if test "$PHP_GD" != "no"; then GD_MODULE_TYPE=external - extra_sources="gdcache.c libgd/gd_compat.c" + extra_sources="gdcache.c libgd/gd_compat.c libgd/gd_filter.c libgd/gd_pixelate.c" dnl Various checks for GD features PHP_GD_ZLIB diff --git a/ext/gd/config.w32 b/ext/gd/config.w32 index d8eeedf66a..d59422da1f 100644 --- a/ext/gd/config.w32 +++ b/ext/gd/config.w32 @@ -33,7 +33,7 @@ if (PHP_GD != "no") { gdcache.c gdfontg.c gdfontl.c gdfontmb.c gdfonts.c gdfontt.c \ gdft.c gd_gd2.c gd_gd.c gd_gif_in.c gd_gif_out.c gdhelpers.c gd_io.c gd_io_dp.c \ gd_io_file.c gd_io_ss.c gd_jpeg.c gdkanji.c gd_png.c gd_ss.c \ - gdtables.c gd_topal.c gd_wbmp.c gdxpm.c wbmp.c xbm.c gd_security.c gd_pixelate.c", "gd"); + gdtables.c gd_topal.c gd_wbmp.c gdxpm.c wbmp.c xbm.c gd_security.c gd_filter.c gd_pixelate.c", "gd"); AC_DEFINE('HAVE_LIBGD', 1, 'GD support'); ADD_FLAG("CFLAGS_GD", " \ /D HAVE_GD_DYNAMIC_CTX_EX=1 \ diff --git a/ext/gd/gd.c b/ext/gd/gd.c index 6cc9741530..c56f75d495 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -132,7 +132,6 @@ int gdImageColorClosestHWB(gdImagePtr im, int r, int g, int b); * IMAGE_FILTER_MAX_ARGS: define the biggest amout of arguments * image_filter array in PHP_FUNCTION(imagefilter) * */ -#if HAVE_GD_BUNDLED #define IMAGE_FILTER_NEGATE 0 #define IMAGE_FILTER_GRAYSCALE 1 #define IMAGE_FILTER_BRIGHTNESS 2 @@ -159,7 +158,7 @@ static void php_image_filter_selective_blur(INTERNAL_FUNCTION_PARAMETERS); static void php_image_filter_mean_removal(INTERNAL_FUNCTION_PARAMETERS); static void php_image_filter_smooth(INTERNAL_FUNCTION_PARAMETERS); static void php_image_filter_pixelate(INTERNAL_FUNCTION_PARAMETERS); -#endif + /* End Section filters declarations */ static gdImagePtr _php_image_create_from_string (zval **Data, char *tn, gdImagePtr (*ioctx_func_p)() TSRMLS_DC); static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, gdImagePtr (*func_p)(), gdImagePtr (*ioctx_func_p)()); @@ -855,7 +854,6 @@ ZEND_BEGIN_ARG_INFO(arginfo_png2wbmp, 0) ZEND_END_ARG_INFO() #endif -#ifdef HAVE_GD_BUNDLED ZEND_BEGIN_ARG_INFO_EX(arginfo_imagefilter, 0, 0, 2) ZEND_ARG_INFO(0, im) ZEND_ARG_INFO(0, filtertype) @@ -871,7 +869,6 @@ ZEND_BEGIN_ARG_INFO(arginfo_imageconvolution, 0) ZEND_ARG_INFO(0, div) ZEND_ARG_INFO(0, offset) ZEND_END_ARG_INFO() -#endif #ifdef HAVE_GD_BUNDLED ZEND_BEGIN_ARG_INFO(arginfo_imageantialias, 0) @@ -1046,10 +1043,8 @@ const zend_function_entry gd_functions[] = { PHP_FE(imagexbm, arginfo_imagexbm) #endif /* gd filters */ -#ifdef HAVE_GD_BUNDLED PHP_FE(imagefilter, arginfo_imagefilter) PHP_FE(imageconvolution, arginfo_imageconvolution) -#endif {NULL, NULL, NULL} }; @@ -4738,8 +4733,6 @@ static void _php_image_convert(INTERNAL_FUNCTION_PARAMETERS, int image_type ) #endif /* HAVE_LIBGD */ /* Section Filters */ -#ifdef HAVE_GD_BUNDLED - #define PHP_GD_SINGLE_RES \ zval *SIM; \ gdImagePtr im_src; \ @@ -5033,9 +5026,9 @@ PHP_FUNCTION(imageconvolution) } } /* }}} */ - /* End section: Filters */ +#ifdef HAVE_GD_BUNDLED /* {{{ proto bool imageantialias(resource im, bool on) Should antialiased functions used or not*/ PHP_FUNCTION(imageantialias) diff --git a/ext/gd/libgd/gd.c b/ext/gd/libgd/gd.c index 75e37416fb..4b050d8d0b 100644 --- a/ext/gd/libgd/gd.c +++ b/ext/gd/libgd/gd.c @@ -3641,459 +3641,3 @@ void gdImageGetClip (gdImagePtr im, int *x1P, int *y1P, int *x2P, int *y2P) *y2P = im->cy2; } - -/* Filters function added on 2003/12 - * by Pierre-Alain Joye (pajoye@pearfr.org) - **/ -/* Begin filters function */ -#ifndef HAVE_GET_TRUE_COLOR -#define GET_PIXEL_FUNCTION(src)(src->trueColor?gdImageGetTrueColorPixel:gdImageGetPixel) -#endif - -/* invert src image */ -int gdImageNegate(gdImagePtr src) -{ - int x, y; - int r,g,b,a; - int new_pxl, pxl; - typedef int (*FuncPtr)(gdImagePtr, int, int); - FuncPtr f; - - if (src==NULL) { - return 0; - } - - f = GET_PIXEL_FUNCTION(src); - - for (y=0; y<src->sy; ++y) { - for (x=0; x<src->sx; ++x) { - pxl = f (src, x, y); - r = gdImageRed(src, pxl); - g = gdImageGreen(src, pxl); - b = gdImageBlue(src, pxl); - a = gdImageAlpha(src, pxl); - - new_pxl = gdImageColorAllocateAlpha(src, 255-r, 255-g, 255-b, a); - if (new_pxl == -1) { - new_pxl = gdImageColorClosestAlpha(src, 255-r, 255-g, 255-b, a); - } - gdImageSetPixel (src, x, y, new_pxl); - } - } - return 1; -} - -/* Convert the image src to a grayscale image */ -int gdImageGrayScale(gdImagePtr src) -{ - int x, y; - int r,g,b,a; - int new_pxl, pxl; - typedef int (*FuncPtr)(gdImagePtr, int, int); - FuncPtr f; - f = GET_PIXEL_FUNCTION(src); - - if (src==NULL) { - return 0; - } - - for (y=0; y<src->sy; ++y) { - for (x=0; x<src->sx; ++x) { - pxl = f (src, x, y); - r = gdImageRed(src, pxl); - g = gdImageGreen(src, pxl); - b = gdImageBlue(src, pxl); - a = gdImageAlpha(src, pxl); - r = g = b = (int) (.299 * r + .587 * g + .114 * b); - - new_pxl = gdImageColorAllocateAlpha(src, r, g, b, a); - if (new_pxl == -1) { - new_pxl = gdImageColorClosestAlpha(src, r, g, b, a); - } - gdImageSetPixel (src, x, y, new_pxl); - } - } - return 1; -} - -/* Set the brightness level <level> for the image src */ -int gdImageBrightness(gdImagePtr src, int brightness) -{ - int x, y; - int r,g,b,a; - int new_pxl, pxl; - typedef int (*FuncPtr)(gdImagePtr, int, int); - FuncPtr f; - f = GET_PIXEL_FUNCTION(src); - - if (src==NULL || (brightness < -255 || brightness>255)) { - return 0; - } - - if (brightness==0) { - return 1; - } - - for (y=0; y<src->sy; ++y) { - for (x=0; x<src->sx; ++x) { - pxl = f (src, x, y); - - r = gdImageRed(src, pxl); - g = gdImageGreen(src, pxl); - b = gdImageBlue(src, pxl); - a = gdImageAlpha(src, pxl); - - r = r + brightness; - g = g + brightness; - b = b + brightness; - - r = (r > 255)? 255 : ((r < 0)? 0:r); - g = (g > 255)? 255 : ((g < 0)? 0:g); - b = (b > 255)? 255 : ((b < 0)? 0:b); - - new_pxl = gdImageColorAllocateAlpha(src, (int)r, (int)g, (int)b, a); - if (new_pxl == -1) { - new_pxl = gdImageColorClosestAlpha(src, (int)r, (int)g, (int)b, a); - } - gdImageSetPixel (src, x, y, new_pxl); - } - } - return 1; -} - - -int gdImageContrast(gdImagePtr src, double contrast) -{ - int x, y; - int r,g,b,a; - double rf,gf,bf; - int new_pxl, pxl; - typedef int (*FuncPtr)(gdImagePtr, int, int); - - FuncPtr f; - f = GET_PIXEL_FUNCTION(src); - - if (src==NULL) { - return 0; - } - - contrast = (double)(100.0-contrast)/100.0; - contrast = contrast*contrast; - - for (y=0; y<src->sy; ++y) { - for (x=0; x<src->sx; ++x) { - pxl = f(src, x, y); - - r = gdImageRed(src, pxl); - g = gdImageGreen(src, pxl); - b = gdImageBlue(src, pxl); - a = gdImageAlpha(src, pxl); - - rf = (double)r/255.0; - rf = rf-0.5; - rf = rf*contrast; - rf = rf+0.5; - rf = rf*255.0; - - bf = (double)b/255.0; - bf = bf-0.5; - bf = bf*contrast; - bf = bf+0.5; - bf = bf*255.0; - - gf = (double)g/255.0; - gf = gf-0.5; - gf = gf*contrast; - gf = gf+0.5; - gf = gf*255.0; - - rf = (rf > 255.0)? 255.0 : ((rf < 0.0)? 0.0:rf); - gf = (gf > 255.0)? 255.0 : ((gf < 0.0)? 0.0:gf); - bf = (bf > 255.0)? 255.0 : ((bf < 0.0)? 0.0:bf); - - new_pxl = gdImageColorAllocateAlpha(src, (int)rf, (int)gf, (int)bf, a); - if (new_pxl == -1) { - new_pxl = gdImageColorClosestAlpha(src, (int)rf, (int)gf, (int)bf, a); - } - gdImageSetPixel (src, x, y, new_pxl); - } - } - return 1; -} - - -int gdImageColor(gdImagePtr src, const int red, const int green, const int blue, const int alpha) -{ - int x, y; - int new_pxl, pxl; - typedef int (*FuncPtr)(gdImagePtr, int, int); - FuncPtr f; - - if (src == NULL) { - return 0; - } - - f = GET_PIXEL_FUNCTION(src); - - for (y=0; y<src->sy; ++y) { - for (x=0; x<src->sx; ++x) { - int r,g,b,a; - - pxl = f(src, x, y); - r = gdImageRed(src, pxl); - g = gdImageGreen(src, pxl); - b = gdImageBlue(src, pxl); - a = gdImageAlpha(src, pxl); - - r = r + red; - g = g + green; - b = b + blue; - a = a + alpha; - - r = (r > 255)? 255 : ((r < 0)? 0 : r); - g = (g > 255)? 255 : ((g < 0)? 0 : g); - b = (b > 255)? 255 : ((b < 0)? 0 : b); - a = (a > 127)? 127 : ((a < 0)? 0 : a); - - new_pxl = gdImageColorAllocateAlpha(src, r, g, b, a); - if (new_pxl == -1) { - new_pxl = gdImageColorClosestAlpha(src, r, g, b, a); - } - gdImageSetPixel (src, x, y, new_pxl); - } - } - return 1; -} - -int gdImageConvolution(gdImagePtr src, float filter[3][3], float filter_div, float offset) -{ - int x, y, i, j, new_a; - float new_r, new_g, new_b; - int new_pxl, pxl=0; - gdImagePtr srcback; - typedef int (*FuncPtr)(gdImagePtr, int, int); - FuncPtr f; - - if (src==NULL) { - return 0; - } - - /* We need the orinal image with each safe neoghb. pixel */ - srcback = gdImageCreateTrueColor (src->sx, src->sy); - if (srcback==NULL) { - return 0; - } - - gdImageSaveAlpha(srcback, 1); - new_pxl = gdImageColorAllocateAlpha(srcback, 0, 0, 0, 127); - gdImageFill(srcback, 0, 0, new_pxl); - - gdImageCopy(srcback, src,0,0,0,0,src->sx,src->sy); - - f = GET_PIXEL_FUNCTION(src); - - for ( y=0; y<src->sy; y++) { - for(x=0; x<src->sx; x++) { - new_r = new_g = new_b = 0; - new_a = gdImageAlpha(srcback, pxl); - - for (j=0; j<3; j++) { - int yv = MIN(MAX(y - 1 + j, 0), src->sy - 1); - for (i=0; i<3; i++) { - pxl = f(srcback, MIN(MAX(x - 1 + i, 0), src->sx - 1), yv); - new_r += (float)gdImageRed(srcback, pxl) * filter[j][i]; - new_g += (float)gdImageGreen(srcback, pxl) * filter[j][i]; - new_b += (float)gdImageBlue(srcback, pxl) * filter[j][i]; - } - } - - new_r = (new_r/filter_div)+offset; - new_g = (new_g/filter_div)+offset; - new_b = (new_b/filter_div)+offset; - - new_r = (new_r > 255.0f)? 255.0f : ((new_r < 0.0f)? 0.0f:new_r); - new_g = (new_g > 255.0f)? 255.0f : ((new_g < 0.0f)? 0.0f:new_g); - new_b = (new_b > 255.0f)? 255.0f : ((new_b < 0.0f)? 0.0f:new_b); - - new_pxl = gdImageColorAllocateAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a); - if (new_pxl == -1) { - new_pxl = gdImageColorClosestAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a); - } - gdImageSetPixel (src, x, y, new_pxl); - } - } - gdImageDestroy(srcback); - return 1; -} - -int gdImageSelectiveBlur( gdImagePtr src) -{ - int x, y, i, j; - float new_r, new_g, new_b; - int new_pxl, cpxl, pxl, new_a=0; - float flt_r [3][3]; - float flt_g [3][3]; - float flt_b [3][3]; - float flt_r_sum, flt_g_sum, flt_b_sum; - - gdImagePtr srcback; - typedef int (*FuncPtr)(gdImagePtr, int, int); - FuncPtr f; - - if (src==NULL) { - return 0; - } - - /* We need the orinal image with each safe neoghb. pixel */ - srcback = gdImageCreateTrueColor (src->sx, src->sy); - if (srcback==NULL) { - return 0; - } - gdImageCopy(srcback, src,0,0,0,0,src->sx,src->sy); - - f = GET_PIXEL_FUNCTION(src); - - for(y = 0; y<src->sy; y++) { - for (x=0; x<src->sx; x++) { - flt_r_sum = flt_g_sum = flt_b_sum = 0.0; - cpxl = f(src, x, y); - - for (j=0; j<3; j++) { - for (i=0; i<3; i++) { - if ((j == 1) && (i == 1)) { - flt_r[1][1] = flt_g[1][1] = flt_b[1][1] = 0.5; - } else { - pxl = f(src, x-(3>>1)+i, y-(3>>1)+j); - new_a = gdImageAlpha(srcback, pxl); - - new_r = ((float)gdImageRed(srcback, cpxl)) - ((float)gdImageRed (srcback, pxl)); - - if (new_r < 0.0f) { - new_r = -new_r; - } - if (new_r != 0) { - flt_r[j][i] = 1.0f/new_r; - } else { - flt_r[j][i] = 1.0f; - } - - new_g = ((float)gdImageGreen(srcback, cpxl)) - ((float)gdImageGreen(srcback, pxl)); - - if (new_g < 0.0f) { - new_g = -new_g; - } - if (new_g != 0) { - flt_g[j][i] = 1.0f/new_g; - } else { - flt_g[j][i] = 1.0f; - } - - new_b = ((float)gdImageBlue(srcback, cpxl)) - ((float)gdImageBlue(srcback, pxl)); - - if (new_b < 0.0f) { - new_b = -new_b; - } - if (new_b != 0) { - flt_b[j][i] = 1.0f/new_b; - } else { - flt_b[j][i] = 1.0f; - } - } - - flt_r_sum += flt_r[j][i]; - flt_g_sum += flt_g[j][i]; - flt_b_sum += flt_b [j][i]; - } - } - - for (j=0; j<3; j++) { - for (i=0; i<3; i++) { - if (flt_r_sum != 0.0) { - flt_r[j][i] /= flt_r_sum; - } - if (flt_g_sum != 0.0) { - flt_g[j][i] /= flt_g_sum; - } - if (flt_b_sum != 0.0) { - flt_b [j][i] /= flt_b_sum; - } - } - } - - new_r = new_g = new_b = 0.0; - - for (j=0; j<3; j++) { - for (i=0; i<3; i++) { - pxl = f(src, x-(3>>1)+i, y-(3>>1)+j); - new_r += (float)gdImageRed(srcback, pxl) * flt_r[j][i]; - new_g += (float)gdImageGreen(srcback, pxl) * flt_g[j][i]; - new_b += (float)gdImageBlue(srcback, pxl) * flt_b[j][i]; - } - } - - new_r = (new_r > 255.0f)? 255.0f : ((new_r < 0.0f)? 0.0f:new_r); - new_g = (new_g > 255.0f)? 255.0f : ((new_g < 0.0f)? 0.0f:new_g); - new_b = (new_b > 255.0f)? 255.0f : ((new_b < 0.0f)? 0.0f:new_b); - new_pxl = gdImageColorAllocateAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a); - if (new_pxl == -1) { - new_pxl = gdImageColorClosestAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a); - } - gdImageSetPixel (src, x, y, new_pxl); - } - } - gdImageDestroy(srcback); - return 1; -} - -int gdImageEdgeDetectQuick(gdImagePtr src) -{ - float filter[3][3] = {{-1.0,0.0,-1.0}, - {0.0,4.0,0.0}, - {-1.0,0.0,-1.0}}; - - return gdImageConvolution(src, filter, 1, 127); -} - -int gdImageGaussianBlur(gdImagePtr im) -{ - float filter[3][3] = {{1.0,2.0,1.0}, - {2.0,4.0,2.0}, - {1.0,2.0,1.0}}; - - return gdImageConvolution(im, filter, 16, 0); -} - -int gdImageEmboss(gdImagePtr im) -{ -/* - float filter[3][3] = {{1.0,1.0,1.0}, - {0.0,0.0,0.0}, - {-1.0,-1.0,-1.0}}; -*/ - float filter[3][3] = {{ 1.5, 0.0, 0.0}, - { 0.0, 0.0, 0.0}, - { 0.0, 0.0,-1.5}}; - - return gdImageConvolution(im, filter, 1, 127); -} - -int gdImageMeanRemoval(gdImagePtr im) -{ - float filter[3][3] = {{-1.0,-1.0,-1.0}, - {-1.0,9.0,-1.0}, - {-1.0,-1.0,-1.0}}; - - return gdImageConvolution(im, filter, 1, 0); -} - -int gdImageSmooth(gdImagePtr im, float weight) -{ - float filter[3][3] = {{1.0,1.0,1.0}, - {1.0,0.0,1.0}, - {1.0,1.0,1.0}}; - - filter[1][1] = weight; - - return gdImageConvolution(im, filter, weight+8, 0); -} -/* End filters function */ diff --git a/ext/gd/libgd/gd_compat.h b/ext/gd/libgd/gd_compat.h index 086e6d2cd3..0f94f83c63 100644 --- a/ext/gd/libgd/gd_compat.h +++ b/ext/gd/libgd/gd_compat.h @@ -1,5 +1,54 @@ +#ifndef GD_COMPAT_H +#define GD_COMPAT_H 1 + +#if HAVE_GD_BUNDLED +# include "gd.h" +#else +# include <gd.h> +#endif + + + const char * gdPngGetVersionString(); int gdJpegGetVersionString(); int gdJpegGetVersionInt(); int overflow2(int a, int b); +/* filters section + * + * Negate the imag src, white becomes black, + * The red, green, and blue intensities of an image are negated. + * White becomes black, yellow becomes blue, etc. + */ +int gdImageNegate(gdImagePtr src); + +/* Convert the image src to a grayscale image */ +int gdImageGrayScale(gdImagePtr src); + +/* Set the brightness level <brightness> for the image src */ +int gdImageBrightness(gdImagePtr src, int brightness); + +/* Set the contrast level <contrast> for the image <src> */ +int gdImageContrast(gdImagePtr src, double contrast); + +/* Simply adds or substracts respectively red, green or blue to a pixel */ +int gdImageColor(gdImagePtr src, const int red, const int green, const int blue, const int alpha); + +/* Image convolution by a 3x3 custom matrix */ +int gdImageConvolution(gdImagePtr src, float ft[3][3], float filter_div, float offset); +int gdImageEdgeDetectQuick(gdImagePtr src); +int gdImageGaussianBlur(gdImagePtr im); +int gdImageSelectiveBlur( gdImagePtr src); +int gdImageEmboss(gdImagePtr im); +int gdImageMeanRemoval(gdImagePtr im); +int gdImageSmooth(gdImagePtr im, float weight); +enum gdPixelateMode { + GD_PIXELATE_UPPERLEFT, + GD_PIXELATE_AVERAGE +}; + +int gdImagePixelate(gdImagePtr im, int block_size, const unsigned int mode); + + +#endif + diff --git a/ext/gd/libgd/gd_filter.c b/ext/gd/libgd/gd_filter.c new file mode 100644 index 0000000000..084e15c20e --- /dev/null +++ b/ext/gd/libgd/gd_filter.c @@ -0,0 +1,462 @@ +#if HAVE_GD_BUNDLED +# include "gd.h" +#else +# include <gd.h> +#endif + +#include "gd_intern.h" +/* Filters function added on 2003/12 + * by Pierre-Alain Joye (pajoye@pearfr.org) + **/ +/* Begin filters function */ +#ifndef HAVE_GET_TRUE_COLOR +#define GET_PIXEL_FUNCTION(src)(src->trueColor?gdImageGetTrueColorPixel:gdImageGetPixel) +#endif + +/* invert src image */ +int gdImageNegate(gdImagePtr src) +{ + int x, y; + int r,g,b,a; + int new_pxl, pxl; + typedef int (*FuncPtr)(gdImagePtr, int, int); + FuncPtr f; + + if (src==NULL) { + return 0; + } + + f = GET_PIXEL_FUNCTION(src); + + for (y=0; y<src->sy; ++y) { + for (x=0; x<src->sx; ++x) { + pxl = f (src, x, y); + r = gdImageRed(src, pxl); + g = gdImageGreen(src, pxl); + b = gdImageBlue(src, pxl); + a = gdImageAlpha(src, pxl); + + new_pxl = gdImageColorAllocateAlpha(src, 255-r, 255-g, 255-b, a); + if (new_pxl == -1) { + new_pxl = gdImageColorClosestAlpha(src, 255-r, 255-g, 255-b, a); + } + gdImageSetPixel (src, x, y, new_pxl); + } + } + return 1; +} + +/* Convert the image src to a grayscale image */ +int gdImageGrayScale(gdImagePtr src) +{ + int x, y; + int r,g,b,a; + int new_pxl, pxl; + typedef int (*FuncPtr)(gdImagePtr, int, int); + FuncPtr f; + f = GET_PIXEL_FUNCTION(src); + + if (src==NULL) { + return 0; + } + + for (y=0; y<src->sy; ++y) { + for (x=0; x<src->sx; ++x) { + pxl = f (src, x, y); + r = gdImageRed(src, pxl); + g = gdImageGreen(src, pxl); + b = gdImageBlue(src, pxl); + a = gdImageAlpha(src, pxl); + r = g = b = (int) (.299 * r + .587 * g + .114 * b); + + new_pxl = gdImageColorAllocateAlpha(src, r, g, b, a); + if (new_pxl == -1) { + new_pxl = gdImageColorClosestAlpha(src, r, g, b, a); + } + gdImageSetPixel (src, x, y, new_pxl); + } + } + return 1; +} + +/* Set the brightness level <level> for the image src */ +int gdImageBrightness(gdImagePtr src, int brightness) +{ + int x, y; + int r,g,b,a; + int new_pxl, pxl; + typedef int (*FuncPtr)(gdImagePtr, int, int); + FuncPtr f; + f = GET_PIXEL_FUNCTION(src); + + if (src==NULL || (brightness < -255 || brightness>255)) { + return 0; + } + + if (brightness==0) { + return 1; + } + + for (y=0; y<src->sy; ++y) { + for (x=0; x<src->sx; ++x) { + pxl = f (src, x, y); + + r = gdImageRed(src, pxl); + g = gdImageGreen(src, pxl); + b = gdImageBlue(src, pxl); + a = gdImageAlpha(src, pxl); + + r = r + brightness; + g = g + brightness; + b = b + brightness; + + r = (r > 255)? 255 : ((r < 0)? 0:r); + g = (g > 255)? 255 : ((g < 0)? 0:g); + b = (b > 255)? 255 : ((b < 0)? 0:b); + + new_pxl = gdImageColorAllocateAlpha(src, (int)r, (int)g, (int)b, a); + if (new_pxl == -1) { + new_pxl = gdImageColorClosestAlpha(src, (int)r, (int)g, (int)b, a); + } + gdImageSetPixel (src, x, y, new_pxl); + } + } + return 1; +} + + +int gdImageContrast(gdImagePtr src, double contrast) +{ + int x, y; + int r,g,b,a; + double rf,gf,bf; + int new_pxl, pxl; + typedef int (*FuncPtr)(gdImagePtr, int, int); + + FuncPtr f; + f = GET_PIXEL_FUNCTION(src); + + if (src==NULL) { + return 0; + } + + contrast = (double)(100.0-contrast)/100.0; + contrast = contrast*contrast; + + for (y=0; y<src->sy; ++y) { + for (x=0; x<src->sx; ++x) { + pxl = f(src, x, y); + + r = gdImageRed(src, pxl); + g = gdImageGreen(src, pxl); + b = gdImageBlue(src, pxl); + a = gdImageAlpha(src, pxl); + + rf = (double)r/255.0; + rf = rf-0.5; + rf = rf*contrast; + rf = rf+0.5; + rf = rf*255.0; + + bf = (double)b/255.0; + bf = bf-0.5; + bf = bf*contrast; + bf = bf+0.5; + bf = bf*255.0; + + gf = (double)g/255.0; + gf = gf-0.5; + gf = gf*contrast; + gf = gf+0.5; + gf = gf*255.0; + + rf = (rf > 255.0)? 255.0 : ((rf < 0.0)? 0.0:rf); + gf = (gf > 255.0)? 255.0 : ((gf < 0.0)? 0.0:gf); + bf = (bf > 255.0)? 255.0 : ((bf < 0.0)? 0.0:bf); + + new_pxl = gdImageColorAllocateAlpha(src, (int)rf, (int)gf, (int)bf, a); + if (new_pxl == -1) { + new_pxl = gdImageColorClosestAlpha(src, (int)rf, (int)gf, (int)bf, a); + } + gdImageSetPixel (src, x, y, new_pxl); + } + } + return 1; +} + + +int gdImageColor(gdImagePtr src, const int red, const int green, const int blue, const int alpha) +{ + int x, y; + int new_pxl, pxl; + typedef int (*FuncPtr)(gdImagePtr, int, int); + FuncPtr f; + + if (src == NULL) { + return 0; + } + + f = GET_PIXEL_FUNCTION(src); + + for (y=0; y<src->sy; ++y) { + for (x=0; x<src->sx; ++x) { + int r,g,b,a; + + pxl = f(src, x, y); + r = gdImageRed(src, pxl); + g = gdImageGreen(src, pxl); + b = gdImageBlue(src, pxl); + a = gdImageAlpha(src, pxl); + + r = r + red; + g = g + green; + b = b + blue; + a = a + alpha; + + r = (r > 255)? 255 : ((r < 0)? 0 : r); + g = (g > 255)? 255 : ((g < 0)? 0 : g); + b = (b > 255)? 255 : ((b < 0)? 0 : b); + a = (a > 127)? 127 : ((a < 0)? 0 : a); + + new_pxl = gdImageColorAllocateAlpha(src, r, g, b, a); + if (new_pxl == -1) { + new_pxl = gdImageColorClosestAlpha(src, r, g, b, a); + } + gdImageSetPixel (src, x, y, new_pxl); + } + } + return 1; +} + +int gdImageConvolution(gdImagePtr src, float filter[3][3], float filter_div, float offset) +{ + int x, y, i, j, new_a; + float new_r, new_g, new_b; + int new_pxl, pxl=0; + gdImagePtr srcback; + typedef int (*FuncPtr)(gdImagePtr, int, int); + FuncPtr f; + + if (src==NULL) { + return 0; + } + + /* We need the orinal image with each safe neoghb. pixel */ + srcback = gdImageCreateTrueColor (src->sx, src->sy); + if (srcback==NULL) { + return 0; + } + + gdImageSaveAlpha(srcback, 1); + new_pxl = gdImageColorAllocateAlpha(srcback, 0, 0, 0, 127); + gdImageFill(srcback, 0, 0, new_pxl); + + gdImageCopy(srcback, src,0,0,0,0,src->sx,src->sy); + + f = GET_PIXEL_FUNCTION(src); + + for ( y=0; y<src->sy; y++) { + for(x=0; x<src->sx; x++) { + new_r = new_g = new_b = 0; + new_a = gdImageAlpha(srcback, pxl); + + for (j=0; j<3; j++) { + int yv = MIN(MAX(y - 1 + j, 0), src->sy - 1); + for (i=0; i<3; i++) { + pxl = f(srcback, MIN(MAX(x - 1 + i, 0), src->sx - 1), yv); + new_r += (float)gdImageRed(srcback, pxl) * filter[j][i]; + new_g += (float)gdImageGreen(srcback, pxl) * filter[j][i]; + new_b += (float)gdImageBlue(srcback, pxl) * filter[j][i]; + } + } + + new_r = (new_r/filter_div)+offset; + new_g = (new_g/filter_div)+offset; + new_b = (new_b/filter_div)+offset; + + new_r = (new_r > 255.0f)? 255.0f : ((new_r < 0.0f)? 0.0f:new_r); + new_g = (new_g > 255.0f)? 255.0f : ((new_g < 0.0f)? 0.0f:new_g); + new_b = (new_b > 255.0f)? 255.0f : ((new_b < 0.0f)? 0.0f:new_b); + + new_pxl = gdImageColorAllocateAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a); + if (new_pxl == -1) { + new_pxl = gdImageColorClosestAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a); + } + gdImageSetPixel (src, x, y, new_pxl); + } + } + gdImageDestroy(srcback); + return 1; +} + +int gdImageSelectiveBlur( gdImagePtr src) +{ + int x, y, i, j; + float new_r, new_g, new_b; + int new_pxl, cpxl, pxl, new_a=0; + float flt_r [3][3]; + float flt_g [3][3]; + float flt_b [3][3]; + float flt_r_sum, flt_g_sum, flt_b_sum; + + gdImagePtr srcback; + typedef int (*FuncPtr)(gdImagePtr, int, int); + FuncPtr f; + + if (src==NULL) { + return 0; + } + + /* We need the orinal image with each safe neoghb. pixel */ + srcback = gdImageCreateTrueColor (src->sx, src->sy); + if (srcback==NULL) { + return 0; + } + gdImageCopy(srcback, src,0,0,0,0,src->sx,src->sy); + + f = GET_PIXEL_FUNCTION(src); + + for(y = 0; y<src->sy; y++) { + for (x=0; x<src->sx; x++) { + flt_r_sum = flt_g_sum = flt_b_sum = 0.0; + cpxl = f(src, x, y); + + for (j=0; j<3; j++) { + for (i=0; i<3; i++) { + if ((j == 1) && (i == 1)) { + flt_r[1][1] = flt_g[1][1] = flt_b[1][1] = 0.5; + } else { + pxl = f(src, x-(3>>1)+i, y-(3>>1)+j); + new_a = gdImageAlpha(srcback, pxl); + + new_r = ((float)gdImageRed(srcback, cpxl)) - ((float)gdImageRed (srcback, pxl)); + + if (new_r < 0.0f) { + new_r = -new_r; + } + if (new_r != 0) { + flt_r[j][i] = 1.0f/new_r; + } else { + flt_r[j][i] = 1.0f; + } + + new_g = ((float)gdImageGreen(srcback, cpxl)) - ((float)gdImageGreen(srcback, pxl)); + + if (new_g < 0.0f) { + new_g = -new_g; + } + if (new_g != 0) { + flt_g[j][i] = 1.0f/new_g; + } else { + flt_g[j][i] = 1.0f; + } + + new_b = ((float)gdImageBlue(srcback, cpxl)) - ((float)gdImageBlue(srcback, pxl)); + + if (new_b < 0.0f) { + new_b = -new_b; + } + if (new_b != 0) { + flt_b[j][i] = 1.0f/new_b; + } else { + flt_b[j][i] = 1.0f; + } + } + + flt_r_sum += flt_r[j][i]; + flt_g_sum += flt_g[j][i]; + flt_b_sum += flt_b [j][i]; + } + } + + for (j=0; j<3; j++) { + for (i=0; i<3; i++) { + if (flt_r_sum != 0.0) { + flt_r[j][i] /= flt_r_sum; + } + if (flt_g_sum != 0.0) { + flt_g[j][i] /= flt_g_sum; + } + if (flt_b_sum != 0.0) { + flt_b [j][i] /= flt_b_sum; + } + } + } + + new_r = new_g = new_b = 0.0; + + for (j=0; j<3; j++) { + for (i=0; i<3; i++) { + pxl = f(src, x-(3>>1)+i, y-(3>>1)+j); + new_r += (float)gdImageRed(srcback, pxl) * flt_r[j][i]; + new_g += (float)gdImageGreen(srcback, pxl) * flt_g[j][i]; + new_b += (float)gdImageBlue(srcback, pxl) * flt_b[j][i]; + } + } + + new_r = (new_r > 255.0f)? 255.0f : ((new_r < 0.0f)? 0.0f:new_r); + new_g = (new_g > 255.0f)? 255.0f : ((new_g < 0.0f)? 0.0f:new_g); + new_b = (new_b > 255.0f)? 255.0f : ((new_b < 0.0f)? 0.0f:new_b); + new_pxl = gdImageColorAllocateAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a); + if (new_pxl == -1) { + new_pxl = gdImageColorClosestAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a); + } + gdImageSetPixel (src, x, y, new_pxl); + } + } + gdImageDestroy(srcback); + return 1; +} + +int gdImageEdgeDetectQuick(gdImagePtr src) +{ + float filter[3][3] = {{-1.0,0.0,-1.0}, + {0.0,4.0,0.0}, + {-1.0,0.0,-1.0}}; + + return gdImageConvolution(src, filter, 1, 127); +} + +int gdImageGaussianBlur(gdImagePtr im) +{ + float filter[3][3] = {{1.0,2.0,1.0}, + {2.0,4.0,2.0}, + {1.0,2.0,1.0}}; + + return gdImageConvolution(im, filter, 16, 0); +} + +int gdImageEmboss(gdImagePtr im) +{ +/* + float filter[3][3] = {{1.0,1.0,1.0}, + {0.0,0.0,0.0}, + {-1.0,-1.0,-1.0}}; +*/ + float filter[3][3] = {{ 1.5, 0.0, 0.0}, + { 0.0, 0.0, 0.0}, + { 0.0, 0.0,-1.5}}; + + return gdImageConvolution(im, filter, 1, 127); +} + +int gdImageMeanRemoval(gdImagePtr im) +{ + float filter[3][3] = {{-1.0,-1.0,-1.0}, + {-1.0,9.0,-1.0}, + {-1.0,-1.0,-1.0}}; + + return gdImageConvolution(im, filter, 1, 0); +} + +int gdImageSmooth(gdImagePtr im, float weight) +{ + float filter[3][3] = {{1.0,1.0,1.0}, + {1.0,0.0,1.0}, + {1.0,1.0,1.0}}; + + filter[1][1] = weight; + + return gdImageConvolution(im, filter, weight+8, 0); +} +/* End filters function */ diff --git a/ext/gd/libgd/gd_intern.h b/ext/gd/libgd/gd_intern.h new file mode 100644 index 0000000000..27f3d10bad --- /dev/null +++ b/ext/gd/libgd/gd_intern.h @@ -0,0 +1,13 @@ +#ifndef GD_INTERN_H +#define GD_INTERN_H +#ifndef MIN +#define MIN(a,b) ((a)<(b)?(a):(b)) +#endif +#define MIN3(a,b,c) ((a)<(b)?(MIN(a,c)):(MIN(b,c))) +#ifndef MAX +#define MAX(a,b) ((a)<(b)?(b):(a)) +#endif +#define MAX3(a,b,c) ((a)<(b)?(MAX(b,c)):(MAX(a,c))) + +#endif + diff --git a/ext/gd/php_gd.h b/ext/gd/php_gd.h index 008bb5d7d7..9091c16ef4 100644 --- a/ext/gd/php_gd.h +++ b/ext/gd/php_gd.h @@ -192,11 +192,12 @@ PHP_FUNCTION(image2wbmp); #if HAVE_GD_BUNDLED PHP_FUNCTION(imagelayereffect); PHP_FUNCTION(imagecolormatch); -PHP_FUNCTION(imagefilter); -PHP_FUNCTION(imageconvolution); PHP_FUNCTION(imagexbm); #endif +PHP_FUNCTION(imagefilter); +PHP_FUNCTION(imageconvolution); + PHP_GD_API int phpi_get_le_gd(void); #else |