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\Encoding;
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: Encoding::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.
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-<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 | ⚠️ | BorderType::Overlay only; b-<width>_<color> |
| Flip | ✅ | fl-h / fl-v |
| Rotate | ✅ | Arbitrary degrees, including negatives (rt-N45 = -45°) |
| AutoOrient | ✅ | rt-auto |
| Watermark | ✅ | WatermarkFromUrl 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 – only
BorderType::Overlayis supported;Shrink/Expandwould need canvas-expansion arithmetic that has no clean ImageKit equivalent. Percent units throw. - Watermark – URL is base64url-encoded via
ie-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; useWatermarkFromUrl. - 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.