Delicious Bookmark this on Delicious Share on Facebook SlashdotSlashdot It! Digg! Digg



PHP : Function Reference : Image Functions : imageconvolution

imageconvolution

Apply a 3x3 convolution matrix, using coefficient and offset (PHP 5 >= 5.1.0)
bool imageconvolution ( resource image, array matrix, float div, float offset )

Example 994. Embossing the PHP.net logo

<?php
$image
= imagecreatefromgif('http://www.php.net/images/php.gif');

$emboss = array(array(2, 0, 0), array(0, -1, 0), array(0, 0, -1));
imageconvolution($image, $emboss, 1, 127);

header('Content-Type: image/png');
imagepng($image, null, 9);
?>

The above example will output:

Example 995. Gaussian blur

<?php
$image
= imagecreatetruecolor(180,40);

// Writes the text and apply a gaussian blur on the image
imagestring($image, 5, 10, 8, 'Gaussian Blur Text', 0x00ff00);
$gaussian = array(array(1.0, 2.0, 1.0), array(2.0, 4.0, 2.0), array(1.0, 2.0, 1.0));
imageconvolution($image, $gaussian, 16, 0);

// Rewrites the text for comparison
imagestring($image, 5, 10, 18, 'Gaussian Blur Text', 0x00ff00);

header('Content-Type: image/png');
imagepng($image, null, 9);
?>

The above example will output:


Code Examples / Notes » imageconvolution

dyer85

Took me a while, but thanks to a couple of the user notes on the array_values PHP documentation page, I was able to come up with a way to dynamically compute the divisor.
I'm using PHP 5.1.0b2 on Win32 with the bundled GD library. When I try and use the imageconvolution function, whether normally, or via the functions below, the resulting image (I've only tried JPEGs and GIFs), always comes out far too bright, even when the divisor makes matrix sum equal to 1. The only thing that would reduce the brightness was to make the offset argument ridiculously large. So, I'm not sure if this effects anyone else.
Here are the functions with an example:
<?php
$im = imagecreatefromjpeg('path/to/pic.jpg');
$matrix = array(   array(5,5,5),
                  array(5,15,5),
                  array(5,5,5) );
makeFilter($im, $matrix);
header ( 'Content-Type: image/jpeg' );
imagejpeg($im);
imagedestroy($im);
/**
* functions
*/
// This flattens the 3X3 array matrix, so we can get the sum of all the values
function array_flatten($array) {
(array)$tempArray = array();
foreach ( $array as $value ) {
if ( is_array($value) ) {
$tempArray = array_merge($tempArray, array_flatten($value));
} else {
$tempArray[] = $value;
}
}
return $tempArray;
}
// Creates the divisor value dynamically, and passes offset
function makeFilter($resource, $matrix, $offset=1.0) {
global $$resource;
(float)$divisor = array_sum(array_flatten($matrix));
return imageconvolution($resource, $matrix, $divisor, $offset) ? true : false;
}
?>


27-oct-2005 01:32

The example below didn't provide a 3x3 matrix. Correctly, it's a multidimensional array.
<?php
   $matrix = array(    array( -1, -1, -1 ),
                       array( -1, 16, -1 ),
                       array( -1, -1, -1 ) );
?>


jase

