Providers

All providers implement Timber\Chainsaw\Provider\ProviderInterface:

interface Provider {
    public function url(Image $image): string;
}

Call (string) $image or echo $image to trigger the provider and get the URL.

Overview

Provider Type
Intervention Local (GD / Imagick / libvips)
Imagine Local (GD / Imagick / Gmagick)
Cloudflare CDN (Freemium SaaS)
Cloudinary CDN (Freemium SaaS)
ImageKit CDN (Freemium SaaS)
imgix CDN (Paid SaaS)
imgproxy CDN (Self-hosted OSS)
Thumbor CDN (Self-hosted OSS)
Imagor CDN (Self-hosted OSS)
wsrv.nl CDN (Free public service)

Per-manipulator support breadth varies — the full support matrix is the authoritative comparison.

Feature comparison

Feature Intervention Imagine Cloudflare Cloudinary ImageKit imgix imgproxy Imagor Thumbor wsrv
Local processing
Format negotiation
Data URIs
URL signing
BlurHash
ThumbHash
Watermark

Not all manipulators are supported by every provider. Unsupported manipulators throw UnsupportedManipulator. See the full support matrix.

Multiple providers

A factory wraps exactly one provider. To mix backends — for example Cloudflare for most images (no server load) and Intervention for the few needing manipulations Cloudflare can’t do — wrap several ImageFactory instances in a FactoryRegistry and pick one explicitly by name. The registry never auto-routes; the call site stays in control.

It mirrors Symfony’s Asset Packages: one nameless default plus any number of named factories.

use Timber\Chainsaw\FactoryRegistry;
use Timber\Chainsaw\ImageFactory;

$registry = new FactoryRegistry(
    default: new ImageFactory($interventionProvider),
    factories: [
        'cloudflare' => new ImageFactory($cloudflareProvider),
        'cloudinary' => new ImageFactory($cloudinaryProvider),
    ],
);

$registry->image('photo.jpg');               // default factory
$registry->image('photo.jpg', 'cloudflare'); // named factory
$registry->factory('cloudflare');            // the underlying ImageFactory

Encoding, presets, and defaults stay per-factory — one provider’s settings rarely fit another (Cloudflare can’t emit gif/png the same way, Cloudinary has f_auto). Each factory keeps its own, and caches don’t collide: every provider owns its own cache surface (local providers their Flysystem variant cache; URL-grammar providers delegate to the CDN).

Method Returns
image(source, name?, meta?) Image from the named factory — the default when name is null
factory(name?) the ImageFactory (default when name is null); throws FactoryNotFound for an unknown name
has(name) whether a named factory is registered
names() the registered names (the default is nameless and excluded)
purger(name?) a purger — see Cache Purging → Multiple providers

In Twig the same name flows through img(source, name) — see Twig Integration.