Resizing images and renaming them

I have 2 partials that does some image resizing.

the code is this:

	    {{ $largeAvatarPNG := $originalAvatar.Resize "512x512" }}
	    {{ with $largeAvatarPNG | resources.Copy (print "assets/avatar/" $urlizedName "-L.png") }}
		{{ $largeAvatarPNG = . }}
	    {{ end }}

I have two setups, 1 works and the other is causing issues.

I use this setup on page bundles, it will resize the image, rename the image and place it in the proper place. The fingerprinted file is stored in the gen folder.

when I use this same setup if the file is located in the assets directory like this:

    {{ $avatarFilename := .Site.Author.avatar }}
    {{ $originalAvatar := resources.Get $avatarFilename }}

    {{ if $originalAvatar }}
        {{ $urlizedName := .Site.Author.name | urlize }}

	    <!-- PNG Images -->
	    {{ $largeAvatarPNG := $originalAvatar.Resize "512x512" }}
	    {{ with $largeAvatarPNG | resources.Copy (print "assets/avatar/" $urlizedName "-L.png") }}
		{{ $largeAvatarPNG = . }}
	    {{ end }}
{{ end }}

the new file is created and copied to assets/avatar

but there’s also the fingerprinted file is left around in the root of the public folder on build.

hugo version:
hugo v0.113.0+extended linux/amd64 BuildDate=2023-08-30T08:06:23Z VendorInfo=debian:0.113.0-3

Is this normal behavior? Any way to fix this issue?

1 Like

I don’t see where you are calling the .Permalink, .RelPermalink, or .Publish method on the resources.

The entire file is a lot long and I provided the relevant parts to show where the images are being generated.

{{- if .Param "authorbox" }}
<div>
    {{ $avatarFilename := .Site.Author.avatar }}
    {{ $originalAvatar := resources.Get $avatarFilename }}

    {{ if $originalAvatar }}
        {{ $urlizedName := .Site.Author.name | urlize }}

	    <!-- PNG Images -->
	    {{ $largeAvatarPNG := $originalAvatar.Resize "512x512" }}
	    {{ with $largeAvatarPNG | resources.Copy (print "assets/avatar/" $urlizedName "-L.png") }}
		{{ $largeAvatarPNG = . }}
	    {{ end }}

	    {{ $mediumAvatarPNG := $originalAvatar.Resize "256x256" }}
	    {{ with $mediumAvatarPNG | resources.Copy (print "assets/avatar/" $urlizedName "-M.png") }}
		{{ $mediumAvatarPNG = . }}
	    {{ end }}

	    {{ $smallAvatarPNG := $originalAvatar.Resize "128x128" }}
	    {{ with $smallAvatarPNG | resources.Copy (print "assets/avatar/" $urlizedName "-S.png") }}
		{{ $smallAvatarPNG = . }}
	    {{ end }}

	    {{ $extraSmallAvatarPNG := $originalAvatar.Resize "64x64" }}
	    {{ with $extraSmallAvatarPNG | resources.Copy (print "assets/avatar/" $urlizedName "-XS.png") }}
		{{ $extraSmallAvatarPNG = . }}
	    {{ end }}

	    <!-- WebP Images -->
	    {{ $largeAvatarWEBP := $originalAvatar.Resize "512x512 webp" }}
	    {{ with $largeAvatarWEBP | resources.Copy (print "assets/avatar/" $urlizedName "-L.webp") }}
		{{ $largeAvatarWEBP = . }}
	    {{ end }}

	    {{ $mediumAvatarWEBP := $originalAvatar.Resize "256x256 webp" }}
	    {{ with $mediumAvatarWEBP | resources.Copy (print "assets/avatar/" $urlizedName "-M.webp") }}
		{{ $mediumAvatarWEBP = . }}
	    {{ end }}

	    {{ $smallAvatarWEBP := $originalAvatar.Resize "128x128 webp" }}
	    {{ with $smallAvatarWEBP | resources.Copy (print "assets/avatar/" $urlizedName "-S.webp") }}
		{{ $smallAvatarWEBP = . }}
	    {{ end }}

	    {{ $extraSmallAvatarWEBP := $originalAvatar.Resize "64x64 webp" }}
	    {{ with $extraSmallAvatarWEBP | resources.Copy (print "assets/avatar/" $urlizedName "-XS.webp") }}
		{{ $extraSmallAvatarWEBP = . }}
	    {{ end }}

	    <!-- JPG Images -->
	    {{ $largeAvatarJPG := $originalAvatar.Resize "512x512 jpg" }}
	    {{ with $largeAvatarJPG | resources.Copy (print "assets/avatar/" $urlizedName "-L.jpg") }}
		{{ $largeAvatarJPG = . }}
	    {{ end }}

	    {{ $mediumAvatarJPG := $originalAvatar.Resize "256x256 jpg" }}
	    {{ with $mediumAvatarJPG | resources.Copy (print "assets/avatar/" $urlizedName "-M.jpg") }}
		{{ $mediumAvatarJPG = . }}
	    {{ end }}

	    {{ $smallAvatarJPG := $originalAvatar.Resize "128x128 jpg" }}
	    {{ with $smallAvatarJPG | resources.Copy (print "assets/avatar/" $urlizedName "-S.jpg") }}
		{{ $smallAvatarJPG = . }}
	    {{ end }}

	    {{ $extraSmallAvatarJPG := $originalAvatar.Resize "64x64 jpg" }}
	    {{ with $extraSmallAvatarJPG | resources.Copy (print "assets/avatar/" $urlizedName "-XS.jpg") }}
		{{ $extraSmallAvatarJPG = . }}
	    {{ end }}
		<picture>
		    <!-- WebP format -->
		    <source media="(min-width: 512px)" srcset="{{ $largeAvatarWEBP.RelPermalink }}" type="image/webp">
		    <source media="(min-width: 256px)" srcset="{{ $mediumAvatarWEBP.RelPermalink }}" type="image/webp">
		    <source media="(min-width: 128px)" srcset="{{ $smallAvatarWEBP.RelPermalink }}" type="image/webp">
		    <source srcset="{{ $extraSmallAvatarWEBP.RelPermalink }}" type="image/webp">

		    <!-- PNG format -->
		    <source media="(min-width: 512px)" srcset="{{ $largeAvatarPNG.RelPermalink }}" type="image/png">
		    <source media="(min-width: 256px)" srcset="{{ $mediumAvatarPNG.RelPermalink }}" type="image/png">
		    <source media="(min-width: 128px)" srcset="{{ $smallAvatarPNG.RelPermalink }}" type="image/png">
		    <source srcset="{{ $extraSmallAvatarPNG.RelPermalink }}" type="image/png">

		    <!-- JPG format -->
		    <source media="(min-width: 512px)" srcset="{{ $largeAvatarJPG.RelPermalink }}" type="image/png">
		    <source media="(min-width: 256px)" srcset="{{ $mediumAvatarJPG.RelPermalink }}" type="image/png">
		    <source media="(min-width: 128px)" srcset="{{ $smallAvatarJPG.RelPermalink }}" type="image/png">
		    <source srcset="{{ $extraSmallAvatarJPG.RelPermalink }}" type="image/png">


		    <!-- Fallback JPG image -->
		    <img alt="{{ $.Site.Author.name }} avatar" src="{{ $mediumAvatarJPG.RelPermalink }}" width="90" height="90">
		</picture>
    {{- end }}

    {{- with .Site.Author.name }}
    <div>
        <span>{{ T "authorbox_name" (dict "Name" .) }}</span>
    </div>
    {{- end }}

    {{- with .Site.Author.bio }}
    <div>
        {{ . | markdownify }}
    </div>
    {{- end }}
