Page 1 of 1

Blurring an image - Advanced convolution [56kb warning]

Posted: Mon Nov 14, 2005 2:39 pm
by onion2k
Note to mods: Don't move this to code snippets coz it's unoptimized and not useable yet. It'll undergo improvements.

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:

Image

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)
			  );
The convolution script:

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);
	}

Posted: Thu Dec 22, 2005 3:48 pm
by malcolmboston
bloody awesome, as usual

Posted: Thu Dec 22, 2005 3:55 pm
by hawleyjr
You blurred her face but left her ear??? I vote for showing the face and blurring the ear.

:lol: :lol: :lol: :lol: :lol:

Very nice :)

Posted: Thu Jan 12, 2006 2:09 pm
by alex.barylski
hawleyjr wrote:You blurred her face but left her ear??? I vote for showing the face and blurring the ear.

:lol: :lol: :lol: :lol: :lol:

Very nice :)
I agree....she's pretty hot 8)

Posted: Thu Jan 12, 2006 3:49 pm
by Ree
It would have been nice if you showed two full pics (blurred and original) rather than half of both.

Cool stuff, 'nuff said.

Re: Blurring an image - Advanced convolution [56kb warning]

Posted: Sun Aug 15, 2010 12:46 pm
by deano_1987
Hey guys, I made some small changes to this script so I could load a GIF with transparency :) I will post again soon with a more updated version for handling any file you chuck at it (with reason...).

Hope this is useful to people :)

Code: Select all

<?php
//Blur Script
//Created by: onion2k
//From Fourms: http://forums.devnetwork.net
//Modified by: Dean Williams
//Website: http://dean.resplace.net

//Filename
$name="mygif.gif";

//$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);
        }
}
//Un-comment for accepting filename via $_GET.
//$name=str_replace(array("/","\\"),array("",""),$_GET['f']);
$original = imagecreatefromgif($name);
imagealphablending($original, false);
imagesavealpha($original, true);
$source = imagecreatetruecolor(imagesx($original)+($m_offset*2),imagesy($original)+($m_offset*2));
imagealphablending($source, true);
$bg = ImageColorAllocateAlpha($source, 255, 255, 255, 127); // (PHP 4 >= 4.3.2, PHP 5)
ImageFill($source, 0, 0 , $bg);
$red = imagecolorallocate($source,255,0,0);
imagecopyresampled($source, $original, $m_offset, $m_offset, 0, 0, imagesx($original),imagesy($original), 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);
imagecopyresampled($source, $original, 0, $m_offset, 0, 0, $m_offset, imagesy($original), $m_offset, imagesy($original));
imagecopyresampled($source, $original, imagesx($original)+$m_offset, $m_offset, imagesx($original)-$m_offset, 0, $m_offset, imagesy($original), $m_offset, imagesy($original));
$image = imagecreatetruecolor(imagesx($original),imagesy($original));
$bg = ImageColorAllocateAlpha($image, 255, 255, 255, 127); // (PHP 4 >= 4.3.2, PHP 5)
ImageFill($image, 0, 0 , $bg);
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 >> 8) & 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/png");
imagePNG($image);
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);
}
?>