jcupitt/vips
PHP FFI bindings for libvips (8.7+) on PHP 7.4+. Build fast, low-memory image processing pipelines and stream operations in parallel. Great for thumbnails, transforms, and saving to many formats with libvips speed.
## Getting Started
### Minimal Setup
1. **Install libvips system library**:
```bash
# Debian/Ubuntu
sudo apt-get install --no-install-recommends libvips42
# macOS (Homebrew)
brew install vips
# Windows: Download from [libvips.org](https://www.libvips.org/install.html)
Enable PHP FFI in php.ini:
ffi.enable=1
zend.max_allowed_stack_size=-1 # Required for PHP 8.3+
Install via Composer:
composer require jcupitt/vips
Verify installation:
use Jcupitt\Vips;
echo Vips\Config::version(); // Should print libvips version (e.g., "8.18.0")
use Jcupitt\Vips;
// Load image
$image = Vips\Image::newFromFile('input.jpg');
// Create thumbnail (128px width, auto-height)
$thumbnail = $image->thumbnail(128);
// Save result
$thumbnail->writeToFile('thumbnail.jpg');
examples/ directory – Practical use cases (e.g., animate-image.php, keep.php).Libvips follows a functional pipeline model where operations return new images without modifying the original. Chain operations for efficiency:
$processed = $image
->resize(0.5) // Half size
->sharpen(1.0) // Sharpen
->jpegsave('output.jpg', ['Q' => 85]); // Save with 85% quality
Use streaming operations to avoid loading entire images into memory:
// Stream from file to file (no full image in memory)
$image = Vips\Image::newFromFile('large.tif');
$image->writeToFile('compressed.jpg', ['Q' => 70]);
Key Methods:
newFromFile() – Load from disk.writeToFile() – Save to disk (supports formats like JPEG, PNG, TIFF).writeToMemory() – Return raw image data as a string.Process multiple images efficiently using libvips' parallel pipelines:
$images = ['img1.jpg', 'img2.jpg', 'img3.jpg'];
foreach ($images as $file) {
$img = Vips\Image::newFromFile($file);
$processed = $img->resize(0.7)->jpegsave("processed/{$file}");
}
Tip: Use Vips\Image::newFromBuffer() for in-memory processing:
$buffer = file_get_contents('image.jpg');
$img = Vips\Image::newFromBuffer($buffer);
compositeCombine images using blend modes (e.g., overlay, multiply):
$base = Vips\Image::newFromFile('background.jpg');
$overlay = Vips\Image::newFromFile('logo.png');
// Composite with "overlay" blend mode
$composite = $base->composite($overlay, Vips\BlendMode::OVERLAY);
$composite->writeToFile('result.jpg');
Blend Modes: OVERLAY, MULTIPLY, SCREEN, DARKEN, LIGHTEN, etc.
Monitor long-running operations:
$image = Vips\Image::newFromFile('huge.tif');
$image->setProgress(function ($progress) {
echo "Progress: " . round($progress * 100) . "%\n";
});
$image->resize(0.5)->writeToFile('small.tif');
Wrap operations in try-catch to handle libvips errors:
try {
$image = Vips\Image::newFromFile('corrupt.jpg');
} catch (Vips\Exception $e) {
logError("Failed to load image: " . $e->getMessage());
}
// ❌ Less efficient (creates temporary image)
$temp = $image->resize(0.5);
$result = $temp->sharpen(1.0);
// ✅ More efficient (pipeline)
$result = $image->resize(0.5)->sharpen(1.0);
keep() for debugging: Prevents garbage collection of intermediate images:
$debugImg = $image->resize(0.5)->keep();
writeToFile directly).zend.max_allowed_stack_size=-1 # Required in php.ini
| Error | Cause | Solution |
|---|---|---|
Failed to load libvips |
Missing system library | Install libvips (apt-get install libvips42) |
FFI extension not enabled |
PHP FFI disabled | Enable in php.ini (ffi.enable=1) |
Stack overflow (PHP 8.3+) |
FFI callback conflicts | Set zend.max_allowed_stack_size=-1 |
Unsupported format |
Missing libvips plugins | Install full libvips (apt-get install libvips-tools) |
Permission denied |
File access issues | Check open_basedir in php.ini |
echo Vips\Config::version(); // Should match system libvips
Vips\Image::setLogging(new \Monolog\Logger('vips'));
$image = Vips\Image::newFromFile('test.jpg');
print_r($image->getFields()); // Lists all available fields
Vips\FFI::addLibraryPath("C:/vips-dev-8.16/bin");
C:\path\to\image.jpg).RUN apt-get install -y libvips42
brew install vips and ensure PHP FFI is enabled.$ffi = FFI::cdef("
int custom_operation(double *data, int width, int height);
", "libcustom.so");
$result = $ffi->custom_operation($image->getData(), $image->width, $image->height);
class ImageProcessor {
public function optimize(Jcupitt\Vips\Image $image, int $quality): string {
return $image
->resize(0.8)
->jpegsave(null, ['Q' => $quality])
->writeToMemory();
}
}
/usr/lib/x86_64-linux-gnu/./usr/local/lib/libvips.dylib.Vips\FFI::addLibraryPath().How can I help you explore Laravel packages today?