image diff
Was having fun today with idiff.php - a PHP shell script to tell you if two images are visually different by comparing them pixel by pixel. If there's a difference, the script creates a third image - black background with the different pixels in green. Only after writing the script I found that there's an imagemagick command compare that does the same
the script
The idea is that two GD images are created from the input files, also a third GD image with black background to store the diff. Loop through all the pixels and compare them one by one. If one is different, write a green pixel at the same location of the diff image.
/** * Shell script to tell if two images are identical. * If not, a third image is written - black background with the different pixels painted green * Code partially inspired by and borrowed from http://pear.php.net/Image_Text test cases */ // check if there's enough input if (empty($argv[1]) || empty($argv[2])) { echo 'gimme at least two image filenames, please.', "\n"; echo 'e.g. "php idiff.php img1.png img2.png"'; echo "\n", 'third filename is the image diff, optional, default is "diffy.png"'; exit(1); } // create images $i1 = @imagecreatefromstring(file_get_contents($argv[1])); $i2 = @imagecreatefromstring(file_get_contents($argv[2])); // check if we were given garbage if (!$i1) { echo $argv[1] . ' is not a valid image'; exit(1); } if (!$i2) { echo $argv[2] . ' is not a valid image'; exit(1); } // dimensions of the first image $sx1 = imagesx($i1); $sy1 = imagesy($i1); // compare dimensions if ($sx1 !== imagesx($i2) || $sy1 !== imagesy($i2)) { echo "The images are not even the same size"; exit(1); } // create a diff image $diffi = imagecreatetruecolor($sx1, $sy1); $green = imagecolorallocate($diffi, 0, 255, 0); imagefill($diffi, 0, 0, imagecolorallocate($diffi, 0, 0, 0)); // increment this counter when encountering a pixel diff $different_pixels = 0; // loop x and y for ($x = 0; $x < $sx1; $x++) { for ($y = 0; $y < $sy1; $y++) { $rgb1 = imagecolorat($i1, $x, $y); $pix1 = imagecolorsforindex($i1, $rgb1); $rgb2 = imagecolorat($i2, $x, $y); $pix2 = imagecolorsforindex($i2, $rgb2); if ($pix1 !== $pix2) { // different pixel // increment and paint in the diff image $different_pixels++; imagesetpixel($diffi, $x, $y, $green); } } } if (!$different_pixels) { echo "Image is the same"; exit(0); } else { if (empty($argv[3])) { $argv[3] = 'diffy.png'; // default result filename } imagepng($diffi, $argv[3]); $total = $sx1 * $sy1; echo "$different_pixels/$total different pixels, or ", number_format(100 * $different_pixels / $total, 2), '%'; exit(1); }
usage
Type in the command line something like:
php idiff.php img1.png img2.png result.png
This command will compare img1.png with img2.png. If they are not the same dimensions, will exit with error code. If their pixels exactly the same will exit with success code 0 and print a success message. If the images are not the same, will write the file result.png.
If you omit result.png, the generated file will be called diffy.png
example
img1.png:

img2.png

running the command:
>php idiff.php img1.png img2.png 70/24600 different pixels, or 0.28%
the result diffy.png:

imagemagick
yep, so after I did this I found that imagemagick has a command called compare that does the same, only with more features, like the -fuzz option for example that allows you to specify how different should the pixels be, in order to consider them important.
the command:
>compare img1.png img2.png diffy-im.png
the diffy-im.png result

As you can see the different pixels are red and the actual image is a very pale background. Nice.
This entry was posted on Saturday, November 15th, 2008 and is filed under images, php. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.
Get notification for future posts: follow me on Twitter or subscribe to my RSS feed

November 16th, 2008 at 8:42 am
I guess, you need that for smush.it?
November 16th, 2008 at 1:13 pm
Hi Boštjan, for smush.it I already have a simpler version that just returns true when all pixels are the same or false when even one pixels is different. The idea is to have a guarantee that smush.it doesn’t affect quality at all and you can run it in a batch and don’t bother checking the results visually.
This was, yeah, somewhat related to smush.it, I wanted to see if I can replace jpegtran with imagemagick for JPEG optimization. Turns out that imagemagick gives smaller files, but when checking the number of colors, they were different. Now checked some diffs and turns out that IM indeed changes the image pixels, so it’s not totally safe, although it’s safe enough, I couldn’t possibly tell any difference, although with the help of the diffs I know where to look.
November 17th, 2008 at 8:31 am
Nice proof also, for someone that still thinks jpg’s are better
December 5th, 2008 at 11:26 am
[...] operations. Inspecting random images visually I couldn’t tell any difference but using an image diff utility shows that pixel information in the images has been [...]
April 8th, 2009 at 10:00 pm
[...] image diff [...]
October 22nd, 2009 at 1:16 am
[...] differencing. Perceptual Diff compares raster images. Image diff is a nicely simple php image differencer. I can find nothing on higher-level image raster [...]
December 21st, 2010 at 4:27 am
[...] lossless operations. Inspecting random images visually I couldn’t tell any difference but using an image diff utility shows that pixel information in the images has been [...]
May 28th, 2011 at 8:11 am
What would many of us do without the presence of the marvellous strategies you talk about on this website? Who else has the tolerance to deal with critical topics in the interests of common readers like me? I and my friends are very happy to have your site among the ones we often visit. Hopefully you know how very much we appreciate your working hard! Best wishes coming from us all.
November 3rd, 2011 at 2:07 pm
Imagent es el hosting de imagenes gratuito de gent10.com…
[...]image diff / Stoyan’s phpied.com[...]…
November 18th, 2011 at 4:36 pm
compra dominio…
[...]image diff / Stoyan’s phpied.com[...]…
March 20th, 2012 at 9:37 pm
Thank you, I have recently been searching for info about this subject for a long time and yours is the best I have came upon so far. But, what about the conclusion? Are you positive about the supply?|What i don’t realize is in reality how you are now not really a lot more smartly-preferred than you may be right now. You are very intelligent.
May 5th, 2012 at 12:58 pm
[...] command ">compare -metric AE -fuzz 10% image1.png image2.png output.png" does. I have found the http://www.phpied.com/image-diff/ code and it does well, but I really need the -fuzz capabilities to filter out the insignificant [...]