imageconvolution

(PHP 5 >= 5.1.0RC1)

imageconvolution -- 用系数 div 和 offset 申请一个 3x3 的卷积矩阵

说明

bool imageconvolution ( resource image, array matrix3x3, float div, float offset )

如果成功则返回 TRUE,失败则返回 FALSE

警告

本函数暂无文档,仅有参数列表。

注: 本函数仅在 PHP 与其捆绑的 GD 库一起编译时可用。


add a note add a note User Contributed Notes
interghost at crovortex dot com
01-Apr-2006 03:26
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)
mlconnor at yahoo dot com
22-Mar-2006 01:00
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 at gmail dot com
18-Jan-2006 01:30
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.
dyer85 at gmail dot com
07-Jan-2006 06:24
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 08: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 ) );
?>
timeshifting at gmail dot com
25-Aug-2005 06:40
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