published on 23.01.2021

Image processing may seem complicated at first but it’s actually easy and definitely worth implementing since it’ll help you decrease page load times. As you probably know, we don’t want to load raw images with huge sizes for small thumbnails or blog-posts. We want to load a small image if we are going to display it in a small container or on small devices like smartphones. Yet, we don’t want to resize images, rename and store them manually. No one would do that. Thankfully, Hugo has a feature called image processing.

Before, going further you must know that you can’t store your images under /static folder anymore. To be able to use image processing, an image must be a resource. What is a resource? Hugo has two types of resources. One is called ‘Page Resource’, page resources are stored within the page’s directory. So, you create a folder for each post and rename the post content as and keep the images in the same folder. The second one is called ‘Global Resource’ which is stored in /assets.

The Fuji Reflects in Lake Kawaguchi
The Fuji Reflects in Lake Kawaguchi

I moved all images under /static to /assets folder. Of course, you can create sub-folders inside the assets folder. I would’ve stored the images for this post like this: /assets/images/posts/2021-01-23-image-processing-hugo/.

Resize An Image

First, I will start with a simple example. Let’s say we want to create a fixed-sized smaller image from a bigger raw image. We’ll use it as a thumbnail for all devices. We won’t bother with the device size for now.

{{ $imagePath := printf "images/thumbnails/%s" .Params.thumbnail }}
{{- $image := resources.Get $imagePath -}}
<img src="{{ ($image.Fill "320x500 q75 Center").RelPermalink }}"/>
  1. Get the image path somehow. I set the image I wanted to use for a post in it’s front-matter. thumbnail: blablabla.jpg
  2. The second line looks up to the given path and gets the resource(image) if there is any match. Don’t forget that this looks under /assets folder. So, the path you give should be relative to the assets.
  3. The third line resizes the image 320x500 with quality 75 and use its relative permalink.

Use srcset

In this section, we will use srcset. Source set requires a set of images instead of one image. So, we will need to resize an image multiple times. Then, we’ll give use all these images in html file and let the browser decide which one to use. The browser will load the appropriate size according to device size.

{{ $banner := resources.GetMatch "pathToYourImage" }}

{{ $tiny := ($banner.Fill "480x280 q90") }}
{{ $small := ($banner.Fill "768x280 q90") }}
{{ $medium := ($banner.Fill "1024x280 q90") }}
{{ $large := ($banner.Fill "1366x280 q90") }}

    {{- with $tiny.RelPermalink -}}{{.}} 480w{{- end -}}
    {{- with $small.RelPermalink -}}, {{.}} 768w{{- end -}}
    {{- with $medium.RelPermalink -}}, {{.}} 1024w{{- end -}}
    {{- with $large.RelPermalink -}}, {{.}} 1366w{{- end -}}"
src="{{ $banner.RelPermalink }}"

Image Processing in Blog Posts

Normally, to use an image in our markdown file we use standard syntax ![](). Even though, I don’t like to go out of plain markdown, I had to create a shortcode for providing more features, like captions, css classes, image-processing and javascript libraries like nanogallery2.

A shortcode is a code snippet in Hugo, that takes some input process it and returns an output just like a function. So, I have got a shortcode named “img” and I call it in markdown files, like this: {\<img src="" >}. In this shortcode, I didn’t use srcset. It simply resizes the given image to a pre-defined fixed size and uses nanogallery2 (a javascript library) to display the original image on click. I’ll share my nanogallery2 experience in another post, since it feels like another topic. Yet, if we want to display an image in smaller size without any javascript features. We can do so, by simply creating a shortcode.

{{ $image = resources.GetMatch (.Get "src") }}

{{/* Generate Thumbnail */}}
{{ if ge $image.Width $image.Height }}
{{ if ge $image.Width "600" }}
    {{ $.Scratch.Set "thumbnail" ($image.Resize "600x q90") }}
{{ else}}
    {{ $.Scratch.Set "thumbnail" $image }}
{{ end }}
{{ else }}
{{ if ge $image.Height "450" }}
    {{ $.Scratch.Set "thumbnail" ($image.Resize "x450 q90") }}
{{ else }}
    {{ $.Scratch.Set "thumbnail" $image }}
{{ end }}
{{ end }}

<img src="{{ ($.Scratch.Get "thumbnail").RelPermalink }}"/>


Processing images will increase the build time but Hugo is pretty fast and you’ll not notice it probably. Good thing is that Hugo is caching these results and won’t start all over again when you are working in your local environment. So, it shouldn’t affect your workflow. You may see an increase in build time on the server (GitHub, Netlify, GitLab, or whatever service you are using).

I don’t have a scientifically right benchmark but this should give an idea: I’ve around 50-60 image files which are ~25MB in total and build time is increased from 30-36 seconds to 40-50 seconds which is very fast. Local build times took less than 7 seconds if I clean the cache and less than 1 second with the cache. Just amazing!

You are reading the 18th of 19 episodes in Hugo.
Published on 23.01.2021 by Mert Bakır with commit 160ea1b.
#hugo #static-site
Next episode:
NanoGallery2 with Hugo
published on 24.01.2021

Some time ago, I wanted to display image galleries on my Hugo website and searched for Hugo themes for photography and gallery. I can’t say I find much. Then, I met with a javascript library called nanogallery2 which is using another javascript library as an image viewer lightbox2. In this …

published on 17.04.2022
edited on 02.05.2022

Önceki bölümde, markdown formatını LaTeX formatına dönüştürmek için kullanılan Pandoc yazılımından bahsetmiştik. Şimdi konuyu bir adım daha ileri taşıyıp ve bookdown’a geçiyoruz. Bookdown; Rmarkdown kullanarak teknik dökümanlar, kitaplar yazabilmemizi sağlayan, Yihui Xie tarafından yazılmış …

published on 10.04.2022

I’ve been using WSL-2 on Windows for over a year. It’s very useful because some Python packages are just a headache to install on Windows. Also, docker. It’s just better on Linux. Yet, WSL-2 can also be problematic. I remember trying a dual-boot setup when things just went way too …

published on 03.03.2022

In this post, I’ll share how to install geopandas and some other gis related packages on Windows. If you are on Mac or Linux you can probably just pip install those without any issue. I usually had to do a google search every time I wanted to install these packages on Windows environment. Of …

published on 19.02.2022

Önceki yazıda LaTeX kullanmanın avantajlarından ve zorluklarından bahsetmiştim, MS Word gibi WYSIWYG programlar ile karşılaştırıp tavsiyelerimi yazmıştım. Bu yazıda Pandoc yazılımı üzerine konuşacağız. Pandoc’un da yardımıyla LaTeX’in avantajlarını alıp zorluklarını biraz geri de …

published on 12.02.2022

LaTeX bir çeşit döküman hazırlama sistemidir, ancak çoğumuzun alıştığı arayüzlerin aksine bu döküman içerisinde kod yazar gibi bazı komutlar kullanırız. Daha sonra derleyici (compiler) bu dökümanı bizim tanımladığınız kurallara göre PDF’e dönüştürür. […] 1978 yılında, Donald Knuth TeX …

published on 02.01.2022

This post is for fellow students who is studying Operations Research with CPLEX. If you don’t know already, IBM offers free academic license for IBM ILOG CPLEX Optimization Studio. […] First, you have to register IBM Academic Initiative with your academic instituion issued email. (e.g. …