Twig Integration
Setup
use Timber\Chainsaw\Twig\ChainsawExtension;
$twig->addExtension(new ChainsawExtension($factory));
The extension accepts either an ImageFactory or a FactoryRegistry. Pass a registry to expose named factories to img() (below); a bare factory is treated as the registry’s single default.
Function
img(source, name?, meta?)
Create an Image from a path string. The optional second argument selects a named factory from the FactoryRegistry — mirroring Symfony’s asset(path, packageName) — and falls back to the default factory when omitted or null:
{% set image = img('photo.jpg') %} {# default factory #}
{% set image = img('photo.jpg', 'cloudflare') %} {# named factory #}
{% set image = img('photo.jpg', meta: meta) %} {# explicit source metadata #}
An unregistered name throws FactoryNotFound. With a single ImageFactory (no named factories), only the default form applies.
Pass metadata with the named argument (meta: meta) rather than positionally — the second positional argument is now the factory name, not the metadata.
Filters
Manipulation filters
All filters accept an Image, a srcset set (WidthSet / DensitySet), or a string (auto-coerced to Image):
{{ 'photo.jpg' | width(400) | render }}
{{ 'photo.jpg' | crop(800, 600) | greyscale | quality(80) | render }}
| Filter | Arguments | Returns |
|---|---|---|
width |
int |
Image |
height |
int |
Image |
scale |
float |
Image |
contain |
int, int, ?bool |
Image |
pad |
int, int, ?string, ?bool |
Image |
stretch |
int, int |
Image |
cover |
int, int, ?anchor, ?bool |
Image |
crop |
int, int, ?anchor, ?bool |
Image (alias of cover) |
manualCrop |
int, int, int, int |
Image |
cropToRatio |
ratio, ?anchor |
Image |
padToRatio |
ratio, ?string |
Image |
trim |
?int, ?string |
Image |
blur |
int |
Image |
sharpen |
int |
Image |
brightness |
int |
Image |
contrast |
int |
Image |
gamma |
float |
Image |
pixelate |
int |
Image |
greyscale |
– | Image |
sepia |
– | Image |
background |
string |
Image |
format |
string |
Image |
quality |
int |
Image |
preset |
string |
Image |
widths |
int, ... |
WidthSet |
densities |
float, ... |
DensitySet |
For the anchor arguments, pass a compass string ('center', 'top', 'bottom-left', …), a detection keyword ('smart', 'entropy', 'attention', 'face'), or 'object:<class>'. For ratio, pass a string like '16:9'.
For format, pass the string value: 'webp', 'avif', 'jpg', 'png', 'gif'.
Manipulations without a dedicated filter (saturation, hue, rotate, flip, …) are available through the manipulate hash filter below.
manipulate
Apply operations from a hash:
{{ 'photo.jpg' | manipulate({ width: 400, blur: 10, quality: 80 }) | render }}
picture
Declarative responsive picture:
{{ 'hero.jpg' | picture(
{ '(min-width: 1024px)': { width: 1200 }, '(min-width: 768px)': { width: 800 } },
['webp']
) | render({ alt: 'Hero', loading: 'lazy' }) }}
render (output filter)
Render any Image, WidthSet / DensitySet, or Picture as HTML. Marked as safe (no escaping):
{# <img> tag #}
{{ image | render }}
{{ image | render({ alt: 'Photo', loading: 'lazy', class: 'hero' }) }}
{# srcset <img> from a WidthSet #}
{{ image | widths(800, 400) | render({ sizes: '100vw' }) }}
{# <picture> element #}
{{ image | picture({}, ['webp']) | render({ alt: 'Photo' }) }}
The filter dispatches to the renderers configured on the ImageFactory (defaults: HtmlImgRenderer, HtmlSourceRenderer, HtmlPictureRenderer). To customize the markup, supply your own renderer to the factory — see Rendering.
Full example
{# Simple responsive image #}
{{ img('hero.jpg') | crop(1200, 600) | widths(1200, 800, 400) | render({
alt: 'Hero banner',
sizes: '(min-width: 1200px) 1200px, 100vw',
loading: 'lazy',
}) }}
{# Thumbnail preset #}
{{ img('avatar.jpg') | preset('thumbnail') | render({ alt: user.name }) }}
{# Greyscale with WebP #}
{{ img('photo.jpg') | crop(600, 400) | greyscale | format('webp') | quality(80) | render }}