Let's begin by creating two Imagick objects and load some PDFs.
<?php
declare(strict_types=1);
$controlDocument = new Imagick();
$compareDocument = new Imagick();
$controlDocument->readImage('control.pdf');
$compareDocument->readImage('compare.pdf');
If you try to run this code and get an exception about security policy: PHP Fatal error: Uncaught ImagickException: attempt to perform an operation not allowed by the security policy `PDF'
, you need to modify your ImageMagick policy to allow reading PDF files.
You can do that by opening /etc/ImageMagick-6/policy.xml
and delete or comment out this line.
<policy domain="coder" rights="none" pattern="PDF" />
Now if you run your script it should work without any errors.
Next let's go and actually compare our documents. We are going to use the included method called compareImages
. Add the following lines to our script.
$result = $controlDocument->compareImages($compareDocument, Imagick::METRIC_ABSOLUTEERRORMETRIC);
$result[0]->setImageFormat("png");
file_put_contents('diff.png', $result[0]);
This method returns an array containing our reconstructed image $result[0]
and number of pixels that are different $result[1]
(in our case since we are using AE as our metric).
We can calculate the difference in percentages using some simple math.
$diffPercentage = $result[1] * 100 / ($controlDocument->getImageWidth() * $controlDocument->getImageHeight());
echo number_format($diffPercentage, 4) . "%";
Here's how it looks on my example documents.
And here's the result image and difference.
Document is 1.7903% different.
Now you can easily adapt this code into your test suit.
Additional information
Find the example code here.
You can control the fuzziness of the pixel difference using the following code.
// Add this before loading the image
// Pixels may be different by up to 5% before being considered different
$controlDocument->setOption('fuzz', '5%');
You can control the image resolution.
// Add this before loading the image
$controlDocument->setResolution(100, 100);
$compareDocument->setResolution(100, 100);