Skip to content

OpalImage Processing for PHP

High-performance image processing for PHP, powered by libvips

Opal

Quick Example

php
use PhpMlKit\Opal\Image;
use PhpMlKit\Opal\Color;
use PhpMlKit\Opal\ColorSpace;
use PhpMlKit\Opal\Kernel;
use PhpMlKit\Opal\SaveOptions;

// Load an image
$img = Image::fromFile('photo.jpg');

// Chain transforms (nothing executes until you save or export)
$result = $img
    ->resize(1920, 1080, Kernel::Lanczos3)
    ->sharpen(sigma: 1.5)
    ->saturation(1.1);

// Draw overlays
$result = $result
    ->drawRect(50, 50, 200, 100, Color::red(), fill: false)
    ->drawText('Label', 60, 70, color: Color::white());

// Save with format options
$result->toFile('output.jpg', SaveOptions::jpeg(quality: 90, strip: true));

// Export as NDArray for ML pipelines
$array = $result->toArray(ChannelFormat::CHW);

Why Opal?

Performance That Matters

PHP image processing has traditionally meant GD (slow, limited) or Imagick (heavy, memory-hungry). Opal changes that with libvips — a C library that's consistently 3–10× faster than GD and 10–55× faster than Imagick in real-world pipelines.

Benchmarks below run the full pipeline — load JPEG → resize → rotate 45° → sharpen — testing each library on four image sizes (lower is better).

ImageGDImagickOpal
640×4808.48 ms128.55 ms1.56 ms
1920×108049.67 ms721.97 ms5.36 ms
4000×2670152.74 ms2,039.15 ms15.47 ms
6000×4000299.43 ms3,538.47 ms33.17 ms

Apple M1, macOS. 5–30 iterations per cell. Run: php benchmarks/opal-vs-gd-vs-imagick.php

Lazy Pipelines

Every transform appends a node to an internal VIPS pipeline. No pixels are decoded or processed until a terminal method — toFile(), toBuffer(), toArray(), or toMemory() — triggers evaluation. The pipeline is automatically reordered and fused for optimal performance.

php
// Nothing happens here — just building a pipeline graph
$pipeline = $img
    ->resize(800, 600)
    ->sharpen(sigma: 2.0)
    ->toGrayscale();

// NOW it executes — libvips processes everything in one pass
$pipeline->toFile('output.jpg');

NDArray Integration

Export images directly to phpmlkit/ndarray for ML workflows:

php
// PyTorch format (CHW)
$tensor = $image->toArray(ChannelFormat::CHW);

// TensorFlow format (HWC)
$tensor = $image->toArray(ChannelFormat::HWC);

// Import back from NDArray
$image = Image::fromArray($tensor, ColorSpace::RGB, ChannelFormat::HWC);

Installation

bash
composer require phpmlkit/opal

Requirements: PHP 8.2+, ext-ffi

Next Steps

Released under the MIT License.