</div>
{{- end }}

the files are successfully created and placed in assets/avatar folder but the fingerprinted files are left over in the public folder.

I use similar method to generate different size images from page bundle resources with no issues.

When I use this for files in assets directory there fingerprinted files are also left around in the root of the public directory after building the site.

I asked about your calls to .Permalink, .RelPermalink, and .Publish because those methods cause the resource to be written to the public directory.

This works as expected
<h2>Page resource</h2>

{{ with .Resources.Get "images/a.jpg" }}
  {{ with .Resize "200x" }}
    {{ with . | resources.Copy "/assets/images/a.jpg" }}
      <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="">
    {{ end }}
  {{ end }}
{{ end }}

<h2>Global resource</h2>

{{ with resources.Get "images/b.jpg" }}
  {{ with .Resize "200x" }}
    {{ with . | resources.Copy "/assets/images/b.jpg" }}
      <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="">
    {{ end }}
  {{ end }}
{{ end }}

Try it:

git clone --single-branch -b hugo-forum-topic-46552 https://github.com/jmooring/hugo-testing hugo-forum-topic-46552
cd hugo-forum-topic-46552
hugo server

Then visit http://localhost:1313/posts/post-1/

Then check the contents of public:

rm -rf public && hugo && tree public

after cloning the repo, saw there’s no artifacts in the public directory.

Does that mean i have to use this structure:

{{ with resources.Get "images/b.jpg" }}
  {{ with .Resize "200x" }}
    {{ with . | resources.Copy "/assets/images/b.jpg" }}
      <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="">
    {{ end }}
  {{ end }}
{{ end }}

for each image i need to format? My example code above have large, medium, small, for jpg, png and webp.

First, if it were me, I wouldn’t rename the images. According to John Mueller of Google:

So having descriptive filenames is good.

But I don’t think you would see a significant change if you already do the other things around images, like the alt texts, the text surrounding the image.

Those are really, really strong signals.

And the filename itself is often… it’s kind of from a technical point of view.

This is what we called it, but it doesn’t provide any real unique information, usually.

Of course, if you don’t do the alt text, or if you don’t have good surrounding text, then, of course, the filename might be the only place where you mention what this image is about.

But if you do the rest, then usually the filenames are okay.

