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 (typically FlysystemSourceAdapter) 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. Absolute http(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-separated key-value transformations: ?tr=w-300,h-200,c-maintain_ratio. Different from imgix’s individual query params.
  • Hex encoding – bare RRGGBB (no #, no %23 prefix, no rgb: prefix). 8-digit RRGGBBAA for 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’s Cover/Contain/Pad/Stretch/ManualCrop map 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() and Anchor::attention() all collapse onto ImageKit’s single fo-auto AI crop. Anchor::object('class') accepts any COCO label (person, car, truck, etc.).
  • Focal anchorAnchor::focal(x, y) throws UnsupportedManipulator. ImageKit’s fo- parameter accepts named positions only; there is no native focal-point-as-percent. Users wanting cross-CDN focal parity should stick with Anchor::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 ×20 scaling factor (sharp=10e-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-level bg- — the same key the Background manipulator uses. If both are stacked, apply order decides (last-write wins, matching Cloudinary’s pattern).
  • Border – only BorderType::Overlay is supported; Shrink / Expand would 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 uses lap-<anchor> for the edge/corner, with lx/ly shifting the layer relative to that anchor (negative offsets — encoded N<abs> — push inward from right/bottom anchors). Percent sizing works (w-bw_mul_0.25 = 25% of base width); percent padding and asymmetric padding throw UnsupportedManipulator. 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; use WatermarkFromUrl.
  • GIF output – ImageKit’s documented format set is auto|orig|jpg|png|webp|avif. Requesting Format::Gif throws UnsupportedOperation.
  • 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.