ImagineProvider

Processes images locally using imagine/imagine with the GD, Imagick, or Gmagick driver. Writes processed files to a cache filesystem.

use Imagine\Gd\Imagine; // or Imagine\Imagick\Imagine / Imagine\Gmagick\Imagine
use Timber\Chainsaw\Provider\Imagine\ImagineProvider;
use Timber\Chainsaw\Source\FlysystemSourceAdapter;

$provider = new ImagineProvider(
    sourceReader: new FlysystemSourceAdapter($sourceFilesystem),
    cache: $cacheFilesystem,
    cachePublicUrl: '/images/cache',
    imagine: new Imagine(),
);

Imagine reads source bytes straight from a string and encodes back to a string — no temporary files on either side. Its GD driver converts palette images to truecolor on load, so palette sources encode to WebP/AVIF without a workaround.

Shared local-provider machinery

ImagineProvider and InterventionProvider extend the same AbstractLocalProvider base, so everything backend-independent behaves identically:

  • Variant cache + existence checks — three-rung ladder (in-memory, optional PSR-6 existsPool, cache filesystem). See Existence cache — the same guidance (remote cache storage only) applies here.
  • Decompression-bomb guard — optional maxSourcePixels ceiling enforced before decoding. See Source pixel budget.
  • Format::Auto — resolved by an AutoFormatStrategyInterface you inject (autoFormat:); throws without one. See Advanced > Format negotiation.
  • Data URIs — implements InlineProvider for $image->toDataUri().
  • Purging — implements Purgeable; purge($source) deletes every cached variant and evicts matching PSR-6 entries.
  • Events — dispatches PreProcess / PostProcess on cache miss when a PSR-14 dispatcher: is wired.
  • Cache addressing — owned by a PathStrategyInterface (default HashedPathStrategy).

Manipulation support

Manipulation Supported Notes
Width
Height
Scale
Cover Compass + focal anchors; detection anchors (smart/face/…) throw
ManualCrop
Contain
Pad Background painted in the letterbox bars only
Stretch
CropToRatio
PadToRatio
Trim Throws UnsupportedManipulator
Blur
Sharpen
Brightness
Contrast Throws UnsupportedManipulator
Gamma
Pixelate Throws UnsupportedManipulator
Greyscale
Sepia Throws UnsupportedManipulator
Saturation Shared Raster\Hsl codec via the native GD/Imagick resource
Hue Shared Raster\Hsl codec via the native GD/Imagick resource
Negate
Background
Border
Flip
Rotate Arbitrary angles with optional background fill
AutoOrient EXIF-based
Watermark WatermarkFromUrl only; pixel and percent units computed locally
BlurHash Shared Raster\BlurHash codec; single-frame LQIP
ThumbHash Shared Raster\ThumbHash codec; single-frame LQIP
Dither Shared Raster\Dither codec

Unsupported manipulators (Trim, Contrast, Pixelate, Sepia) are intentionally unregistered — Imagine has no native primitive for them — and throw UnsupportedManipulator. If you need them locally, use InterventionProvider, which supports every manipulator in the library.

Anchor support: Anchor::compass() and Anchor::focal() work; detection-based anchors (smart(), entropy(), attention(), face(), object()) throw. Server-default watermarks (WatermarkFromServerDefault) throw — only URL watermark sources are supported.

Encoding

Format Supported
JPEG
PNG
WebP ✅ (capability-probed, lazy)
AVIF ✅ (capability-probed, lazy)
GIF
Auto format ✅ (needs an injected AutoFormatStrategy)
Quality

JPEG/PNG/GIF are universally available and never probed. WebP and AVIF vary by build, so ImagineFormatSupport runs a one-off 1×1 trial encode per format and memoizes the result. An explicit request for a format the driver can’t encode throws UnsupportedOperation. Pass your own formatSupport: to override or skip probing.

Animation

Animated GIF/WebP handling depends on the driver:

  • Imagick driver — geometry-only chains (resize/crop-based manipulators) keep every frame, and encode animated output when the target format is GIF or WebP. Frame delays are preserved; the loop count is forced to infinite by Imagine’s animate(). Handlers built on single-frame APIs (effects, paste, rotate, flip) freeze to frame 0, as does encoding to a static target format (JPEG/PNG/AVIF). Saturation/Hue bypass Imagine’s single-frame APIs and modulate the native handle per frame, so they keep animation too.
  • GD driver — GD has no multi-frame support; animated sources decode to their first frame.

BlurHash/ThumbHash placeholders always flatten to frame 0 before encoding (single-frame LQIP by design).

Notes

  • Why pick Imagine over Intervention? Mostly when imagine/imagine is already in your dependency tree, or you need the Gmagick driver. Feature-wise it’s a strict subset of InterventionProvider (27 of 31 manipulators, no detection anchors, no Vips driver).
  • The quality encoding default is 85 when no Encoding quality is set.
  • Pad paints the background into the letterbox bars only, never over source pixels.