These options set the size and shape of the image, its pixel density, and the canvas, padding, and background around it. Values use the shared option value syntax, and processing order shows which steps run before and after the resize.

The result can't exceed the maximum output size set in the Plug configuration or server configuration. A larger result is scaled down to fit. A frame that exceeds the configured processing pixel limit fails with 422 before it is buffered, downsampled, or delivered. Native size limits also fail with 422 when the image's size and the requested options exceed them.

Resize

w and h

Accepts a whole pixel length from 1 to 2147483647, or auto. Default: none.

Sets the width and height of the box the image is resized into. How the image fills the box is set by fit, which defaults to contain. With only one of them, or with the other set to auto, the other dimension follows the image's aspect ratio, except under fit=stretch. auto needs a number in the other dimension or in min-w or min-h, and is ignored without one.

Without enlarge, the resized image is never larger than the source. A 300-pixel-wide source requested with w=400 comes out 300 pixels wide.

URL

/w=400/h=300/src/photos/beach.jpg

Elixir

ImagePipe.URL.group(builder, resize: [width: 400, height: 300])

fit

Accepts one of these named values. Default: contain.

  • contain fits the whole image inside the box. One side can come out shorter than the box.
  • cover fills the box and cuts off what doesn't fit. The center is kept unless anchor, focus, or detect sets another part.
  • stretch resizes the width and height separately to the box, which distorts the image when the aspect ratios differ. With only w, the height stays at the source height, and with only h, the width does.
  • auto uses cover when the source and the box are both landscape or both portrait, and contain otherwise. A square counts as landscape. With only one of w and h, it uses contain.

fit needs a number in w, h, min-w, or min-h in the same group, and is ignored without one.

Without enlarge, a cover result for a small source keeps the box's aspect ratio at a smaller size, because the box is scaled down to fit the source before cropping. A 300×300 source with w=400/h=300/fit=cover comes out 300×225.

URL

/w=400/h=300/fit=cover/src/photos/beach.jpg

Elixir

ImagePipe.URL.group(builder, resize: [width: 400, height: 300, fit: :cover])

enlarge

A boolean. Default: false.

Allows the result to be larger than the source. Without it, a source smaller than the requested size keeps its own size, or shrinks to keep the box's aspect ratio under fit=cover. enlarge needs a number in w, h, min-w, or min-h in the same group, and is ignored without one.

URL

/w=1200/enlarge/src/photos/beach.jpg

Elixir

ImagePipe.URL.group(builder, resize: [width: 1200, enlarge: true])

min-w and min-h

Accepts a whole pixel length from 1 to 2147483647. Default: none.

Sets the smallest width or height the resized image may have. When the target from w and h is smaller, ImagePipe enlarges the whole target, keeping its aspect ratio, until it meets both minimums. Without w or h, the target starts at the source's own size.

The minimums don't override enlarge: without it, the result still can't be larger than the source, so min-w or min-h alone changes nothing.

A 2:1 source at least 600 pixels wide, requested with w=400/min-h=300, comes out 600×300, because 400 pixels wide would make it only 200 pixels high.

URL

/w=400/min-h=300/src/photos/beach.jpg

Elixir

ImagePipe.URL.group(builder, resize: [width: 400, min_height: 300])

zoom

Accepts a positive number up to 2147483647, or an x,y pair of them. Default: 1.

Multiplies w and h before fit is applied, both by the one number or each by its own. With only min-w or min-h, it multiplies the source's size. An auto dimension follows the zoomed one, so w=400/zoom=2,1 gives an 800-pixel-wide image that keeps its aspect ratio.

Zoom doesn't change the canvas, padding, or offsets. A zoom other than 1 needs a number in w, h, min-w, or min-h in the same group, and is ignored without one.

URL

/w=400/zoom=1.5/src/photos/beach.jpg

Elixir

ImagePipe.URL.group(builder, resize: [width: 400, zoom: 1.5])

dpr

Accepts a positive number up to 2147483647, the device pixel ratio. Default: 1.

