summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/gd/config.m42
-rw-r--r--ext/gd/config.w322
-rw-r--r--ext/gd/gd.c32
-rw-r--r--ext/gd/libgd/gd.h7
-rw-r--r--ext/gd/libgd/gd_pixelate.c57
-rw-r--r--ext/gd/tests/imagefilter.phpt11
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