The comment below is an extremely good workaround
however, php did throw lots of warnings at me when i had error reporting set to E_ALL
this can be avoided with one line of code and no impact (as i can see) to the rest of the function
<?php
//include this file whenever you have to use imageconvolution...
//you can use in your project, but keep the comment below :)
//great for any image manipulation library
//Made by Chao Xu(Mgccl) 2/28/07
//www.webdevlogs.com
//V 1.0
if(!function_exists('imageconvolution')){
function imageconvolution($src, $filter, $filter_div, $offset){
   if ($src==NULL) {
       return 0;
   }
   
   $sx = imagesx($src);
   $sy = imagesy($src);
   $srcback = ImageCreateTrueColor ($sx, $sy);
   ImageCopy($srcback, $src,0,0,0,0,$sx,$sy);
   
   if($srcback==NULL){
       return 0;
   }
       
   #FIX HERE
   #$pxl array was the problem so simply set it with very low values
   $pxl = array(1,1);
   #this little fix worked for me as the undefined array threw out errors
   for ($y=0; $y<$sy; ++$y){
       for($x=0; $x<$sx; ++$x){
           $new_r = $new_g = $new_b = 0;
           $alpha = imagecolorat($srcback, $pxl[0], $pxl[1]);
           $new_a = $alpha >> 24;
           
           for ($j=0; $j<3; ++$j) {
               $yv = min(max($y - 1 + $j, 0), $sy - 1);
               for ($i=0; $i<3; ++$i) {
                       $pxl = array(min(max($x - 1 + $i, 0), $sx - 1), $yv);
                   $rgb = imagecolorat($srcback, $pxl[0], $pxl[1]);
                   $new_r += (($rgb >> 16) & 0xFF) * $filter[$j][$i];
                   $new_g += (($rgb >> 8) & 0xFF) * $filter[$j][$i];
                   $new_b += ($rgb & 0xFF) * $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)? 255 : (($new_r < 0)? 0:$new_r);
           $new_g = ($new_g > 255)? 255 : (($new_g < 0)? 0:$new_g);
           $new_b = ($new_b > 255)? 255 : (($new_b < 0)? 0:$new_b);
           $new_pxl = ImageColorAllocateAlpha($src, (int)$new_r, (int)$new_g, (int)$new_b, $new_a);
           if ($new_pxl == -1) {
               $new_pxl = ImageColorClosestAlpha($src, (int)$new_r, (int)$new_g, (int)$new_b, $new_a);
           }
           if (($y >= 0) && ($y < $sy)) {
               imagesetpixel($src, $x, $y, $new_pxl);
           }
       }
   }
   imagedestroy($srcback);
   return 1;
}
}
?>


timeshifting

Matrices can be used for sharpening, blurring, edge detection, etc, ala Photoshop.
A sharpening example:
<?php
$sharpenMatrix = array(-1,-1,-1,-1,16,-1,-1,-1,-1);
$divisor = 8;
$offset = 0;
imageconvolution($myImage, $sharpenMatrix, $divisor, $offset);
?>
Below is some information on building different kinds of matrices. (If you have photoshop (or PSP, GIMP) you can test out your matrices before applying them in PHP)
http://loriweb.pair.com/8udf-basics.html (covers blurs)
http://loriweb.pair.com/8udf-sharpen.html
http://loriweb.pair.com/8udf-edges.html
http://loriweb.pair.com/8udf-emboss.html


mgcclx

imageconvolution() does not appear in PHP with non-bundled GD libraries. It is a rare situation, but it still happens. That's why I wrote a replication of imageconvolution() in PHP. Compare to the post below, this one makes the use of offset and 30% faster.
Because it's written in PHP, it is 50 times slower than the bundled version.
Actually, this is a replication of gdimageconvolutaion() of GD library, it does not support data validating feature imageconvolution() have. But I guess people who uses this function knows their stuff.
THE SCRIPT:
<?php
//include this file whenever you have to use imageconvolution...
//you can use in your project, but keep the comment below :)
//great for any image manipulation library
//Made by Chao Xu(Mgccl) 2/28/07
//www.webdevlogs.com
//V 1.0
if(!function_exists('imageconvolution')){
function imageconvolution($src, $filter, $filter_div, $offset){
if ($src==NULL) {
return 0;
}

$sx = imagesx($src);
$sy = imagesy($src);
$srcback = ImageCreateTrueColor ($sx, $sy);
ImageCopy($srcback, $src,0,0,0,0,$sx,$sy);

if($srcback==NULL){
return 0;
}

for ($y=0; $y<$sy; ++$y){
for($x=0; $x<$sx; ++$x){
$new_r = $new_g = $new_b = 0;
$alpha = imagecolorat($srcback, $pxl[0], $pxl[1]);
$new_a = $alpha >> 24;

for ($j=0; $j<3; ++$j) {
$yv = min(max($y - 1 + $j, 0), $sy - 1);
for ($i=0; $i<3; ++$i) {
       $pxl = array(min(max($x - 1 + $i, 0), $sx - 1), $yv);
   $rgb = imagecolorat($srcback, $pxl[0], $pxl[1]);
$new_r += (($rgb >> 16) & 0xFF) * $filter[$j][$i];
$new_g += (($rgb >> 8) & 0xFF) * $filter[$j][$i];
$new_b += ($rgb & 0xFF) * $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)? 255 : (($new_r < 0)? 0:$new_r);
$new_g = ($new_g > 255)? 255 : (($new_g < 0)? 0:$new_g);
$new_b = ($new_b > 255)? 255 : (($new_b < 0)? 0:$new_b);
$new_pxl = ImageColorAllocateAlpha($src, (int)$new_r, (int)$new_g, (int)$new_b, $new_a);
if ($new_pxl == -1) {
$new_pxl = ImageColorClosestAlpha($src, (int)$new_r, (int)$new_g, (int)$new_b, $new_a);
}
if (($y >= 0) && ($y < $sy)) {
imagesetpixel($src, $x, $y, $new_pxl);
}
}
}
imagedestroy($srcback);
return 1;
}
}
?>


mlconnor

I've seen many people come up with ways to do a drop shadow behind a rectangle such as a picture.  I haven't found one yet that was fast, PHP 4 complaint, and nice looking.  Here is one I came up with last night.  It takes an image, fills it with the background, and creates a blurred drop shadow at the specified coords using the colors and the distance offset specified.  It looks great!!!
 function blurRect(&$image, $distance, $rectX1, $rectY1, $rectX2, $rectY2, $shadowR, $shadowG, $shadowB, $backR, $backG, $backB) {
   $potentialOverlap = ($distance * 2) * ($distance * 2);
   $backgroundColor = imagecolorallocate($image, $backR, $backG, $backB);
   $shadowColor = imagecolorallocate($image, $shadowR, $shadowG, $shadowB);
   $imageWidth = imagesx($image);
   $imageHeight = imagesy($image);
   imageFilledRectangle($image, 0, 0, $imageWidth - 1, $imageHeight - 1, $backgroundColor);
   imageFilledRectangle($image, $rectX1, $rectY1, $rectX2, $rectY2, $shadowColor);
   for ( $pointX = $rectX1 - $distance; $pointX < $imageWidth; $pointX++ ) {
     for ( $pointY = $rectY1 - $distance; $pointY < $imageHeight; $pointY++ ) {
       if ( $pointX > $rectX1 + $distance &&
            $pointX < $rectX2 - $distance &&
            $pointY > $rectY1 + $distance &&
            $pointY < $rectY2 - $distance ) {
         $pointY = $rectY2 - $distance;
       }
       $boxX1 = $pointX - $distance;
       $boxY1 = $pointY - $distance;
       $boxX2 = $pointX + $distance;
       $boxY2 = $pointY + $distance;
       $xOverlap = max(0, min($boxX2, $rectX2) - max($boxX1, $rectX1));
       $yOverlap = max(0, min($boxY2, $rectY2) - max($boxY1, $rectY1));
       $totalOverlap = $xOverlap * $yOverlap;
       $shadowPcnt = $totalOverlap / $potentialOverlap;
       $backPcnt = 1.0 - $shadowPcnt;
       $newR = $shadowR * $shadowPcnt + $backR * $backPcnt;
       $newG = $shadowG * $shadowPcnt + $backG * $backPcnt;
       $newB = $shadowB * $shadowPcnt + $backB * $backPcnt;
       $newcol = imagecolorallocate($image, $newR, $newG, $newB);
       imagesetpixel($image, $pointX, $pointY, $newcol);
     }
   }
 }


jonathan dot aquino

For those who don't have PHP 5.1 and thus don't have imageconvolution, I found some code to do blurring: http://www.hudzilla.org/php/11_2_25.php  Works quite nicely.

interghost

an implementation of this function for PHP versions <5.1
<?php
if(!function_exists("imageconvolution"))
{
function imageconvolution(&$img,$mat,$div,$off)
{
  if(!imageistruecolor($img) || !is_array($mat) || count($mat)!=3 || count($mat[0])!=3 || count($mat[1])!=3 || count($mat[2])!=3) return FALSE;
  unset($bojainfo);
  for($nx=0;$nx<imagesx($img)-1;$nx++)
  {
    for($ny=0;$ny<imagesy($img)-1;$ny++)
    {
       $rgb=imagecolorat($img,$nx,$ny);
       $bojainfo[$nx][$ny][r]=($rgb>>16)&0xFF;
       $bojainfo[$nx][$ny][g]=($rgb>>8)&0xFF;
       $bojainfo[$nx][$ny][b]=$rgb&0xFF;
    }
  }
  for($nx=1;$nx<imagesx($img)-1;$nx++)
  {
    for($ny=1;$ny<imagesy($img)-1;$ny++)
    {
       $nr=$mat[0][0]*$bojainfo[$nx-1][$ny-1][r] + $mat[0][1]*$bojainfo[$nx][$ny-1][r] + $mat[0][2]*$bojainfo[$nx+1][$ny-1][r] + $mat[1][0]*$bojainfo[$nx-1][$ny][r] + $mat[1][1]*$bojainfo[$nx][$ny][r] + $mat[1][2]*$bojainfo[$nx+1][$ny][r] + $mat[2][0]*$bojainfo[$nx-1][$ny+1][r] + $mat[2][1]*$bojainfo[$nx][$ny+1][r] + $mat[2][2]*$bojainfo[$nx+1][$ny+1][r];
       $nr=intval(round($nr/$div));
       if($nr<0) $nr=0;
       elseif($nr>255) $nr=255;
       $ng=$mat[0][0]*$bojainfo[$nx-1][$ny-1][g]  + $mat[0][1]*$bojainfo[$nx][$ny-1][g] + $mat[0][2]*$bojainfo[$nx+1][$ny-1][g] + $mat[1][0]*$bojainfo[$nx-1][$ny][g] + $mat[1][1]*$bojainfo[$nx][$ny][g] + $mat[1][2]*$bojainfo[$nx+1][$ny][g] + $mat[2][0]*$bojainfo[$nx-1][$ny+1][g] + $mat[2][1]*$bojainfo[$nx][$ny+1][g] + $mat[2][2]*$bojainfo[$nx+1][$ny+1][g];
       $ng=intval(round($ng/$div));
       if($ng<0) $ng=0;
       elseif($ng>255) $ng=255;
       $nb=$mat[0][0]*$bojainfo[$nx-1][$ny-1][b] + $mat[0][1]*$bojainfo[$nx][$ny-1][b] + $mat[0][2]*$bojainfo[$nx+1][$ny-1][b] + $mat[1][0]*$bojainfo[$nx-1][$ny][b] + $mat[1][1]*$bojainfo[$nx][$ny][b] + $mat[1][2]*$bojainfo[$nx+1][$ny][b] + $mat[2][0]*$bojainfo[$nx-1][$ny+1][b] + $mat[2][1]*$bojainfo[$nx][$ny+1][b] + $mat[2][2]*$bojainfo[$nx+1][$ny+1][b];
       $nb=intval(round($nb/$div));
       if($nb<0) $nb=0;
       elseif($nb>255) $nb=255;
       $nrgb=($nr<<16)+($ng<<8)+$nb;
       if(!imagesetpixel($img,$nx,$ny,$nrgb)) return FALSE;
    }
  }
  return TRUE;
 }
}
?>
it's a bit slowish so I wouldn't recommend big images, also offset is not implemented (don't know what it's suppose to do)


Change Language


Follow Navioo On Twitter
gd_info
getimagesize
image_type_to_extension
image_type_to_mime_type
image2wbmp
imagealphablending
imageantialias
imagearc
imagechar
imagecharup
imagecolorallocate
imagecolorallocatealpha
imagecolorat
imagecolorclosest
imagecolorclosestalpha
imagecolorclosesthwb
imagecolordeallocate
imagecolorexact
imagecolorexactalpha
imagecolormatch
imagecolorresolve
imagecolorresolvealpha
imagecolorset
imagecolorsforindex
imagecolorstotal
imagecolortransparent
imageconvolution
imagecopy
imagecopymerge
imagecopymergegray
imagecopyresampled
imagecopyresized
imagecreate
imagecreatefromgd2
imagecreatefromgd2part
imagecreatefromgd
imagecreatefromgif
imagecreatefromjpeg
imagecreatefrompng
imagecreatefromstring
imagecreatefromwbmp
imagecreatefromxbm
imagecreatefromxpm
imagecreatetruecolor
imagedashedline
imagedestroy
imageellipse
imagefill
imagefilledarc
imagefilledellipse
imagefilledpolygon
imagefilledrectangle
imagefilltoborder
imagefilter
imagefontheight
imagefontwidth
imageftbbox
imagefttext
imagegammacorrect
imagegd2
imagegd
imagegif
imagegrabscreen
imagegrabwindow
imageinterlace
imageistruecolor
imagejpeg
imagelayereffect
imageline
imageloadfont
imagepalettecopy
imagepng
imagepolygon
imagepsbbox
imagepsencodefont
imagepsextendfont
imagepsfreefont
imagepsloadfont
imagepsslantfont
imagepstext
imagerectangle
imagerotate
imagesavealpha
imagesetbrush
imagesetpixel
imagesetstyle
imagesetthickness
imagesettile
imagestring
imagestringup
imagesx
imagesy
imagetruecolortopalette
imagettfbbox
imagettftext
imagetypes
imagewbmp
imagexbm
iptcembed
iptcparse
jpeg2wbmp
png2wbmp
eXTReMe Tracker