Latest Articles
 by awuehr on 11-10-2008 in Tips & Tricks by Village Idiot on 11-04-2008 in Classes & Objects by codefreek on 10-23-2008 in Basic by wiifanatic on 09-12-2008 in Security & Permissions by drewbee on 07-03-2008 in Tips & Tricks
 IRC Channel
 Join the friendly bunch on IRC... (#TalkPHP on Freenode) ...Also available via a web interface. See this thread for information on the TalkPHP Free Hugs Initiative™. Subject to availability.
 Associates
 Associates
 TalkPHP » Pixelate algorithm using GD
 11-17-2008, 05:10 AM #1 (permalink) The Frequenter     Join Date: Sep 2007 Location: Denmark Posts: 352 Thanks: 8 Pixelate algorithm using GD Long time no script for here, so I decided that a function I was working on the other day might be useful for posting here. Its an pixelate algorithm written in PHP using GD, it includes a basic algorithm that works by coloring the pixel block the first color found in a block. The advanced algorithm iterates through all pixels and finds the average color in a block and colors it like that, through meaning more execution time. Source: PHP Code: ```      * @link    http://www.tuxxedo.net/     * @copyright    2006+     * @license    Microsoft Public License     *      * ========================================================================     */    function imagepixelate(\$im, \$blocksize, \$advanced = false)    {        if(!is_resource(\$im) || strtolower(get_resource_type(\$im)) != 'gd')        {            return;        }        \$blocksize     = (integer) \$blocksize;        \$sx        = imagesx(\$im);        \$sy        = imagesy(\$im);        if(\$blocksize <= 0)        {            return(false);        }        elseif(\$blocksize == 1)        {            return(true);        }        if(\$advanced)        {            for(\$x = 0; \$x < \$sx; \$x += \$blocksize)            {                for(\$y = 0; \$y < \$sy; \$y += \$blocksize)                {                    \$colors = Array(                            'alpha'        => 0,                             'red'        => 0,                             'green'        => 0,                             'blue'        => 0,                             'total'        => 0                            );                    for(\$cx = 0; \$cx < \$blocksize; ++\$cx)                    {                        for(\$cy = 0; \$cy < \$blocksize; ++\$cy)                        {                            if(\$x + \$cx >= \$sx || \$y + \$cy >= \$sy)                            {                                continue;                            }                            \$color = imagecolorat(\$im, \$x + \$cx, \$y + \$cy);                            imagecolordeallocate(\$im, \$color);                            \$colors['alpha']     += (\$color >> 24) & 0xFF;                            \$colors['red']        += (\$color >> 16) & 0xFF;                            \$colors['green']    += (\$color >> 8) & 0xFF;                            \$colors['blue']        += \$color & 0xFF;                            ++\$colors['total'];                        }                    }                    \$color = imagecolorallocatealpha(\$im,                                         \$colors['red'] / \$colors['total'],                                         \$colors['green'] / \$colors['total'],                                         \$colors['blue'] / \$colors['total'],                                         \$colors['alpha'] / \$colors['total']                                        );                    if(!@imagefilledrectangle(\$im, \$x, \$y, (\$x + \$blocksize - 1), (\$y + \$blocksize - 1), \$color))                    {                        return(false);                    }                }            }        }        else        {            for(\$x = 0; \$x < \$sx; \$x += \$blocksize)            {                for(\$y = 0; \$y < \$sy; \$y += \$blocksize)                {                    if(!@imagefilledrectangle(\$im, \$x, \$y, (\$x + \$blocksize - 1), (\$y + \$blocksize - 1), imagecolorat(\$im, \$x, \$y)))                    {                        return(false);                    }                }            }        }        return(true);    }?> ``` (Note that GD 2.0.1 or greater is required for this to work, but the chances that you're using GD 2.0.1 or greater is very high) The code is licensed under the Ms-Pl license which can be found at: http://www.opensource.org/licenses/ms-pl.html Prototype: `imagepixelate(resource \$image, integer \$blocksize [, boolean \$advanced = false])` The \$image parameter must be a resource valid resource, invalid resources NULL is returned. The \$blocksize parameter defines the blocksize in pixels. If a blocksize of 0 or lower is supplied the function will return false. Note that a blocksize of 1 wouldn't have any effect as each block already is one pixel so therefore the function just returns true. The \$advanced parameter is used to specify which algorithm to use, by default its using the simple algorithm, descriptions can be found above. Return values, NULL on invalid resource specified, FALSE on error and TRUE on success. Example code (basic): PHP Code: ``` ``` Example code (advanced): PHP Code: ``` ``` Example output (basic): Example output (advanced): A clear difference is visable, enjoy! :) C Version I've made a version, also written for gd. So in order to get it to work you have to be a minor libgd hacker. The C code is as follows: c Code: `int gdImagePixelate(gdImagePtr im, int blocksize, int advanced){    int x, y;    if (blocksize <= 0) {        return 0;    } else if (blocksize == 1) {        return 1;    }    if (advanced) {        int a, r, g, b, c;        int total;        int cx, cy;        for (x = 0; x < im->sx; x += blocksize) {            for (y = 0; y < im->sy; y += blocksize) {                a = r = g = b = c = total = 0;                for (cx = 0; cx < blocksize; cx++) {                    for (cy = 0; cy < blocksize; cy++) {                        if (gdImageBoundsSafe(im, (x + cx), (y + cy)) == 0) {                            continue;                        }                        c = gdImageGetPixel(im, (x + cx), (y + cy));                        gdImageColorDeallocate(im, c);                        a += (c >> 24) & 0xFF;                        r += (c >> 16) & 0xFF;                        g += (c >> 8) & 0xFF;                        b += c & 0xFF;                        total++;                    }                }                c = gdImageColorAllocateAlpha(im, r / total, g / total, b / total, a / total);                gdImageFilledRectangle(im, x, y, (x + blocksize - 1), (y + blocksize - 1), c);            }        }        return 1;    }    for (x = 0; x < im->sx; x += blocksize) {        for(y = 0; y < im->sy; y += blocksize) {            gdImageFilledRectangle(im, x, y, (x + blocksize - 1), (y + blocksize - 1), gdImageGetPixel(im, x, y));        }    }    return 1;}` Put that in the bottom of gd.c, and in the gd.h header after the other function prototypes then add the following: c Code: `int gdImagePixelate(gdImagePtr im, int blocksize, int advanced);` Its usage are exactly the same as the php version, except for this is on C level and much faster ofcourse. Furthermore for people who also hacks php a little you can alter the gd binding to support this function, I assume people who do this knows how the basic PHPAPI works so I'll only post the PHP_FUNCTION macro's body: c Code: `/* {{{ proto bool imagepixelate(resource im, int blocksize [, bool advanced])   Applies pixelation to the image */PHP_FUNCTION(imagepixelate){    zval *IM;    gdImagePtr im;    long blocksize;    zend_bool advanced = 0;    int retval;    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|b", &IM, &blocksize, &advanced) == FAILURE) {        return;    }    ZEND_FETCH_RESOURCE(im, gdImagePtr, &IM, -1, "Image", le_gd);    retval = gdImagePixelate(im, (int) blocksize, advanced);    if (retval) {        RETURN_TRUE;    } else {        RETURN_FALSE;    }}/* }}} */` I've submitted it as a feature request to GD itself and yet again, enjoy! :) __________________ Last edited by Wildhoney : 11-23-2008 at 04:13 PM.

 Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)