Note: Updated the convolution code .. approx 8 times faster now. Still slow though.
I've been working on a new and improved image convolution script .. so far so good so I thought I'd share some results:

What's going on in the image there then?
By taking a 7*7 convolution matrix as follows and multipling all the pixels in the image against it you can calculate the values of new pixels as an "average" of the pixels around it .. hence the blur effect.
The Matrix:
Code: Select all
$m = array( array(1,0,0,0,0,0,1),
array(0,2,0,0,0,2,0),
array(0,0,2,4,2,0,0),
array(0,0,4,8,4,0,0),
array(0,0,2,4,2,0,0),
array(0,2,0,0,0,2,0),
array(1,0,0,0,0,0,1)
);
Code: Select all
$time_start = microtime_float();
// Blur
$m = array( array(1,0,0,0,0,0,1),
array(0,2,0,0,0,2,0),
array(0,0,2,4,2,0,0),
array(0,0,4,8,4,0,0),
array(0,0,2,4,2,0,0),
array(0,2,0,0,0,2,0),
array(1,0,0,0,0,0,1)
);
$f = array_sum_multi($m);
$c = 0;
$m_elements = count($m);
$m_offset = floor($m_elements/2);
for ($m_y=0;$m_y<$m_elements;$m_y++) {
for ($m_x=0;$m_x<$m_elements;$m_x++) {
$mx[$m[$m_x][$m_y]][] = array($m_x-$m_offset,$m_y-$m_offset);
}
}
$original = imagecreatefromjpeg("xxx.jpg");
$source = imagecreatetruecolor(imagesx($original)+($m_offset*2),imagesy($original)+($m_offset*2));
$red = imagecolorallocate($source,255,0,0);
imagecopy($source, $original, $m_offset, $m_offset, 0, 0, imagesx($original),imagesy($original));
imagecopyresampled($source, $original, 0, 0, 0, 0, imagesx($original)+($m_offset*2), $m_offset, imagesx($original), $m_offset);
imagecopyresampled($source, $original, 0, imagesy($original)+$m_offset, 0, imagesy($original)-$m_offset, imagesx($original)+($m_offset*2), $m_offset, imagesx($original), $m_offset);
imagecopy($source, $original, 0, $m_offset, 0, 0, $m_offset, imagesy($original));
imagecopy($source, $original, imagesx($original)+$m_offset, $m_offset, imagesx($original)-$m_offset, 0, $m_offset, imagesy($original));
$image = imagecreatetruecolor(imagesx($original),imagesy($original));
for ($y=0;$y<imagesy($source);$y++) {
for ($x=0;$x<imagesx($source);$x++) {
$t1 = imagecolorat($source,$x,$y);
$p[$x][$y]['r'] = ($t1 >> 16) & 0xFF;
$p[$x][$y]['g'] = ($t1 >> & 0xFF;
$p[$x][$y]['b'] = $t1 & 0xFF;
}
}
for ($y=$m_offset;$y<imagesy($original)+$m_offset;$y++) {
for ($x=$m_offset;$x<imagesx($original)+$m_offset;$x++) {
$pixel_r = 0;
$pixel_g = 0;
$pixel_b = 0;
// Slooooooooooooooooooooow
// for ($m_y=0;$m_y<$m_elements;$m_y++) {
// for ($m_x=0;$m_x<$m_elements;$m_x++) {
// $pixel_r += ($p[$x+($m_x-$m_offset)][$y+($m_y-$m_offset)]['r']*$m[$m_x][$m_y]);
// $pixel_g += ($p[$x+($m_x-$m_offset)][$y+($m_y-$m_offset)]['g']*$m[$m_x][$m_y]);
// $pixel_b += ($p[$x+($m_x-$m_offset)][$y+($m_y-$m_offset)]['b']*$m[$m_x][$m_y]);
// }
// }
// Bit quicker
foreach ($mx as $m => $a) {
if ($m != 0) {
$pixel_r_temp = 0;
$pixel_g_temp = 0;
$pixel_b_temp = 0;
foreach ($a as $avals) {
$xt = $x+$avals[0];
$yt = $y+$avals[1];
$pixel_r_temp += ($p[$xt][$yt]['r']);
$pixel_g_temp += ($p[$xt][$yt]['g']);
$pixel_b_temp += ($p[$xt][$yt]['b']);
}
$pixel_r += $pixel_r_temp*$m;
$pixel_g += $pixel_g_temp*$m;
$pixel_b += $pixel_b_temp*$m;
}
}
$pixel_r = ($pixel_r/$f)+$c;
$pixel_g = ($pixel_g/$f)+$c;
$pixel_b = ($pixel_b/$f)+$c;
$col = imagecolorallocate($image,$pixel_r,$pixel_g,$pixel_b);
imagesetpixel($image,$x-$m_offset,$y-$m_offset,$col);
}
}
$black = imagecolorallocate($image,0,0,0);
$time_end = microtime_float();
$time = $time_end - $time_start;
imagestring($image, 3, 5, 5, $time, $black);
header("Content-Type: image/jpeg");
imageJPEG($image,"",100);
function array_sum_multi($a) {
if(!is_array($a)) return $a;
foreach($a as $key=>$value) {
$total += array_sum_multi($value);
}
return $total;
}
function microtime_float() {
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}