Provider Support Matrix
Chainsaw ships with ten providers. Each provider supports a different subset of the available manipulators. Unsupported manipulators throw UnsupportedManipulator at URL-generation time.
Providers at a glance
| Provider | Type | Pricing | URL style | Signing |
|---|---|---|---|---|
| Intervention | Local processing | OSS (free) | n/a (filesystem) | n/a |
| Imagine | Local processing | OSS (free) | n/a (filesystem) | n/a |
| Cloudflare | URL grammar | Freemium SaaS | /cdn-cgi/image/w=…,h=…/source |
Cloudflare-managed |
| Cloudinary | URL grammar | Freemium SaaS | /image/upload/w_…,h_…/source |
HMAC (s--…--) |
| ImageKit | URL grammar | Freemium SaaS | /source?tr=w-…,h-…,c-maintain_ratio |
HMAC-SHA1 (&ik-s=…) |
| imgix | URL grammar | Paid SaaS | /source?w=…&h=…&fit=crop |
MD5 (&s=…) |
| imgproxy | URL grammar | OSS (self-hosted) | /rs:…/w:…/h:…/plain/source |
HMAC (path signature) |
| Thumbor | URL grammar | OSS (self-hosted) | /hmac/WxH/filters:…/source |
HMAC (path prefix) |
| Imagor | URL grammar | OSS (self-hosted) | /fit-in/WxH/filters:…/source |
HMAC (path prefix) |
| wsrv.nl | URL grammar | Free (public) | ?url=…&w=…&h=…&output=webp |
n/a (public service) |
Portability baseline
If your presets stick to the manipulators below, switching providers is a configuration change — no provider will throw UnsupportedManipulator:
- Resize:
Width,Height,Cover(and itscrop()alias),ManualCrop,Contain,Pad,Stretch - Encoding: JPEG, PNG, WebP, AVIF,
Quality - Filters:
Blur,Sharpen,Greyscale - Decoration:
Background,Flip,Rotate(quarter-turns),AutoOrient
“Portable” here means the manipulator is accepted by every provider — not that output is pixel-identical. Numeric ranges and algorithms differ between backends (e.g. Blur radius, Quality scales, AVIF encoder settings), so expect visual differences when switching providers even within the baseline. Run visual regression if that matters to you.
Precision notes
Sharpen(0..100)— backend granularity varies widely. Cloudflare quantizes to 11 steps (0..10), imgproxy Pro to ~10 sigma steps, Thumbor to 11 amount steps. Expect visible banding at small mid-range deltas on these backends. imgix, Cloudinary, Imagor and wsrv.nl preserve the full 0…100 precision.Gamma(0.1..9.99)— Chainsaw uses a multiplier (1.0 = unchanged). Cloudinary and imgix natively take a percentage, so the providers translate viapct = round((gamma - 1) * 100)and clamp to each backend’s percentage window (Cloudinary-50..150, imgix-100..100). Large multipliers saturate rather than extrapolate.
Manipulation support
Legend: ✅ = supported, ❌ = not supported.
Resize & crop
| Manipulator | Cloudflare | Cloudinary | Imagekit | Imagine | Imagor | Imgix | Imgproxy | Intervention | Thumbor | Wserv |
|---|---|---|---|---|---|---|---|---|---|---|
| Width | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Height | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Scale | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
| Cover | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| ManualCrop | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Contain | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Pad | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Stretch | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| CropToRatio | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ |
| PadToRatio | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ |
| Trim | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Filters & effects
| Manipulator | Cloudflare | Cloudinary | Imagekit | Imagine | Imagor | Imgix | Imgproxy | Intervention | Thumbor | Wserv |
|---|---|---|---|---|---|---|---|---|---|---|
| Blur | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Sharpen | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Brightness | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Contrast | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Gamma | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ |
| Greyscale | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Sepia | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ |
| Pixelate | ❌ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| Saturation | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Hue | ❌ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ |
| Negate | ❌ | ✅ | ❌ | ✅ | ❌ | ✅ | ❌ | ✅ | ❌ | ✅ |
Decoration & orientation
| Manipulator | Cloudflare | Cloudinary | Imagekit | Imagine | Imagor | Imgix | Imgproxy | Intervention | Thumbor | Wserv |
|---|---|---|---|---|---|---|---|---|---|---|
| Background | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Border | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ |
| Flip | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Rotate | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| AutoOrient | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Watermark sub-matrix
Source types:
| Source | Intervention | Imagine | Cloudflare | Cloudinary | ImageKit | imgix | imgproxy (free) | imgproxy (Pro) | Thumbor | Imagor | wsrv |
|---|---|---|---|---|---|---|---|---|---|---|---|
WatermarkFromUrl |
✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ |
WatermarkFromServerDefault |
❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ✅¹ | ✅ | ❌ | ❌ | ❌ |
Size units ($sizeUnit):
| Unit | Intervention | Imagine | Cloudflare | Cloudinary | ImageKit | imgix | imgproxy (free) | imgproxy (Pro) | Thumbor | Imagor | wsrv |
|---|---|---|---|---|---|---|---|---|---|---|---|
Unit::Pixel |
✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅² | ✅² | ❌ |
Unit::Percent |
✅ | ✅ | ❌ | ✅ | ✅¹⁰ | ✅⁸ | ✅ | ✅ | ✅ | ✅ | ❌ |
Padding units ($paddingUnit):
| Unit | Intervention | Imagine | Cloudflare | Cloudinary | ImageKit | imgix | imgproxy (free) | imgproxy (Pro) | Thumbor | Imagor | wsrv |
|---|---|---|---|---|---|---|---|---|---|---|---|
Unit::Pixel |
✅ | ✅ | ❌ | ✅ | ✅ | ✅⁹ | ❌ | ✅ | ✅ | ✅ | ❌ |
Unit::Percent |
✅³ | ✅³ | ❌ | ✅⁴ | ✅¹⁰ | ❌⁵ | ✅⁶ | ✅⁶ | ✅⁷ | ✅⁷ | ❌ |
¹ Only key === 'default' (matches the server’s IMGPROXY_WATERMARK_URL). Custom keys require Pro.
² Converts pixels → ratio using the output image width (set via upstream Width/Crop). Without upstream output dims, throws UnsupportedManipulator.
³ Computed locally from base image dims.
⁴ Native via decimal x_0.1 / y_0.05 per Cloudinary docs.
⁵ Imgix mark-x/mark-y/mark-pad are integer-only per docs; throws UnsupportedManipulator.
⁶ Native via relative offset (imgproxy treats |v| < 1 as percent of image dims).
⁷ Native via Xp notation (Thumbor / Imagor docs: “20p” = 20% of image width).
⁸ Converts percent → pixels using the output image dims (set via upstream Width/Crop/Contain). Imgix’s native mark-w=0..1 is a fraction of the watermark source, not the output image — without upstream output dims, throws UnsupportedManipulator.
⁹ Symmetric only (paddingX === paddingY); emits mark-pad. Imgix mark-x / mark-y are absolute pixel offsets that override mark-align, so asymmetric padding from the alignment edge has no clean imgix equivalent — throws UnsupportedManipulator.
¹⁰ Native via ImageKit arithmetic expressions (bw_mul_0.25 = 25% of base width) per ImageKit’s imgix migration guide.
Special
| Manipulator | Cloudflare | Cloudinary | Imagekit | Imagine | Imagor | Imgix | Imgproxy | Intervention | Thumbor | Wserv |
|---|---|---|---|---|---|---|---|---|---|---|
| BlurHash | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
| ThumbHash | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
| Dither | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
Encoding
Every provider supports format conversion and quality control through the Encoding value object.
| Capability | Intervention | Imagine | Cloudflare | Cloudinary | ImageKit | imgix | imgproxy | Thumbor | Imagor | wsrv |
|---|---|---|---|---|---|---|---|---|---|---|
| JPEG | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| PNG | ✅ | ✅ | ❌¹ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| WebP | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| AVIF | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| GIF | ✅ | ✅ | ❌¹ | ✅ | ❌² | ✅ | ✅ | ✅ | ✅ | ✅ |
| Auto format | ✅³ | ✅³ | ✅ | ✅ | ✅ | ✅ | ❌⁴ | ❌⁴ | ❌⁴ | ❌⁴ |
| Quality | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
¹ Cloudflare’s URL API has no format=png|gif value — an explicit PNG/GIF request is silently ignored and the source format passes through.
² ImageKit does not output GIF — an explicit request throws UnsupportedOperation.
³ Origin-side, resolved by an AutoFormatStrategyInterface you inject — see Advanced > Format negotiation. The CDN columns negotiate edge-side (format=auto / f_auto / f-auto / auto=format).
⁴ Format::Auto is silently ignored — set an explicit format or compose a <picture> with typed sources.