Use Hugo Shortcodes to read pictures EXIF metadata
If you’ve read my previous article about a Champagne cave visit, you may have noticed that all the photos are displaying their technical metadata : Camera and Lens model, aperture, speed, etc. Sorry to deceive you, but I haven’t written all these text manually, I’ve used one of the resourceful Hugo feature : the shortcodes.
What are shortcodes
Basically, Hugo shortcodes allow you to create custom tags that Hugo will read and interpret during rendering based on a template you’ve provided.
In my pictures case, this shortcode :
{{< exif src="photos/visite-cave-champagne/DSC_0019.jpg" alt="Test EXIF reading" >}}
Will render this :
How to declare the shortcode
As the documentation says, the shortcodes can be declared at two places, in the following order :
- /layouts/shortcodes/<SHORTCODE>.html
- /themes/<THEME>/layouts/shortcodes/<SHORTCODE>.html
For my Exif reader, I’ve created the following file : /layouts/shortcodes/exif.html
Inside, I’ve put this code :
{{- $imageName := .Get "src" -}}
{{- $alt := .Get "alt" -}}
{{- $originalImage := resources.Get $imageName -}}
<figure>
<img src="{{ $originalImage.RelPermalink }}" alt="{{ $alt }}">
{{ with $originalImage.Exif }}
<figcaption>{{ $alt }}
<br />{{with .Tags.Model }}{{ . }} {{ end }} {{with .Tags.LensModel }}{{ . }} {{ end }} {{ with .Tags.FNumber }}<i>f</i>{{ . }} {{ end }} {{ with .Tags.FocalLength }} {{ . }}mm{{ end }} {{ with .Tags.ExposureTime }} {{ partial "format-exposure-time.html" . }} {{ end }} {{ with .Tags.ISOSpeedRatings }} ISO {{ . }}{{ end }}
<br />{{with .Tags.Artist }}{{ . }} - {{ end }} {{with .Tags.DateTimeOriginal }} {{ . }} - {{ end }} {{ with .Tags.Copyright}}{{ . }}{{ end }}
</figcaption>
{{ end }}
</figure>
You may have noticed this part : {{ partial "format-exposure-time.html" . }}
.
That’s a partial template I’ve found on Hugo’s Forum to format the exposure time from raw milliseconds to 1/xx seconds as displayed by cameras. You can create it in the following folders :
- /layouts/partials/format-exposure-time.html
- /themes/<THEME>/layouts/partials/format-exposure-time.html
With the following code (which I don’t really understand to be honest) :
{{ $n := "- . ," }} {{/* numFmt options */}}
{{ $p := 9 }} {{/* precision */}}
{{ $e := "" }}
{{ if eq (printf "%T" .) "float64" }}
{{ $r := div 1 . }}
{{ if math.ModBool (mul $r (pow 10 $p)) (mul (int $r) (pow 10 $p)) }}
{{ $e = printf "1/%d s" (int $r) }}
{{ else }}
{{ $e = printf "%s s" (lang.NumFmt $p . $n ) }}
{{ end }}
{{ else }}
{{ $e = printf "%s s" . }}
{{ end }}
{{ return $e }}
Variation : Display all EXIF tags
For debugging purpose, I had to create a version of this shortcode that returns all supported tags. It’s the same procedure as below, but I’ve named the HTML file exif-full.html
.
So, if I call this :
{{< exif-full src="photos/visite-cave-champagne/DSC_0019.jpg" alt="Test EXIF reading" >}}
The output will display all EXIF metadata :
Date: 2022-01-06 15:18:33 +0100 CET Lat/Long: 0/0 Tags:* TAG: Artist: Seb
* TAG: CFAPattern:
* TAG: Copyright: Creative Commons Attribution-ShareAlike (CC BY-SA)
* TAG: CustomRendered: 0
* TAG: DateTime: 2022-01-11 22:27:26 +0100 CET
* TAG: DateTimeDigitized: 2022-01-06 15:18:33 +0100 CET
(...)
The shortcode code is the same, with an extra part taken from Hugo’s Image Processing documentation :
{{- $imageName := .Get "src" -}}
{{- $alt := .Get "alt" -}}
{{- $originalImage := resources.Get $imageName -}}
<figure>
<img src="{{ $originalImage.RelPermalink }}" alt="{{ $alt }}">
{{ with $originalImage.Exif }}
<figcaption>{{ $alt }}
<br />{{with .Tags.Model }}{{ . }} {{ end }} {{with .Tags.LensModel }}{{ . }} {{ end }} {{ with .Tags.FNumber }}<i>f</i>{{ . }} {{ end }} {{ with .Tags.FocalLength }} {{ . }}mm{{ end }} {{ with .Tags.ExposureTime }} {{ partial "format-exposure-time.html" . }} {{ end }} {{ with .Tags.ISOSpeedRatings }} ISO {{ . }}{{ end }}
<br />{{with .Tags.Artist }}{{ . }} - {{ end }} {{with .Tags.DateTimeOriginal }} {{ . }} - {{ end }} {{ with .Tags.Copyright}}{{ . }}{{ end }}
</figcaption>
{{ end }}
</figure>
{{ with $originalImage.Exif }}
Date: {{ .Date }}
Lat/Long: {{ .Lat}}/{{ .Long }}
Tags:
{{ range $k, $v := .Tags }}
<li>TAG: {{ $k }}: {{ $v }}</li>
{{ end }}
{{ end }}
Lens Model issue with Darktable
During my shortcode testings, I’ve encountered an issue where the Lens Model field was not displayed. As the value was correctly displayed by Darktable (which I use to develop my pictures) and gThumb, I thought about a problem with in my code, or maybe Hugo. So I’ve opened a support request on Hugo’s forum.
Thanks to some nice analysis material provided by the members of this forum, and ensured the problem was my pictures and not Hugo, I’ve understood that Darktable didn’t properly filled the Lens Model field. Instead, it was the Lens ID and Hugo is not currently reading it.
After digging a little on Darktable issues, I’ve found this one and this one that helped me. In Darktable export module, open the module preferences.
First, ensure the “Exif Data” field is checked.
Then, add a redefined tag for Exif.Photo.LensModel
with $(LENS)
as a value.
Export your picture again and you should have the expected result.
I hope this shortcode will help you, don’t hesitate to send your suggestions about this code, as I’m not a developer, maybe it could be better 😀