PHPackages                             phpmlkit/opal - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Image &amp; Media](/categories/media)
4. /
5. phpmlkit/opal

ActivePlatform-package[Image &amp; Media](/categories/media)

phpmlkit/opal
=============

High-performance image processing for PHP, backed by libvips via FFI.

1.1.1(1mo ago)117MITPHPPHP ^8.2CI passing

Since May 23Pushed 2mo agoCompare

[ Source](https://github.com/phpmlkit/opal)[ Packagist](https://packagist.org/packages/phpmlkit/opal)[ RSS](/packages/phpmlkit-opal/feed)WikiDiscussions main Synced 3w ago

READMEChangelog (3)Dependencies (14)Versions (4)Used By (0)

 [![Opal Logo](docs/public/logo.png)](docs/public/logo.png)

Opal
====

[](#opal)

High-performance image processing for PHP, backed by libvips

 [![Latest Version](https://camo.githubusercontent.com/099d90f6eaa74ade2b59b25c210ec00e9ee810f8c63d530bf351210a4a86f4a1/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7068706d6c6b69742f6f70616c3f7374796c653d666c61742d737175617265)](https://packagist.org/packages/phpmlkit/opal) [![GitHub Workflow Status](https://camo.githubusercontent.com/a325cb37634f0e013a72704305df256427b71cdde46a183d24f4d39f581aa227/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f7068706d6c6b69742f6f70616c2f74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/phpmlkit/opal/actions) [![Total Downloads](https://camo.githubusercontent.com/b028dfeaef1bbc46c93c73392f939e59fe9c66d2acfcc59c6b3ed0807175960f/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f7068706d6c6b69742f6f70616c3f7374796c653d666c61742d737175617265)](https://packagist.org/packages/phpmlkit/opal) [![License](https://camo.githubusercontent.com/8bb50fd2278f18fc326bf71f6e88ca8f884f72f179d3e555e20ed30157190d0d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d677265656e2e737667)](LICENSE)

Features
--------

[](#features)

- **Lazy Evaluation**: All image operations are lazy and only executed when needed (saving, encoding, exporting)
- **Immutable Operations**: Every transformation returns a new image instance
- **NDArray Integration**: Seamless interoperability with `phpmlkit/ndarray` for ML workflows
- **Comprehensive API**: Support for all common image operations
- **Type-Safe**: Full PHP 8.2+ type safety with enums and value objects
- **Memory Efficient**: Zero-copy operations where possible

Performance
-----------

[](#performance)

**Load → resize → rotate 45° → sharpen** (full pipeline):

ImageGDImagickOpal640×4808.48 ms128.55 ms**1.56 ms**1920×108049.67 ms721.97 ms**5.36 ms**4000×2670152.74 ms2,039.15 ms**15.47 ms**6000×4000299.43 ms3,538.47 ms**33.17 ms***Apple M1, macOS. Run: `php benchmarks/opal-vs-gd-vs-imagick.php`*

Installation
------------

[](#installation)

```
composer require phpmlkit/opal
```

Quick Start
-----------

[](#quick-start)

```
use PhpMlKit\Opal\Image;
use PhpMlKit\Opal\Color;
use PhpMlKit\Opal\ColorSpace;
use PhpMlKit\Opal\Kernel;

// Load an image
$image = Image::fromFile('path/to/image.jpg');

// Resize with high-quality kernel
$resized = $image->resize(800, 600, Kernel::Lanczos3);

// Convert to grayscale
$grayscale = $resized->toGrayscale();

// Save the result
$grayscale->toFile('output.jpg');
```

Core Concepts
-------------

[](#core-concepts)

### Lazy Evaluation

[](#lazy-evaluation)

All image operations are lazy - they build a pipeline that's only executed when you call a terminal operation:

```
// This doesn't process anything yet
$pipeline = $image
    ->resize(800, 600)
    ->toGrayscale()
    ->brightness(1.2);

// This triggers the actual processing
$pipeline->toFile('output.jpg');
```

### Immutable Operations

[](#immutable-operations)

Every transformation returns a new image instance:

```
$original = Image::fromFile('input.jpg');
$modified = $original->resize(800, 600);

// $original is unchanged
$original->toFile('original.jpg');
$modified->toFile('resized.jpg');
```

Usage Examples
--------------

[](#usage-examples)

### Basic Image Operations

[](#basic-image-operations)

```
use PhpMlKit\Opal\Image;
use PhpMlKit\Opal\Color;
use PhpMlKit\Opal\ColorSpace;
use PhpMlKit\Opal\Kernel;
use PhpMlKit\Opal\FlipDirection;

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

// Resize
$resized = $image->resize(1920, 1080);
$scaled = $image->scale(0.5);

// Thumbnail via shrink-on-load — faster than load+resize
$thumbnail = Image::thumbnail('photo.jpg', 300);

// Crop
$cropped = $image->crop(100, 100, 800, 600);
$centerCropped = $image->centerCrop(800, 600);

// Flip and rotate
$flipped = $image->flip(FlipDirection::Horizontal);
$rotated = $image->rotate(45);
$rotated90 = $image->rot90();

// Save
$resized->toFile('resized.jpg');
```

### Color Space Conversion

[](#color-space-conversion)

```
use PhpMlKit\Opal\Image;
use PhpMlKit\Opal\ColorSpace;

$image = Image::fromFile('photo.jpg');

// Convert to grayscale
$grayscale = $image->toGrayscale();

// Convert to RGB
$rgb = $grayscale->toRGB();

// Add alpha channel
$rgba = $image->toRGBA();

// Remove alpha
$rgb = $rgba->removeAlpha();
```

### Color Adjustments

[](#color-adjustments)

```
use PhpMlKit\Opal\Image;

$image = Image::fromFile('photo.jpg');

// Brightness (1.0 = unchanged, >1 = brighter, brightness(1.2);

// Contrast (1.0 = unchanged, >1 = more contrast, contrast(1.5);

// Saturation (0 = grayscale, 1.0 = unchanged, >1 = more saturated)
$vivid = $image->saturation(1.3);

// Hue rotation
$hueShifted = $image->hue(90);

// Gamma correction
$gammaCorrected = $image->gamma(2.2);
```

### Filters and Effects

[](#filters-and-effects)

```
use PhpMlKit\Opal\Image;

$image = Image::fromFile('photo.jpg');

// Sharpen
$sharpened = $image->sharpen(sigma: 2.0);

// Blur
$blurred = $image->blur(sigma: 3.0);

// Median blur (good for noise reduction)
$denoised = $image->medianBlur(5);

// Invert colors
$inverted = $image->invert();
```

### Drawing and Compositing

[](#drawing-and-compositing)

```
use PhpMlKit\Opal\Image;
use PhpMlKit\Opal\Color;
use PhpMlKit\Opal\BoundingBox;

$image = Image::fromFile('photo.jpg');

// Draw rectangle
$withRect = $image->drawRect(
    100, 100, 200, 150,
    Color::red()
);

// Draw circle
$withCircle = $image->drawCircle(
    400, 300, 50,
    Color::blue(),
    fill: true
);

// Draw text
$withText = $image->drawText(
    'Hello World',
    100, 100,
    color: Color::white()
);

// Composite images
$overlay = Image::fromFile('overlay.png');
$composited = $image->composite($overlay, 50, 50);
```

### NDArray Interoperability

[](#ndarray-interoperability)

```
use PhpMlKit\Opal\Image;
use PhpMlKit\NDArray\NDArray;
use PhpMlKit\Opal\ColorSpace;
use PhpMlKit\Opal\ChannelFormat;

// Convert image to NDArray
$image = Image::fromFile('photo.jpg');
$array = $image->toArray(ChannelFormat::HWC);  // [H, W, C]

// Convert NDArray to image
$array = NDArray::zeros([224, 224, 3]);
$image = Image::fromArray($array, ColorSpace::RGB, ChannelFormat::HWC);
```

### Advanced Options

[](#advanced-options)

```
use PhpMlKit\Opal\Image;
use PhpMlKit\Opal\LoadOptions;
use PhpMlKit\Opal\SaveOptions;

// Load with options
$image = Image::fromFile('photo.jpg', LoadOptions::default()
    ->withAutoRotate(true)
    ->withShrink(2)
);

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

// PNG with compression
$image->toFile('output.png', SaveOptions::png(
    compression: 9,
    interlace: true
));

// WebP with lossless
$image->toFile('output.webp', SaveOptions::webp(
    quality: 80,
    lossless: false
));
```

API Reference
-------------

[](#api-reference)

### Value Objects

[](#value-objects)

#### `Color`

[](#color)

Immutable RGBA color representation.

```
$red = Color::rgb(255, 0, 0);
$blue = Color::fromHex('#0000ff');
$white = Color::white();
$transparent = Color::transparent();
```

#### `ImageSize`

[](#imagesize)

Immutable 2D size descriptor.

```
$size = new ImageSize(1920, 1080);
$aspectRatio = $size->aspectRatio();
$pixels = $size->pixels();
```

#### `BoundingBox`

[](#boundingbox)

Immutable axis-aligned bounding box.

```
$box = new BoundingBox(10, 10, 100, 50);
$iou = $box->iou($otherBox);
$clamped = $box->clamp($imageWidth, $imageHeight);
```

### Enums

[](#enums)

- `ColorSpace`: RGB, RGBA, BGR, BGRA, Grayscale, Lab, HSV, CMYK
- `ImageFormat`: JPEG, PNG, WebP, TIFF, GIF, BMP, AVIF, HEIF
- `Kernel`: Nearest, Linear, Cubic, Mitchell, Lanczos2, Lanczos3, Mks211, Mks213
- `FlipDirection`: Horizontal, Vertical, Both
- `BandFormat`: UChar, UInt16, Float, Double
- `ChannelFormat`: HWC, CHW

### Options Classes

[](#options-classes)

#### `LoadOptions`

[](#loadoptions)

Control image loading behavior.

```
$options = LoadOptions::default()
    ->withPage(0)
    ->withAutoRotate(true)
    ->withShrink(2);
```

#### `SaveOptions`

[](#saveoptions)

Control image saving behavior.

```
$options = SaveOptions::jpeg(quality: 90, strip: true);
$options = SaveOptions::png(compression: 9);
$options = SaveOptions::webp(quality: 80, lossless: false);
```

Performance Tips
----------------

[](#performance-tips)

1. **Use lazy evaluation**: Chain operations together before saving
2. **Use shrink-on-load**: Load with `Image::thumbnail()` or `LoadOptions::withShrink()` for large images
3. **Choose appropriate interpolation**: Use `Lanczos` for quality, `Bilinear` for speed
4. **Dispose explicitly**: Call `dispose()` when done with large images

Documentation
-------------

[](#documentation)

- [Full Documentation](https://phpmlkit.github.io/opal/)
- [What is Opal?](https://phpmlkit.github.io/opal/guide/getting-started/what-is-opal)
- [Quick Start](https://phpmlkit.github.io/opal/guide/getting-started/quick-start)
- [API Reference](https://phpmlkit.github.io/opal/api/)
- [Installation](https://phpmlkit.github.io/opal/guide/getting-started/installation)

Development
-----------

[](#development)

```
# Install dependencies
composer install

# Run tests
composer test

# Run static analysis
composer lint

# Format code
composer cs:fix
```

Requirements
------------

[](#requirements)

- PHP 8.2 or higher
- ext-ffi extension

License
-------

[](#license)

MIT

Credits
-------

[](#credits)

- [libvips](https://www.libvips.org) — image processing engine
- [jcupitt/vips](https://github.com/jcupitt/php-vips) — PHP FFI bindings for libvips
- [phpmlkit/ndarray](https://github.com/phpmlkit/ndarray) — numerical computing for ML workflows

###  Health Score

41

—

FairBetter than 87% of packages

Maintenance90

Actively maintained with recent releases

Popularity10

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~14 days

Total

3

Last Release

34d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/146c2eb02350558d165083e0018f5377f15f0e71493439c93ee60e7c7ac97fc1?d=identicon)[CodeWithKyrian](/maintainers/CodeWithKyrian)

---

Top Contributors

[![CodeWithKyrian](https://avatars.githubusercontent.com/u/48791154?v=4)](https://github.com/CodeWithKyrian "CodeWithKyrian (23 commits)")

---

Tags

imagegdimagickimage processingmachine learningmllibvipsvipsffindarray

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/phpmlkit-opal/health.svg)

```
[![Health](https://phpackages.com/badges/phpmlkit-opal/health.svg)](https://phpackages.com/packages/phpmlkit-opal)
```

###  Alternatives

[intervention/image

PHP Image Processing

14.4k208.9M2.6k](/packages/intervention-image)[league/glide

Wonderfully easy on-demand image manipulation library with an HTTP based API.

2.6k53.3M149](/packages/league-glide)[intervention/image-driver-vips

libvips driver for Intervention Image

48177.4k14](/packages/intervention-image-driver-vips)[intervention/image-laravel

Laravel Integration of Intervention Image

1588.9M201](/packages/intervention-image-laravel)[folklore/image

Image manipulation library for Laravel 5 based on Imagine and inspired by Croppa for easy url based manipulation

269248.8k5](/packages/folklore-image)[rokka/imagine-vips

libvips adapter for imagine

43638.4k7](/packages/rokka-imagine-vips)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
