spatie/pixelmatch-php
PHP wrapper around pixelmatch for fast, simple image comparison. Generate diff images and measure mismatch percentages to spot visual regressions in tests or validate uploads. Works with common image formats via GD/Imagick depending on setup.
Start by installing the package via Composer:
composer require spatie/pixelmatch-php
Then ensure GD or Imagick is installed on your system (required for image processing). The package doesn’t bundle native dependencies — it delegates image handling to PHP’s GD extension.
The core use case is comparing two images (e.g., baseline vs. current screenshot) for visual regression. A minimal example:
use Spatie\Pixelmatch\Pixelmatch;
$diff = (new Pixelmatch())
->compare('baseline.png', 'current.png')
->toImage(); // returns GD resource
imagepng($diff, 'diff.png');
Check the README.md in the GitHub repo for examples — it’s minimal but covers the full API surface.
Testing: Use with PHPUnit for visual regression in UI components:
$this->assertLessThan(0.01, $pixelmatch->compare($base, $actual)->percentage());
(Note: percentage() returns 0.0–1.0, where 0 = identical.)
CI Integration: Generate and store diff images when thresholds are exceeded. In GitHub Actions, for example:
php tests/screenshots/comparator.php && echo "✅ No diffs" || { echo "❌ Diffs detected"; cp diff.png /tmp/diff.png; }
Upload the diff.png as an artifact for review.
Configurable Sensitivity: Adjust threshold, includeAA (anti-aliasing), and alpha in compare() calls:
$pixelmatch->compare($img1, $img2, [
'threshold' => 0.1, // stricter than default 0.1 (0.0–1.0)
'includeAA' => true,
]);
Batteries-optional: Pair with tools like Spatie’s browsershot for full visual testing pipeline: generate screenshots → compare with pixelmatch-php → fail build on regressions.
No fallback image formats: It only accepts PNG/GD/Imagick input — GIF/SVG require preprocessing (e.g., convert with Imagick::pingImage() + readImage() or external CLI).
Size mismatch defaults to full diff: If images differ in dimensions, the entire second image is treated as "changed" (i.e., diff covers whole area). Always resize first if needed:
$img2 = imagescale($img2, imagesx($img1), imagesy($img1));
Floating-point diff percentage can surprise: percentage() returns a float between 0 and 1 — don’t expect % value (e.g., 0.05 = 5%). Use round($pixelmatch->compare(...)->percentage() * 100, 2) for readability.
Memory limits in CI: Large screenshots (e.g., 1920×1080 PNGs) may exhaust memory on low-RAM runners. Mitigate by downsampling or using Imagick driver (more memory-efficient than GD for large images).
Extensibility: While the API is thin, you can pass custom pixelmatch options via the array parameter — consult the underlying pixelmatch JS library options to fine-tune sensitivity (e.g., threshold, alpha, antialiasing).
How can I help you explore Laravel packages today?