← Hugo/Lightbox image gallery: Loading image captions from EXIF data

Hugo/Lightbox image gallery: Overlay images with logo

| tags: hugo, lightbox2, web

Another nice addition to the Hugo/Lightbox2 image gallery: one of Hugo’s available image filters is able to overlay the gallery images with a logo.

Before we start, here’s the previous version of the gallery shortcode (including the EXIF caption from the last post) for reference:

/layouts/shortcodes/gallery.html:

{{ $image := (.Page.Resources.ByType "image") }}
{{ with $image }}
	{{ range . }}
	{{ $resized := .Fill "150x115 q20" }}
	<a href="{{ .Permalink }}" data-lightbox="x" data-title="{{ with .Exif }}{{ .Tags.ImageDescription }}{{ end }}"><img src="{{ $resized.Permalink }}" /></a>
	{{ end }}
{{ end }}

Like in the previous post, I will add the changes shown here as new commits in the hugo-gallery-example project in my code-examples repository.


In order to be processed by Hugo, images must be either page resources or global resources.
The gallery images are page resources anyway, but the logo that will overlay all gallery images doesn’t belong to one single page. So it has to be a global resource.

The simplest way to make it a global resource is putting it into the assets folder.

Once it’s there, it can be applied to all gallery images by:

  • loading the logo with resources.Get
  • applying the filter, which overlays the gallery image with the logo
  • showing the changed image in the gallery instead of the original one

Here’s the commit with the changes.

The complete changed shortcode now looks like this:

{{ $logo := resources.Get "img/overlay-logo.png" }}
{{ $image := (.Page.Resources.ByType "image") }}
{{ with $image }}
	{{ range . }}
	{{ $resized := .Fill "150x115 q20" }}
	{{ $withlogo := .Filter (images.Overlay $logo 10 10)}}
	<a href="{{ $withlogo.Permalink }}" data-lightbox="x" data-title="{{ with .Exif }}{{ .Tags.ImageDescription }}{{ end }}"><img src="{{ $resized.Permalink }}" /></a>
	{{ end }}
{{ end }}

Step 2: move to bottom right

The coordinates are from the top left, so images.Overlay $logo 10 10 means 10 pixels from the top and 10 pixels from the left.

But I wanted to have the logo at the bottom right, so I needed to calculate the correct pixel values depending on the sizes of the gallery image and the logo.

The calculation itself is not difficult. All images in Hugo have properties for width and height, so I can access $logo.Width and $logo.Height (for the logo) and .Width and .Height (for the current gallery image).

For example, the correct x value for the logo’s top left corner (so that its bottom right corner is 10 pixels away from the right and from the bottom) is .Width - $logo.Width - 10,

Here’s some fancy ASCII art to visualize:

┌───────────────────────────────────────────────┐
│                                               │
│                                               │
│                                               │
│                                               │
│                          ┌─────────────┐      │
│                          │     LOGO    │      │
│                          └─────────────┘      │
│<---------- x -----------><-$logo.Width-><-10->│
│                                               │
└───────────────────────────────────────────────┘
    
<-------------------- .Width ------------------->

Same for the height: .Height - $logo.Height - 10

But I spent an insane amount of time getting the syntax right. The problem was the (for me) unusual syntax of Hugo’s template functions.

Getting used to the {{ name parameter1 parameter2 }} format and finding the correct math functions was one thing, but nesting two of these calls with all the correct brackets made my brain hurt.

But actually I just had to change this:

{{ $withlogo := .Filter (images.Overlay $logo 10 10)}}

…into this:

{{ $x := sub .Width (add $logo.Width 10) }}
{{ $y := sub .Height (add $logo.Height 10) }}
{{ $withlogo := .Filter (images.Overlay $logo $x $y)}}

Here’s the commit, and finally here’s the complete changed shortcode again:

{{ $logo := resources.Get "img/overlay-logo.png" }}
{{ $image := (.Page.Resources.ByType "image") }}
{{ with $image }}
	{{ range . }}
	{{ $resized := .Fill "150x115 q20" }}
	{{ $x := sub .Width (add $logo.Width 10) }}
	{{ $y := sub .Height (add $logo.Height 10) }}
	{{ $withlogo := .Filter (images.Overlay $logo $x $y)}}
	<a href="{{ $withlogo.Permalink }}" data-lightbox="x" data-title="{{ with .Exif }}{{ .Tags.ImageDescription }}{{ end }}"><img src="{{ $resized.Permalink }}" /></a>
	{{ end }}
{{ end }}

Once again, I am amazed by Hugo’s image manipulation features.

With these few lines of template code, I can now auto-create a thumbnail, pull the image title from the image’s EXIF data and overlay the image with a logo.


← Hugo/Lightbox image gallery: Loading image captions from EXIF data