ImagekitProvider
Generates ImageKit transformation URLs. SaaS image CDN in the same family as imgix and Cloudinary, with strong AI/object-aware crop primitives on the free tier.
use Timber\Chainsaw\Provider\Imagekit\ImagekitProvider;
$provider = new ImagekitProvider(
urlEndpoint: 'https://ik.imagekit.io/your-account',
);
Output: {urlEndpoint}/{source}?tr=w-300,h-200,c-maintain_ratio&ik-s={signature}
Source modes
ImagekitProvider auto-detects between two modes based on whether a SourceLocator is supplied:
- Account-origin mode – pass a
SourceLocator(typicallyFlysystemSourceAdapter) to rewrite relative paths to fetchable URLs. ImageKit’s dashboard must be configured with the matching origin (S3, web folder, custom). Mirrors the imgix workflow. - Web proxy mode – no
SourceLocator. Absolutehttp(s)source URLs are appended directly to the endpoint:https://ik.imagekit.io/your-account/https://example.com/photo.jpg. Useful for ad-hoc remote sources; no dashboard origin config needed.
URL signing
Optional signed URLs via UrlSignerInterface. ImageKit uses HMAC-SHA1 (lowercase hex) over path + query + expiryTimestamp. Wire it with HmacUrlSigner configured for hex output:
use Timber\Chainsaw\Provider\Imagekit\ImagekitProvider;
use Timber\Chainsaw\Signer\Algorithm;
use Timber\Chainsaw\Signer\SignatureEncoding;
use Timber\Chainsaw\Signer\HmacUrlSigner;
$provider = new ImagekitProvider(
urlEndpoint: 'https://ik.imagekit.io/your-account',
signer: new HmacUrlSigner(
key: 'your-private-api-key',
algorithm: Algorithm::Sha1,
encoding: SignatureEncoding::Hex,
),
);
Output (default, no TTL): {urlEndpoint}/{source}?tr=…&ik-s={hex-signature}. ImageKit’s official SDK always appends a 9999999999 sentinel timestamp to the signed payload but omits the ik-t query parameter when no expiry is configured — the server replays the sentinel during signature verification. The provider mirrors this so signed URLs stay deterministic and CDN-cacheable.
Opt into a TTL by passing expirySeconds:
$provider = new ImagekitProvider(
urlEndpoint: 'https://ik.imagekit.io/your-account',
signer: $signer,
expirySeconds: 300, // 5-minute TTL
);
The URL gains &ik-t=<unix-timestamp> and the signature covers path + query + timestamp. Signatures drift per second, so cache hit rates drop accordingly.
The timestamp comes from an optional PSR-20 clock (clock: constructor parameter); by default the system time is used. Inject a fixed clock (for example symfony/clock’s MockClock) to make signed-TTL URLs deterministic in tests.
Signing is required only when “Restrict Unsigned URLs” is enabled in the ImageKit dashboard. The default is off, so unsigned URLs work out of the box.
Manipulation support
Legend: ✅ = implemented in Chainsaw, ⚠️ = supported with caveats, ❌ = not available on this CDN.
Resize & crop
| Manipulation | Chainsaw | Availability |
|---|---|---|
| Width | ✅ | Free tier |
| Height | ✅ | Free tier |
| Scale | ❌ | No scale-by-factor primitive; use width()/height() |
| Cover | ⚠️ | All anchors except Focal (named positions only on fo-) |
| ManualCrop | ✅ | Free tier (cm-extract) |
| Contain | ✅ | Maps c-at_max_enlarge (upscale) / c-at_max (no-upscale) |
| Pad | ✅ | Maps cm-pad_resize / cm-pad_resize_no_enlarge |
| Stretch | ✅ | Maps c-force |
| CropToRatio | ✅ | Maps ar-w-h,c-maintain_ratio |
| PadToRatio | ✅ | Maps ar-w-h,cm-pad_resize |
| Trim | ✅ | t-true (auto) or t-<1..99> (threshold) |
| Smart crop | ✅ | Anchor::smart() / Anchor::entropy() / Anchor::attention() all map to fo-auto |
| Face crop | ✅ | Anchor::face() → fo-face |
| Object-aware crop | ✅ | Anchor::object('car') → fo-car; full COCO label set |
Filters & effects
| Manipulation | Chainsaw | Availability |
|---|---|---|
| Blur | ✅ | bl- = round(radius × 0.55) → emits 1…55 (σ anchor; ImageKit accepts 1…100); blur(0) is a no-op |
| Sharpen | ✅ | e-sharpen (auto) or e-sharpen-<0..100>; see notes |
| Greyscale | ✅ | e-grayscale |
| Brightness | ❌ | Not documented in ImageKit’s URL API |
| Contrast | ❌ | e-contrast is a boolean auto-enhance only, no level control |
| Gamma | ❌ | Not documented in ImageKit’s URL API |
| Saturation | ❌ | Not documented in ImageKit’s URL API |
| Hue | ❌ | Not documented in ImageKit’s URL API |
| Sepia | ❌ | Not documented (could approximate via e-colorize, deferred) |
| Pixelate | ❌ | Not documented |
| Negate / Invert | ❌ | Not documented |
Decoration & orientation
| Manipulation | Chainsaw | Availability |
|---|---|---|
| Background | ✅ | Bare hex bg-RRGGBB[AA] (alpha as trailing 2 hex digits) |
| Border | ✅ | All BorderType variants; b-<width>_<color> |
| Flip | ✅ | fl-h / fl-v |
| Rotate | ✅ | Arbitrary degrees, including negatives (rt-N45 = -45°) |
| AutoOrient | ✅ | rt-auto |
| Watermark | ✅ | WatermarkFromSource only; px and percent units |
Special
| Manipulation | Chainsaw | Availability |
|---|---|---|
| BlurHash | ❌ | Local-pixel manipulator; ImageKit emits images, not hash strings |
| ThumbHash | ❌ | Same as BlurHash |
| Dither | ❌ | Not documented |
Encoding
| Format | Supported |
|---|---|
| JPEG | ✅ |
| PNG | ✅ |
| WebP | ✅ |
| AVIF | ✅ |
| GIF | ❌ |
| Auto format | ✅ |
| Quality | ✅ |
Notes
- URL grammar – ImageKit uses a single
tr=query parameter with comma-separatedkey-valuetransformations:?tr=w-300,h-200,c-maintain_ratio. Different from imgix’s individual query params. - Hex encoding – bare
RRGGBB(no#, no%23prefix, norgb:prefix). 8-digitRRGGBBAAfor alpha. Different scheme from every other Chainsaw provider. - Crop modes – ImageKit splits “fit” across two axes:
c-(mode:maintain_ratio,at_max,force,at_max_enlarge) ×cm-(strategy:extract,pad_resize,pad_resize_no_enlarge). Chainsaw’sCover/Contain/Pad/Stretch/ManualCropmap to specific combinations per the imgix migration guide. - Anchor mapping – compass tokens use underscore separator:
top_left,bottom_right(not commas as on imgix).Anchor::smart(),Anchor::entropy()andAnchor::attention()all collapse onto ImageKit’s singlefo-autoAI crop.Anchor::object('class')accepts any COCO label (person,car,truck, etc.). - Focal anchor –
Anchor::focal(x, y)throwsUnsupportedManipulator. ImageKit’sfo-parameter accepts named positions only; there is no native focal-point-as-percent. Users wanting cross-CDN focal parity should stick withAnchor::compass()or switch to AI-driven anchoring (face/smart). - Sharpen – the main docs document
e-sharpen-<0..100>; ImageKit’s imgix migration guide hints at a×20scaling factor (sharp=10→e-sharpen-200). Empirical calibration is deferred; expect output to differ from the documented range until verified. - Rotate background – arbitrary-angle rotations leave triangular voids. ImageKit has no dedicated rotation-background parameter, so
Rotate(degrees, background)emits the colour as the page-levelbg-— the same key theBackgroundmanipulator uses. If both are stacked, apply order decides (last-write wins, matching Cloudinary’s pattern). - Border – all three
BorderTypevariants render at the requested output size.Expandemits ImageKit’s nativeb-(the canvas grows by2×widthper axis).Shrinkpre-shrinks the constrained dims so the expandingb-lands back on the requested box (content shrinks to make room).Overlaykeeps the subject at full crop scale by chaining a centrecm-extractthat trims inward by2×widthbeforeb-grows it back, so the border paints over the outer band rather than resizing the content.Overlayneeds both dimensions from an upstream box resize (crop/cover/pad/stretch, orwidth()+height()) and throwsUnsupportedManipulatorotherwise.Unit::Percentthrows. - Watermark – The
WatermarkFromSourceref (URL or storage path) is base64url-encoded viaie-to safely pass through ImageKit’s comma/colon-separated grammar. The layer block is its own:-chained step. Positioning useslap-<anchor>for the edge/corner, withlx/lyshifting the layer relative to that anchor (negative offsets — encodedN<abs>— push inward from right/bottom anchors). Percent sizing works (w-bw_mul_0.25= 25% of base width); percent padding and asymmetric padding throwUnsupportedManipulator. On centered axes (Position::Top/Bottom/Left/Right/Center) the offset along the centered axis is dropped — padding has no direction there. Server-default registries are not supported; useWatermarkFromSource. - Watermark fit – with a width/height box the overlay crop token carries the fit:
Contain→c-at_max(fits inside the box keeping aspect),Stretch→c-force(distorts to the box). ImageKit’s cover (c-at_least) overflows the box rather than cropping to it, soFillandCropthrowUnsupportedManipulator. A single axis scales proportionally and emits no crop token. - GIF output – ImageKit’s documented format set is
auto|orig|jpg|png|webp|avif. RequestingFormat::GifthrowsUnsupportedOperation. - Free tier – ImageKit’s free tier covers all geometry, encoding, signing, and AI-driven crop (face, smart, object-class). Some advanced AI primitives (background removal, gen-fill, etc.) consume metered “extension units”; those are not currently exposed by Chainsaw.