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 }}