Image processing in Hugo

2021.06.22, updated 2023.01.03. Tags: Hugo

The image processing system in Hugo was an interesting discovery and I really liked it: it’s quite powerful and functional, but it also has a simple interface that allows you to customize it with a few lines of code. It also supports WebP, an image format that I also really like.

I made the following shortcode for inserting images:

layouts/shortcodes/img.html

{{ $original := $.Page.Resources.GetMatch (.Get 0) }}
{{ $optimized := $original.Fit "896x3072 webp" }}

<figure>
	<a href="{{ $original.RelPermalink }}" target="_blank">
		<picture>
			<source type="image/webp" srcset="{{ $optimized.RelPermalink }}">
			<img src="{{ $original.RelPermalink }}" alt="{{ .Get 1 }}"
				 width="{{ $optimized.Width }}" height="{{ $optimized.Height }}" />
		</picture>
	</a>
	<figcaption>{{ .Get 1 }}</figcaption>
</figure>

Usage within Markdown

{{< img "myimage.png" "My favourite picture" >}}

What is it doing

  1. The first argument is the image from the page directory (Page Resource)
  2. If the image is wider than the specified value, it’s scaled to that width with the proportions preserved: in my case it’s a bit less than the maximum width of a text block on the page (896 pixels).
  3. The optimized image is saved in the WebP format;
  4. Since this size limit may not be enough for some images, the user can open the original in a new tab by clicking on the image;
  5. The optimized image is shown on the page along with the caption from the second shortcode argument (for accessibility and cases when the image is not loaded);
  6. For older browsers that do not support WebP and/or the picture tag, the original image is shown.

And – most importantly – all transformations are done at the building stage automatically, which means that the directory with the content does not store two copies of the same picture in different formats, which is very convenient and consistent with the principle of DRY.

If you wish, you can similarly make several optimized images for different screen sizes using the media attribute of the source tag.

Settings

The default image quality is not the best, especially after they are scaled.

The following settings in the config.yaml file significantly improved the appearance of the optimized images:

imaging:
  quality: 85 # percent
  hint: picture
  resampleFilter: Lanczos

In my case, the images are mostly screenshots, so for other cases (such as photos), the settings might need to be adjusted.

The result

On the test page without image scaling, the size changed as follows:

Source formatJPEGPNG
Original size15,95 Kb21,33 Kb
WebP size4,45 Kb15,95 Kb

To me, the difference is barely noticeable when comparing side by side.