image-driver-vips

Official libvips driver for Intervention Image, swapping in fast, low-memory image processing behind the same PHP API.

Library
Composer
v4.1.3
51stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
66/100Good
Development Activity80
Maintenance84
Community36
Maturity44
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
83/100Excellent
Architecture82
Code Quality90
Innovation78
Learning Curve80

image-driver-vips is Intervention Image’s official driver for libvips, the C image processing library that consistently outperforms PHP’s built-in GD and Imagick extensions on speed and memory footprint. Installing the package and pointing ImageManager::usingDriver() at Intervention\Image\Drivers\Vips\Driver is the only change required — every decode, modifier, and encode call in application code keeps working exactly as written against Intervention Image’s public API.

Under the hood, the driver reimplements every stage of that API — decoders, analyzers, modifiers, and encoders — as thin adapters around libvips’ demand-driven pipeline, accessed through the jcupitt/vips FFI bindings. It manages the tradeoffs specific to that pipeline itself: capping how many operations chain before rendering to memory to avoid stack overflows on deep operation chains, tracking stripped metadata separately because libvips regenerates EXIF blocks at save time, and falling back to per-frame processing when a libvips fast-path (like smart cropping) doesn’t apply. None of that complexity reaches the calling code.

What You Get

  • A Driver class implementing Intervention Image’s AbstractDriver contract, selected with a single ImageManager::usingDriver() call
  • Full parity across Intervention Image’s decoders, analyzers, modifiers, and encoders, each reimplemented against libvips instead of GD/Imagick
  • Format coverage including AVIF, HEIC, JPEG 2000, JPEG XL, WebP, TIFF, BMP, GIF, and PNG through libvips’ native codecs
  • Automatic pipeline-depth management that renders long modifier chains into memory before they risk overrunning libvips’ worker thread stack
  • A checkHealth() and version() surface for verifying the libvips FFI extension is installed and reporting the linked library version

Common Use Cases

  • Swapping an existing Intervention Image v4 project from GD or Imagick to libvips for lower memory use on large images
  • High-throughput thumbnail and watermark pipelines where libvips’ streaming decode/encode reduces per-request memory pressure
  • Batch resizing and format conversion jobs (e.g. to AVIF or WebP) that benefit from libvips’ faster codec paths
  • Self-hosted media processing services that need predictable memory behavior under concurrent image transforms
  • Projects already using PHP’s FFI extension that want to avoid installing and configuring the separate Imagick PECL extension

Under The Hood

Architecture The driver follows Intervention Image’s plugin-driver contract exactly: Driver extends AbstractDriver and wires up a Core (implementing CoreInterface/Iterator over frames), plus one class per operation under Analyzers/, Decoders/, Encoders/, and Modifiers/, each extending a generic base class from the parent intervention/image package and marked SpecializedInterface to opt into the libvips-specific path. Core::setNative() is the architectural crux: it counts chained libvips operations and forces a copyMemory() render once a MAX_CHAINED_OPERATIONS threshold (32, calibrated against measured worker-thread stack limits on macOS arm64, musl, and glibc) is crossed, trading a one-time memory materialization for immunity to SIGBUS/SIGSEGV crashes on long chains like tiled watermarking or many-shape drawing loops. Metadata-stripped state is tracked as an explicit flag on Core rather than inferred from the image, because libvips synthesizes an EXIF block at save time regardless of what fields were removed.

Tech Stack Built for PHP 8.3+ against intervention/image ^4.2 (the driver contract it implements) and jcupitt/vips ^2.6, the FFI-based PHP bindings to the libvips C library — meaning the PHP FFI extension is a hard runtime requirement, not just a recommendation. Dev tooling runs PHPUnit 12 for tests, PHPStan at level 6 with checked-exception enforcement turned on, PHP_CodeSniffer with the Slevomat coding standard, and a Docker/docker-compose setup for containerized local development against a matching libvips build. Composer autoloading is standard PSR-4 under the Intervention\Image\Drivers\Vips\ namespace.

Code Quality Test coverage mirrors the src/ layout file-for-file — every analyzer, decoder, encoder, and modifier has a corresponding Unit test, run against real sample images (JPEG, PNG, GIF, animated GIF, CMYK, ICC-profiled, EXIF-oriented) rather than mocks. strict_types is declared throughout, exceptions are typed into a dedicated hierarchy (DriverException, ModifierException, EncoderException, etc.) with @throws annotations enforced by PHPStan’s missingCheckedExceptionInThrows check — a stricter contract than most PHP projects opt into. CI runs the full matrix (PHP 8.3–8.5 × two libvips versions, built from source) on every push, executing PHPUnit, PHPStan, and PHPCS as required gates.

API Design The defining design choice is that there is no new API to learn: swapping to this driver changes zero call sites in application code, which is the entire point of Intervention Image’s driver abstraction. Where the driver does add its own surface, it stays narrow and purposeful — version() and checkHealth() for operational diagnostics, and quietly using libvips fast-paths (like smartcrop for content-aware cropping) only when the request pattern allows it, falling back to the generic per-frame implementation otherwise so behavior stays correct even when the libvips shortcut doesn’t apply.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search