php-collective / file-storage-image-processor
File Storage Image Processor
Package info
github.com/php-collective/file-storage-image-processor
pkg:composer/php-collective/file-storage-image-processor
Requires
- php: >=8.3
- ext-json: *
- intervention/image: ^4.0
- spatie/image-optimizer: ^1.8.0
Requires (Dev)
- php-collective/code-sniffer: ^0.6.0
- php-collective/file-storage: ^1.0.0
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^12.3 || ^13.0
- dev-master
- 2.0.0
- v1.x-dev
- 1.0.1
- 1.0.0
- 0.1.0
- dev-fix/v1-release-health
- dev-feature/exceptions-and-format-enum
- dev-feature/ci-prefer-lowest
- dev-feature/animation-docs
- dev-feature/2.0-readiness
- dev-feature/animated-images
- dev-feature/operation-classes
- dev-feature/cleanup-followups
- dev-feature/driver-factory
- dev-feature/preserve-icc-profile
- dev-intervention-image-v4
This package is auto-updated.
Last update: 2026-04-29 12:20:22 UTC
README
Image Processing for the File Storage Library.
Built on top of Intervention Image v4.
Features
- Generates and stores variants of an uploaded image (thumbnails, avatars, hero crops, …)
- 24+ first-class image operations: resize, scale, cover, crop, rotate, flip, sharpen, orient (EXIF auto-rotate), brightness, contrast, grayscale, colorize, blur, pixelate, trim, resizeCanvas, padding, place (watermark), convert (format swap), …
- Per-format encoder quality, EXIF/metadata strip toggle, ICC color-profile preservation
- Pluggable operation registry — add custom operations without forking
- Optional file-size optimization via spatie/image-optimizer
- Works with League Flysystem for flexible storage backends
- Fluent API for chaining operations, including repeating the same operation type multiple times
Requirements
- GD or Imagick extension
- Intervention Image v4
Installation
composer require php-collective/file-storage-image-processor
Quick Example
use PhpCollective\Infrastructure\Storage\Processor\Image\Driver; use PhpCollective\Infrastructure\Storage\Processor\Image\Format; use PhpCollective\Infrastructure\Storage\Processor\Image\ImageProcessor; use PhpCollective\Infrastructure\Storage\Processor\Image\ImageVariantCollection; use PhpCollective\Infrastructure\Storage\Processor\Image\Position; // Driver::Auto picks Imagick when the extension is loaded and falls // back to GD; use Driver::Gd or Driver::Imagick to choose explicitly. $imageProcessor = ImageProcessor::create(Driver::Auto, $fileStorage, $pathBuilder); $collection = ImageVariantCollection::create(); // Create a thumbnail with aspect ratio preserved $collection->addNew('thumbnail') ->scale(300, 300) ->optimize(); // Create an avatar that fills exact dimensions $collection->addNew('avatar') ->cover(150, 150, Position::TopCenter) ->optimize(); // Re-encode a JPEG source as WebP — Format enum or string both work $collection->addNew('webp') ->scale(800, 600) ->convert(Format::Webp); // Repeat the same operation type without losing earlier steps $collection->addNew('effects') ->blur(1) ->blur(6); $file = $file->withVariants($collection->toArray()); $file = $imageProcessor->process($file);
Tuning the encoder
$imageProcessor ->setQuality(['webp' => 80, 'jpg' => 90, 'avif' => 70]) // per-format ->setStripExif(true) // privacy + smaller files (default) ->setPreserveProfile(true) // keep wide-gamut color rendering (default) ->setPreserveAnimation(true); // animated GIF/WebP keep all frames (default)
setPreserveAnimation(false) flattens animated sources to a single frame — useful for static thumbnail variants or when converting to a non-animated format like JPEG.
Processing a subset of variants
// Per-call filter — does not leak into subsequent process() calls. $file = $imageProcessor->process($file, ['thumbnail']);
Custom operations
use PhpCollective\Infrastructure\Storage\Processor\Image\Operation\Operation; use PhpCollective\Infrastructure\Storage\Processor\Image\Operation\OperationRegistry; $registry = OperationRegistry::default() ->register('myFilter', static fn (array $args): Operation => new MyFilter(...$args)); $processor = new ImageProcessor($storage, $pathBuilder, $imageManager, urlBuilder: null, operationRegistry: $registry);
Repeated operations of the same name are preserved in order when you serialize variants with toArray() and rebuild them later with ImageVariantCollection::fromArray().
Documentation
Please start by reading the documentation in the docs/ directory:
- Installation & Setup
- Processing Images
- Available Operations — complete reference of all image operations
Upgrading from 1.x to 2.x
This major release migrates to Intervention Image v4 and replaces the stringly-typed dispatcher with a typed Operation class hierarchy. See the CHANGELOG for the full list; the headline changes:
- PHP 8.3+ required (was 8.1)
- Intervention Image v4 required (was v3)
processOnlyTheseVariants()/processAll()removed — use the newprocess($file, ['thumbnail'])per-call filter insteadOperations::POSITION_*string constants replaced by thePositionenum (Position::Center,Position::TopCenter, …)ImageVariant::FLIP_HORIZONTAL/FLIP_VERTICALconstants replaced by theFlipDirectionenumOperationsclass is gone — operations are now individual classes undersrc/Operation/resolved viaOperationRegistryflip()now acceptsFlipDirection|string(string form still works for config-driven setups)cover()no longer takes a (always-ignored)$callbackparameter