diff options
-rw-r--r-- | ext/gd/gd.c | 52 | ||||
-rw-r--r-- | ext/gd/libgd/gd.h | 12 | ||||
-rw-r--r-- | ext/gd/libgd/gd_filter.c | 102 | ||||
-rw-r--r-- | ext/gd/tests/imagefilter.phpt | 11 |
4 files changed, 175 insertions, 2 deletions
diff --git a/ext/gd/gd.c b/ext/gd/gd.c index f9319cf830..786589d263 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -112,7 +112,8 @@ int overflow2(int a, int b); #define IMAGE_FILTER_MEAN_REMOVAL 9 #define IMAGE_FILTER_SMOOTH 10 #define IMAGE_FILTER_PIXELATE 11 -#define IMAGE_FILTER_MAX 11 +#define IMAGE_FILTER_SCATTER 12 +#define IMAGE_FILTER_MAX 12 #define IMAGE_FILTER_MAX_ARGS 6 static void php_image_filter_negate(INTERNAL_FUNCTION_PARAMETERS); static void php_image_filter_grayscale(INTERNAL_FUNCTION_PARAMETERS); @@ -126,6 +127,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); +static void php_image_filter_scatter(INTERNAL_FUNCTION_PARAMETERS); /* End Section filters declarations */ static gdImagePtr _php_image_create_from_string (zval *Data, char *tn, gdImagePtr (*ioctx_func_p)()); @@ -1191,6 +1193,7 @@ PHP_MINIT_FUNCTION(gd) 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); + REGISTER_LONG_CONSTANT("IMG_FILTER_SCATTER", IMAGE_FILTER_SCATTER, CONST_CS | CONST_PERSISTENT); /* End Section Filters */ #ifdef GD_VERSION_STRING @@ -4455,6 +4458,50 @@ static void php_image_filter_pixelate(INTERNAL_FUNCTION_PARAMETERS) RETURN_FALSE; } +static void php_image_filter_scatter(INTERNAL_FUNCTION_PARAMETERS) +{ + zval *IM; + zval *hash_colors = NULL; + gdImagePtr im; + zend_long tmp; + zend_long scatter_sub, scatter_plus; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlll|a", &IM, &tmp, &scatter_sub, &scatter_plus, &hash_colors) == FAILURE) { + RETURN_FALSE; + } + + if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) { + RETURN_FALSE; + } + + if (hash_colors) { + uint32_t i = 0; + uint32_t num_colors = zend_hash_num_elements(Z_ARRVAL_P(hash_colors)); + zval *color; + int *colors; + + if (num_colors == 0) { + RETURN_BOOL(gdImageScatter(im, (int)scatter_sub, (int)scatter_plus)); + } + + colors = emalloc(num_colors * sizeof(int)); + + zend_hash_internal_pointer_reset(Z_ARRVAL_P(hash_colors)); + + while ((color = zend_hash_get_current_data(Z_ARRVAL_P(hash_colors))) != NULL) { + zend_hash_move_forward(Z_ARRVAL_P(hash_colors)); + + *(colors + i++) = (int) zval_get_long(color); + } + + RETVAL_BOOL(gdImageScatterColor(im, (int)scatter_sub, (int)scatter_plus, colors, num_colors)); + + efree(colors); + } else { + RETURN_BOOL(gdImageScatter(im, (int) scatter_sub, (int) scatter_plus)) + } +} + /* {{{ proto bool imagefilter(resource src_im, int filtertype[, int arg1 [, int arg2 [, int arg3 [, int arg4 ]]]] ) Applies Filter an image using a custom angle */ PHP_FUNCTION(imagefilter) @@ -4476,7 +4523,8 @@ PHP_FUNCTION(imagefilter) php_image_filter_selective_blur, php_image_filter_mean_removal, php_image_filter_smooth, - php_image_filter_pixelate + php_image_filter_pixelate, + php_image_filter_scatter }; if (ZEND_NUM_ARGS() < 2 || ZEND_NUM_ARGS() > IMAGE_FILTER_MAX_ARGS) { diff --git a/ext/gd/libgd/gd.h b/ext/gd/libgd/gd.h index 89a64041a0..30f59b38f6 100644 --- a/ext/gd/libgd/gd.h +++ b/ext/gd/libgd/gd.h @@ -717,6 +717,18 @@ enum gdPixelateMode { int gdImagePixelate(gdImagePtr im, int block_size, const unsigned int mode); +typedef struct { + int sub; + int plus; + unsigned int num_colors; + int *colors; + unsigned int seed; +} gdScatter, *gdScatterPtr; + +int gdImageScatter(gdImagePtr im, int sub, int plus); +int gdImageScatterColor(gdImagePtr im, int sub, int plus, int colors[], unsigned int num_colors); +int gdImageScatterEx(gdImagePtr im, gdScatterPtr s); + /* Macros to access information about images. */ /* Returns nonzero if the image is a truecolor image, diff --git a/ext/gd/libgd/gd_filter.c b/ext/gd/libgd/gd_filter.c index fc48cd08de..cebaa8785a 100644 --- a/ext/gd/libgd/gd_filter.c +++ b/ext/gd/libgd/gd_filter.c @@ -6,12 +6,114 @@ #include "gd_intern.h" +#ifdef _WIN32 +# include <windows.h> +#else +# include <unistd.h> +#endif +#include <stdlib.h> +#include <time.h> + /* Filters function added on 2003/12 * by Pierre-Alain Joye (pierre@php.net) + * + * Scatter filter added in libgd 2.1.0 + * by Kalle Sommer Nielsen (kalle@php.net) **/ + /* Begin filters function */ #define GET_PIXEL_FUNCTION(src)(src->trueColor?gdImageGetTrueColorPixel:gdImageGetPixel) +#ifdef _WIN32 +# define GD_SCATTER_SEED() (unsigned int)(time(0) * GetCurrentProcessId()) +#else +# define GD_SCATTER_SEED() (unsigned int)(time(0) * getpid()) +#endif + +int gdImageScatter(gdImagePtr im, int sub, int plus) +{ + gdScatter s; + + s.sub = sub; + s.plus = plus; + s.num_colors = 0; + s.seed = GD_SCATTER_SEED(); + return gdImageScatterEx(im, &s); +} + +int gdImageScatterColor(gdImagePtr im, int sub, int plus, int colors[], unsigned int num_colors) +{ + gdScatter s; + + s.sub = sub; + s.plus = plus; + s.colors = colors; + s.num_colors = num_colors; + s.seed = GD_SCATTER_SEED(); + return gdImageScatterEx(im, &s); +} + +int gdImageScatterEx(gdImagePtr im, gdScatterPtr scatter) +{ + register int x, y; + int dest_x, dest_y; + int pxl, new_pxl; + unsigned int n; + int sub = scatter->sub, plus = scatter->plus; + + if (plus == 0 && sub == 0) { + return 1; + } + else if (sub >= plus) { + return 0; + } + + (void)srand(scatter->seed); + + if (scatter->num_colors) { + for (y = 0; y < im->sy; y++) { + for (x = 0; x < im->sx; x++) { + dest_x = (int)(x + ((rand() % (plus - sub)) + sub)); + dest_y = (int)(y + ((rand() % (plus - sub)) + sub)); + + if (!gdImageBoundsSafe(im, dest_x, dest_y)) { + continue; + } + + pxl = gdImageGetPixel(im, x, y); + new_pxl = gdImageGetPixel(im, dest_x, dest_y); + + for (n = 0; n < scatter->num_colors; n++) { + if (pxl == scatter->colors[n]) { + gdImageSetPixel(im, dest_x, dest_y, pxl); + gdImageSetPixel(im, x, y, new_pxl); + } + } + } + } + } + else { + for (y = 0; y < im->sy; y++) { + for (x = 0; x < im->sx; x++) { + dest_x = (int)(x + ((rand() % (plus - sub)) + sub)); + dest_y = (int)(y + ((rand() % (plus - sub)) + sub)); + + if (!gdImageBoundsSafe(im, dest_x, dest_y)) { + continue; + } + + pxl = gdImageGetPixel(im, x, y); + new_pxl = gdImageGetPixel(im, dest_x, dest_y); + + gdImageSetPixel(im, dest_x, dest_y, pxl); + gdImageSetPixel(im, x, y, new_pxl); + } + } + } + + return 1; +} + /* invert src image */ int gdImageNegate(gdImagePtr src) { diff --git a/ext/gd/tests/imagefilter.phpt b/ext/gd/tests/imagefilter.phpt index 87efb1591e..a46cc1476e 100644 --- a/ext/gd/tests/imagefilter.phpt +++ b/ext/gd/tests/imagefilter.phpt @@ -82,6 +82,16 @@ $SOURCE_IMG = $SAVE_DIR . "/test.png"; } else { echo "IMG_FILTER_PIXELATE failed\n"; } + + $im = imagecreatefrompng($SOURCE_IMG); + + if (imagefilter($im, IMG_FILTER_SCATTER, 3, 5)) { + imagepng($im, $SAVE_DIR . "/IMG_FILTER_SCATTER.png"); + echo "IMG_FILTER_SCATTER success\n"; + unlink($SAVE_DIR . "/IMG_FILTER_SCATTER.png"); + } else { + echo "IMG_FILTER_SCATTER failed\n"; + } ?> --EXPECT-- IMG_FILTER_NEGATE success @@ -96,3 +106,4 @@ IMG_FILTER_COLORIZE success IMG_FILTER_CONTRAST success IMG_FILTER_BRIGHTNESS success IMG_FILTER_PIXELATE success +IMG_FILTER_SCATTER success |