Multiplies the sizes you request in pixels: w, h, min-w, min-h, the extend canvas, pad, extend-offset, and an anchor-offset on a cover resize. /w=400/dpr=2 gives an 800-pixel-wide image, from a source at least that wide, for a 400-pixel slot on a high-density screen.

dpr doesn't change percentages, or the sizes and offsets of a crop or region, which are measured in pixels of the image being cropped.

  • Without w, h, min-w, or min-h there is nothing to resize, so the image keeps its own size. pad is still multiplied: /pad=10/dpr=2 adds 20 pixels on each side.
  • Without enlarge, a source too small to reach the requested size lowers the density used for padding, the canvas, and offsets to match the size actually reached. It never goes below the smaller of 1 and the requested dpr. A 150×150 source with w=100/h=100/dpr=2/pad=10 reaches 1.5× instead of 2×, so it comes out as 150×150 pixels of image with 15 pixels of padding on each side, 180×180 in all. Adding enlarge gives 240×240.

URL

/w=400/h=300/fit=cover/dpr=2/src/photos/beach.jpg

Elixir

ImagePipe.URL.group(builder, resize: [width: 400, height: 300, fit: :cover], dpr: 2)

Canvas, padding, and background

Added space is transparent until bg fills it.

extend and extend-ratio

Each is a boolean. Default: false.

  • extend places the image on a canvas of w × h pixels (times dpr).
  • extend-ratio adds space along one axis so the result has the aspect ratio w:h.

extend-at sets where the image sits on the canvas, the center by default.

Neither scales nor crops the image. Each needs numbers in both w and h, and is ignored without them. Using both in one group fails with 400. The canvas is never smaller than the image, so extend changes nothing when the image already fills the box, as with fit=cover.

A source smaller than the box keeps its size without enlarge: a 120×90 source with w=300/h=200/extend sits at 120×90 in the middle of a 300×200 canvas.

URL

/w=400/h=400/extend/src/photos/beach.jpg

Elixir

ImagePipe.URL.group(builder, resize: [width: 400, height: 400], extend: true)

extend-at and extend-offset

extend-at accepts an anchor. Default: center.

extend-offset accepts an x,y pair of pixel lengths or percentages, either of which can be negative. Percentages are of the canvas width and height. Pixels are multiplied by dpr. Default: 0,0.

extend-at sets where the image sits on the canvas, and extend-offset moves it from there. Positive values move it right and down from a left, top, or center anchor, and inward from a right or bottom anchor. The image always stays inside the canvas. Both need extend or extend-ratio in the same group, and are ignored without one.

URL

/w=400/h=400/extend/extend-at=bottom/extend-offset=0,10/src/photos/beach.jpg

Elixir

ImagePipe.URL.group(builder,
  resize: [width: 400, height: 400],
  extend: true,
  extend_at: :bottom,
  extend_offset: {0, 10}
)

pad

Accepts one to four whole pixel lengths from 0 to 1000000000, in CSS order. Default: none.

  • One value pads every side.
  • Two values pad the top and bottom, then the left and right.
  • Three values pad the top, then the left and right, then the bottom.
  • Four values pad the top, right, bottom, and left.

Adds space outside the image and any canvas, so the result grows by the padding. Padding is multiplied by dpr.

URL

/w=400/pad=10,20/src/photos/beach.jpg

Elixir

ImagePipe.URL.group(builder, resize: [width: 400], padding: {10, 20})

bg

Accepts a color, optionally followed by an alpha fraction. Default: none.

Fills every transparent pixel in the group's result: canvas, padding, the corners left by rotate, and transparent areas of the image itself. An opaque bg makes the image fully opaque. With an alpha below 1, those areas stay partly transparent.

Without bg, transparent areas stay transparent in formats that support it, such as PNG, WebP, and AVIF. JPEG has no transparency, so it turns any remaining transparency white.

URL

/w=400/h=400/extend/pad=12/bg=fff/src/photos/beach.jpg

Elixir

ImagePipe.URL.group(builder,
  resize: [width: 400, height: 400],
  extend: true,
  padding: 12,
  background: "fff"
)