sorl-thumbnail

pgmagick examples

Every result below is made by sorl-thumbnail with the pgmagick engine, from the template shown with it.

This site was built without pgmagick. The templates are still shown below.

Geometry

The geometry string sets the box the thumbnail must fit in: both sides, only the width, or only the height. The aspect ratio is kept.

Compare Pillow · libvips · ImageMagick · GraphicsMagick · Wand · pgmagick

Fit in a box

{% load thumbnail %}
{% thumbnail "images/caritas-romana.webp" "300x300" as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Caritas Romana fit inside a 300 by 300 box">
{% endthumbnail %}
Not built.

Fixed width

{% load thumbnail %}
{% thumbnail "images/kimono.avif" "300" as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Kimono scaled to 300 pixels wide">
{% endthumbnail %}
Not built.

Fixed height

{% load thumbnail %}
{% thumbnail "images/caritas-romana.webp" "x300" as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Caritas Romana scaled to 300 pixels high">
{% endthumbnail %}
Not built.

Crop

With crop the thumbnail fills the whole box and the overflow is cut. Position it with CSS-like keywords, percentages or pixels.

Compare Pillow · libvips · ImageMagick · GraphicsMagick · Wand · pgmagick

Center crop

{% load thumbnail %}
{% thumbnail "images/mona-lisa.jpg" "300x300" crop="center" as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Mona Lisa cropped to a square around the center">
{% endthumbnail %}
Not built.

Top crop

{% load thumbnail %}
{% thumbnail "images/mona-lisa.jpg" "300x300" crop="top" as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Mona Lisa cropped to a square from the top">
{% endthumbnail %}
Not built.

Bottom crop

{% load thumbnail %}
{% thumbnail "images/mona-lisa.jpg" "300x300" crop="bottom" as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Mona Lisa cropped to a square from the bottom">
{% endthumbnail %}
Not built.

Left crop

{% load thumbnail %}
{% thumbnail "images/caritas-romana.webp" "300x300" crop="left" as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Caritas Romana cropped to a square from the left">
{% endthumbnail %}
Not built.

Right crop

{% load thumbnail %}
{% thumbnail "images/caritas-romana.webp" "300x300" crop="right" as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Caritas Romana cropped to a square from the right">
{% endthumbnail %}
Not built.

Percentage offset

{% load thumbnail %}
{% thumbnail "images/mona-lisa.jpg" "300x150" crop="50% 20%" as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Mona Lisa cropped to a wide strip around the face">
{% endthumbnail %}
Not built.

Pixel offset

{% load thumbnail %}
{% thumbnail "images/caritas-romana.webp" "300x300" crop="40px 0px" as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Caritas Romana cropped 40 pixels in from the left">
{% endthumbnail %}
Not built.

No-op crop

{% load thumbnail %}
{% thumbnail "images/mona-lisa.jpg" "300x300" crop="noop" as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Mona Lisa scaled to fit, not cropped">
{% endthumbnail %}
Not built.

Smart crop

{% load thumbnail %}
{% thumbnail "images/fixtures/white_border.jpg" "200x200" crop="smart" as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Test image cropped to its busiest area">
{% endthumbnail %}
Not run: smart cropping is only implemented by Pillow and libvips.

Crop box

{% load thumbnail %}
{% thumbnail "images/mona-lisa.jpg" "300x300" cropbox="300,200,800,700" as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="The face of the Mona Lisa, cut out before scaling">
{% endthumbnail %}
Not built.

Upscale

Small sources are enlarged to the requested size unless upscale=False.

Compare Pillow · libvips · ImageMagick · GraphicsMagick · Wand · pgmagick

Upscaled (default)

{% load thumbnail %}
{% thumbnail "images/bouncing-ball.gif" "240x240" as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Small animation enlarged to 240 pixels">
{% endthumbnail %}
Not built.

Not upscaled

{% load thumbnail %}
{% thumbnail "images/bouncing-ball.gif" "240x240" upscale=False as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Small animation kept at its original size">
{% endthumbnail %}
Not built.

Formats

The output format is JPEG unless you ask for another one. Which formats work depends on the codecs the engine was built with.

Compare Pillow · libvips · ImageMagick · GraphicsMagick · Wand · pgmagick

JPEG

{% load thumbnail %}
{% thumbnail "images/mona-lisa.jpg" "240" format="JPEG" as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Mona Lisa as JPEG">
{% endthumbnail %}
Not built.

PNG

{% load thumbnail %}
{% thumbnail "images/mona-lisa.jpg" "240" format="PNG" as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Mona Lisa as PNG">
{% endthumbnail %}
Not built.

WEBP

{% load thumbnail %}
{% thumbnail "images/mona-lisa.jpg" "240" format="WEBP" as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Mona Lisa as WEBP">
{% endthumbnail %}
Not built.

GIF

{% load thumbnail %}
{% thumbnail "images/mona-lisa.jpg" "240" format="GIF" as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Mona Lisa as GIF">
{% endthumbnail %}
Not built.

AVIF

{% load thumbnail %}
{% thumbnail "images/mona-lisa.jpg" "240" format="AVIF" as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Mona Lisa as AVIF">
{% endthumbnail %}
Not built.

Quality

JPEG quality trades file size for detail. Progressive JPEGs load in passes; the final image is the same.

Compare Pillow · libvips · ImageMagick · GraphicsMagick · Wand · pgmagick

Quality 10

{% load thumbnail %}
{% thumbnail "images/mona-lisa.jpg" "240" quality=10 as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Mona Lisa at JPEG quality 10">
{% endthumbnail %}
Not built.

Quality 50

{% load thumbnail %}
{% thumbnail "images/mona-lisa.jpg" "240" quality=50 as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Mona Lisa at JPEG quality 50">
{% endthumbnail %}
Not built.

Quality 95 (default)

{% load thumbnail %}
{% thumbnail "images/mona-lisa.jpg" "240" as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Mona Lisa at the default JPEG quality">
{% endthumbnail %}
Not built.

Not progressive

{% load thumbnail %}
{% thumbnail "images/mona-lisa.jpg" "240" progressive=False as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Mona Lisa as a baseline JPEG">
{% endthumbnail %}
Not built.

Colorspace

Thumbnails are RGB by default. GRAY converts to grayscale.

Compare Pillow · libvips · ImageMagick · GraphicsMagick · Wand · pgmagick

RGB (default)

{% load thumbnail %}
{% thumbnail "images/kimono.avif" "240" as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Kimono in color">
{% endthumbnail %}
Not built.

Grayscale

{% load thumbnail %}
{% thumbnail "images/kimono.avif" "240" colorspace="GRAY" as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Kimono in grayscale">
{% endthumbnail %}
Not built.

Padding

With padding the thumbnail is centered on a canvas of the exact requested size.

Compare Pillow · libvips · ImageMagick · GraphicsMagick · Wand · pgmagick

White padding (default color)

{% load thumbnail %}
{% thumbnail "images/caritas-romana.webp" "300x300" padding=True as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Caritas Romana centered on a white square">
{% endthumbnail %}
Not run: this engine does not implement padding.

Colored padding

{% load thumbnail %}
{% thumbnail "images/caritas-romana.webp" "300x300" padding=True padding_color="#274c63" as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Caritas Romana centered on a blue square">
{% endthumbnail %}
Not run: this engine does not implement padding.

Effects

Rounded corners, blur and border removal.

Compare Pillow · libvips · ImageMagick · GraphicsMagick · Wand · pgmagick

Rounded corners

{% load thumbnail %}
{% thumbnail "images/earth-apollo-11.png" "300x300" rounded=40 format="PNG" as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Earth with rounded corners on a transparent background">
{% endthumbnail %}
Not run: rounded corners are only implemented by Pillow and libvips.

Blur

{% load thumbnail %}
{% thumbnail "images/mona-lisa.jpg" "240" blur=6 as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Mona Lisa blurred">
{% endthumbnail %}
Not run: blur is only implemented by Pillow and libvips.

Remove border

{% load thumbnail %}
{% thumbnail "images/fixtures/white_border.jpg" "200x200" remove_border=True as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Test image with its white border removed">
{% endthumbnail %}
Not run: border removal is only implemented by Pillow and libvips.

Animation

With GIF output, Wand and libvips keep every frame, and so does Pillow after 13.2.0 (#687). ImageMagick, GraphicsMagick and every other format take the first frame.

Compare Pillow · libvips · ImageMagick · GraphicsMagick · Wand · pgmagick

GIF output

{% load thumbnail %}
{% thumbnail "images/bouncing-ball.gif" "160x160" format="GIF" as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Animated bouncing ball">
{% endthumbnail %}
Not built.

PNG output

{% load thumbnail %}
{% thumbnail "images/bouncing-ball.gif" "160x160" format="PNG" as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="First frame of the bouncing ball">
{% endthumbnail %}
Not built.

Orientation

Photos are rotated following their EXIF orientation unless orientation=False. This test image is stored sideways.

Compare Pillow · libvips · ImageMagick · GraphicsMagick · Wand · pgmagick

Follow EXIF (default)

{% load thumbnail %}
{% thumbnail "images/fixtures/aspect_test.jpg" "200x200" as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Test image rotated upright">
{% endthumbnail %}
Not built.

Ignore EXIF

{% load thumbnail %}
{% thumbnail "images/fixtures/aspect_test.jpg" "200x200" orientation=False as im %}
  <img src="{{ im.url }}" loading="lazy"
       width="{{ im.width }}" height="{{ im.height }}"
       alt="Test image left as stored">
{% endthumbnail %}
Not built.

Filters

is_portrait tells you if an image is taller than wide, before making a thumbnail. margin centers a thumbnail in a fixed box.

Compare Pillow · libvips · ImageMagick · GraphicsMagick · Wand · pgmagick

is_portrait

{% load thumbnail %}
{% if "images/kimono.avif"|is_portrait %}
  {% thumbnail "images/kimono.avif" "x200" as im %}
    <img src="{{ im.url }}" loading="lazy"
         width="{{ im.width }}" height="{{ im.height }}"
         alt="Portrait kimono, limited by height">
  {% endthumbnail %}
{% else %}
  {% thumbnail "images/kimono.avif" "200" as im %}
    <img src="{{ im.url }}" loading="lazy"
         width="{{ im.width }}" height="{{ im.height }}"
         alt="Landscape kimono, limited by width">
  {% endthumbnail %}
{% endif %}
Not built.

margin

{% load thumbnail %}
{% thumbnail "images/caritas-romana.webp" "200x200" as im %}
  <div style="display: inline-block; background: #e6e1d6">
    <img src="{{ im.url }}" loading="lazy"
         width="{{ im.width }}" height="{{ im.height }}"
         style="display: block; margin: {{ im|margin:"200x200" }}"
         alt="Caritas Romana centered in a 200 by 200 frame">
  </div>
{% endthumbnail %}
Not built.

Not shown here

Alternative resolutions for high-density screens, dummy images, remote URLs as sources, and the density and authenticate options for PDF and other vector sources. See the settings and template references.

Sources

The original files the examples start from.

ImageWorkAuthorLicenseFile
Mona Lisa, original Mona Lisa Leonardo da Vinci Public domain JPEG · 1071×1600 · 390.4 KB
Earth from Apollo 11, original Earth from Apollo 11 NASA Public domain PNG · 1600×1440 · 630.8 KB
Caritas Romana, original Caritas Romana Artemisia Gentileschi Public domain WEBP · 1240×986 · 38.8 KB
Bouncing ball, original Bouncing ball Branko at English Wikipedia Public domain GIF · 82×82 · 6 frames · 2.1 KB
Kimono, original Kimono Momiji Jinzamomi and Kaede Fujisaki CC BY-SA 4.0 AVIF · 722×1024 · 83.4 KB
White border test image, original White border test image sorl-thumbnail tests BSD-3-Clause JPEG · 100×100 · 1.6 KB
EXIF orientation test image, original EXIF orientation test image sorl-thumbnail tests BSD-3-Clause JPEG · 200×100 · 5.6 KB