diff options
-rw-r--r-- | ext/gd/config.m4 | 2 | ||||
-rw-r--r-- | ext/gd/config.w32 | 2 | ||||
-rw-r--r-- | ext/gd/gd.c | 32 | ||||
-rw-r--r-- | ext/gd/libgd/gd.h | 7 | ||||
-rw-r--r-- | ext/gd/libgd/gd_pixelate.c | 57 | ||||
-rw-r--r-- | ext/gd/tests/imagefilter.phpt | 11 |
6 files changed, 107 insertions, 4 deletions
diff --git a/ext/gd/config.m4 b/ext/gd/config.m4 index 23ecc7ab1f..42cd9018ea 100644 --- a/ext/gd/config.m4 +++ b/ext/gd/config.m4 @@ -274,7 +274,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/xbm.c libgd/gd_gif_out.c libgd/gd_security.c libgd/gd_pixelate.c" dnl check for fabsf and floorf which are available since C99 AC_CHECK_FUNCS([fabsf floorf]) diff --git a/ext/gd/config.w32 b/ext/gd/config.w32 index 15033c0488..75d240c67e 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"); + gdtables.c gd_topal.c gd_wbmp.c gdxpm.c wbmp.c xbm.c gd_security.c gd_pixelate.c", "gd"); AC_DEFINE('HAVE_LIBGD', 1, 'GD support'); ADD_FLAG("CFLAGS_GD", " \ /D HAVE_GD_BUNDLED=1 \ diff --git a/ext/gd/gd.c b/ext/gd/gd.c index 13d45f9ede..640abc5503 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -112,7 +112,8 @@ int gdImageColorClosestHWB(gdImagePtr im, int r, int g, int b); #define IMAGE_FILTER_SELECTIVE_BLUR 8 #define IMAGE_FILTER_MEAN_REMOVAL 9 #define IMAGE_FILTER_SMOOTH 10 -#define IMAGE_FILTER_MAX 10 +#define IMAGE_FILTER_PIXELATE 11 +#define IMAGE_FILTER_MAX 11 #define IMAGE_FILTER_MAX_ARGS 5 static void php_image_filter_negate(INTERNAL_FUNCTION_PARAMETERS); static void php_image_filter_grayscale(INTERNAL_FUNCTION_PARAMETERS); @@ -125,6 +126,7 @@ static void php_image_filter_gaussian_blur(INTERNAL_FUNCTION_PARAMETERS); 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); @@ -1126,6 +1128,7 @@ PHP_MINIT_FUNCTION(gd) REGISTER_LONG_CONSTANT("IMG_FILTER_EMBOSS", IMAGE_FILTER_EMBOSS, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMG_FILTER_MEAN_REMOVAL", IMAGE_FILTER_MEAN_REMOVAL, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMG_FILTER_SMOOTH", IMAGE_FILTER_SMOOTH, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IMG_FILTER_PIXELATE", IMAGE_FILTER_PIXELATE, CONST_CS | CONST_PERSISTENT); /* End Section Filters */ #else REGISTER_LONG_CONSTANT("GD_BUNDLED", 0, CONST_CS | CONST_PERSISTENT); @@ -4606,6 +4609,30 @@ static void php_image_filter_smooth(INTERNAL_FUNCTION_PARAMETERS) RETURN_FALSE; } +static void php_image_filter_pixelate(INTERNAL_FUNCTION_PARAMETERS) +{ + zval *IM; + gdImagePtr im; + long tmp, blocksize, mode = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rll|l", &IM, &tmp, &blocksize, &mode) == FAILURE) { + RETURN_FALSE; + } + + ZEND_FETCH_RESOURCE(im, gdImagePtr, &IM, -1, "Image", le_gd); + + if (im == NULL) { + RETURN_FALSE; + } + + if (gdImagePixelate(im, (int) blocksize, (const unsigned int) mode)) { + RETURN_TRUE; + } + + RETURN_FALSE; +} + + /* {{{ proto bool imagefilter(resource src_im, int filtertype, [args] ) U Applies Filter an image using a custom angle */ PHP_FUNCTION(imagefilter) @@ -4626,7 +4653,8 @@ PHP_FUNCTION(imagefilter) php_image_filter_gaussian_blur, php_image_filter_selective_blur, php_image_filter_mean_removal, - php_image_filter_smooth + php_image_filter_smooth, + php_image_filter_pixelate }; if (ZEND_NUM_ARGS() < 2 || ZEND_NUM_ARGS() > 6) { diff --git a/ext/gd/libgd/gd.h b/ext/gd/libgd/gd.h index dfadeeb7d7..a186247056 100644 --- a/ext/gd/libgd/gd.h +++ b/ext/gd/libgd/gd.h @@ -577,6 +577,13 @@ void gdImageAlphaBlending(gdImagePtr im, int alphaBlendingArg); void gdImageAntialias(gdImagePtr im, int antialias); void gdImageSaveAlpha(gdImagePtr im, int saveAlphaArg); +enum gdPixelateMode { + GD_PIXELATE_UPPERLEFT, + GD_PIXELATE_AVERAGE +}; + +int gdImagePixelate(gdImagePtr im, int block_size, const unsigned int mode); + /* Macros to access information about images. */ /* Returns nonzero if the image is a truecolor image, diff --git a/ext/gd/libgd/gd_pixelate.c b/ext/gd/libgd/gd_pixelate.c new file mode 100644 index 0000000000..3808a6e55d --- /dev/null +++ b/ext/gd/libgd/gd_pixelate.c @@ -0,0 +1,57 @@ +#include "gd.h" + +int gdImagePixelate(gdImagePtr im, int block_size, const unsigned int mode) +{ + int x, y; + + if (block_size <= 0) { + return 0; + } else if (block_size == 1) { + return 1; + } + switch (mode) { + case GD_PIXELATE_UPPERLEFT: + for (y = 0; y < im->sy; y += block_size) { + for (x = 0; x < im->sx; x += block_size) { + if (gdImageBoundsSafe(im, x, y)) { + int c = gdImageGetPixel(im, x, y); + gdImageFilledRectangle(im, x, y, x + block_size - 1, y + block_size - 1, c); + } + } + } + break; + case GD_PIXELATE_AVERAGE: + for (y = 0; y < im->sy; y += block_size) { + for (x = 0; x < im->sx; x += block_size) { + int a, r, g, b, c; + int total; + int cx, cy; + + a = r = g = b = c = total = 0; + /* sampling */ + for (cy = 0; cy < block_size; cy++) { + for (cx = 0; cx < block_size; cx++) { + if (!gdImageBoundsSafe(im, x + cx, y + cy)) { + continue; + } + c = gdImageGetPixel(im, x + cx, y + cy); + a += gdImageAlpha(im, c); + r += gdImageRed(im, c); + g += gdImageGreen(im, c); + b += gdImageBlue(im, c); + total++; + } + } + /* drawing */ + if (total > 0) { + c = gdImageColorResolveAlpha(im, r / total, g / total, b / total, a / total); + gdImageFilledRectangle(im, x, y, x + block_size - 1, y + block_size - 1, c); + } + } + } + break; + default: + return 0; + } + return 1; +} diff --git a/ext/gd/tests/imagefilter.phpt b/ext/gd/tests/imagefilter.phpt index 5da5a66227..b62b5facfd 100644 --- a/ext/gd/tests/imagefilter.phpt +++ b/ext/gd/tests/imagefilter.phpt @@ -72,6 +72,16 @@ $SOURCE_IMG = $SAVE_DIR . "/test.png"; } else { echo "IMG_FILTER_BRIGHTNESS failed\n"; } + + $im = imagecreatefrompng($SOURCE_IMG); + + if (imagefilter($im, IMG_FILTER_PIXELATE, 5, 1)) { + imagepng($im, $SAVE_DIR . "/IMG_FILTER_PIXELATE.png"); + echo "IMG_FILTER_PIXELATE success\n"; + unlink($SAVE_DIR . "/IMG_FILTER_PIXELATE.png"); + } else { + echo "IMG_FILTER_PIXELATE failed\n"; + } ?> --EXPECT-- IMG_FILTER_NEGATE success @@ -85,3 +95,4 @@ IMG_FILTER_SMOOTH success IMG_FILTER_COLORIZE success IMG_FILTER_CONTRAST success IMG_FILTER_BRIGHTNESS success +IMG_FILTER_PIXELATE success |