https://www.searchenginejournal.com/google-on-image-filenames-a-surprising-seo-mistake/468366/
https://webaheadinternetltd.co.uk/do-image-filenames-have-a-significant-impact-on-seo/
https://search-off-the-record.libsyn.com/lets-talk-image-seo

Second, if I have time I might look at your stuff, but only if you provide access to a repository. I am not going to recreate your setup.

2 Likes

What’s the point of having jpg, webp, and png versions of the same image? All current bruisers display webp just fine.

Safari is the culprit here.

apologies but I cannot share this site’s repo at this time.

I’ll see if I can sort out what’s going on with this.

its really strange behavior that those functions would cause resources to be written to the public directory when they were already saved in another location and being correctly linked from that path…

So, those three methods are what causes a resource to be written to the public directory. Nothing else.

trying to think of a solution, i would need to see if after the images are created, instead of linking with the *links functions, i can manually generate the file paths and link them myself. This is hacky and prone to break.

Your explanation also explains why sometimes random images would end up in the public directory but this only seems to affect resources placed in the assets directory and not page bundles.

another solution is a script that just deletes the images from the public directory after the build has been completed but again, that’s also problematic.

How? Safari has full support of WebP, but requires macOS 11 (Big Sur), released three years ago. And what is PNG needed for?

Not everyone has the luxury of the latest iphones or macs, especially in developing countries.

True. Then one has to find a balance between the pros (possibly larger audience) and the cons (local disk space, code complexity, Hugo run time).

I still don’t see where PNG come into play, though. Even with very old devices …

PNG is the only raster image format with an alpha channel usable for websites.

WebP also has an alpha channel.

identify -verbose example.webp
Result
Image:
  Filename: example.webp
  Format: WEBP (WebP Image Format)
  Mime type: image/webp
  Class: DirectClass
  Geometry: 510x510+0+0
  Units: Undefined
  Colorspace: sRGB
  Type: TrueColorAlpha
  Base type: Undefined
  Endianness: Undefined
  Depth: 8-bit
  Channel depth:
    red: 8-bit
    green: 8-bit
    blue: 8-bit
    alpha: 8-bit
  Channel statistics:
    Pixels: 260100
    Red:
      min: 13  (0.0509804)
      max: 255 (1)
      mean: 190.013 (0.74515)
      standard deviation: 96.1356 (0.377002)
      kurtosis: -0.912241
      skewness: -0.991407
      entropy: 0.309377
    Green:
      min: 53  (0.207843)
      max: 255 (1)
      mean: 185.294 (0.726643)
      standard deviation: 87.9074 (0.344735)
      kurtosis: -1.72434
      skewness: -0.48883
      entropy: 0.344154
    Blue:
      min: 0  (0)
      max: 255 (1)
      mean: 191.298 (0.750189)
      standard deviation: 88.4233 (0.346758)
      kurtosis: -0.230313
      skewness: -1.05322
      entropy: 0.307396
    Alpha:
      min: 0  (0)
      max: 255 (1)
      mean: 85.1879 (0.33407)
      standard deviation: 119.828 (0.469914)
      kurtosis: -1.49985
      skewness: 0.703284
      entropy: 0.254756
  Image statistics:
    Overall:
      min: 0  (0)
      max: 255 (1)
      mean: 162.948 (0.639013)
      standard deviation: 98.0736 (0.384602)
      kurtosis: -1.54833
      skewness: -0.49954
      entropy: 0.303921
  Alpha: srgba(255,255,255,0)   #FFFFFF00
  Rendering intent: Perceptual
  Gamma: 0.454545
  Chromaticity:
    red primary: (0.64,0.33)
    green primary: (0.3,0.6)
    blue primary: (0.15,0.06)
    white point: (0.3127,0.329)
  Background color: white
  Border color: srgba(223,223,223,1)
  Matte color: grey74
  Transparent color: none
  Interlace: None
  Intensity: Undefined
  Compose: Over
  Page geometry: 510x510+0+0
  Dispose: Undefined
  Iterations: 0
  Compression: Undefined
  Orientation: Undefined
  Properties:
    date:create: 2023-10-07T19:03:31+00:00
    date:modify: 2023-10-07T19:01:41+00:00
    signature: 52a5739e858c0e3bafcb24cf8c192114cbb7a4a7636df6f7b38fb3b05d0c6460
  Artifacts:
    filename: example.webp
    verbose: true
  Tainted: False
  Filesize: 7102B
  Number pixels: 260100
  Pixels per second: 62.7805MB
  User time: 0.010u
  Elapsed time: 0:01.004
  Version: ImageMagick 6.9.11-60 Q16 x86_64 2021-01-25 https://imagemagick.org


2 Likes

Nice, that’s a pretty new feature I’ve missed. Thanks!

I was talking about webP specifically. You will be surprised how popular older iphones and macs are in some developing countries when their prices go down with age. So, as you said, it is a matter of choice vs support for your audience.

this topic has gotten a bit off topic.

Is it possible to address the issue that I brought up? I’ve been trying different things and the more I touch resources.Copy or image processing in general, it’s pretty rough sailing.

It’s really rough just how many sharp edges are around these corners of the code.