gohugoio / hugo

The world’s fastest framework for building websites.
https://gohugo.io
Apache License 2.0
76.22k stars 7.55k forks source link

Image distorted when rotating and cropping/filling using the smart anchor #11266

Open eiszfuchs opened 1 year ago

eiszfuchs commented 1 year ago

What version of Hugo are you using (hugo version)?

$ hugo version
hugo v0.112.3+extended linux/amd64 BuildDate=unknown

Does this issue reproduce with the latest release?

The bug is also present in

hugo v0.115.3-5c2e014a5150553a9fa4f9c1eb7dc4db89c0f1ab+extended linux/amd64 BuildDate=2023-07-13T16:11:34Z VendorInfo=gohugoio

Description

I am currently collecting a lot of JPEG files of different sources and try to present them with thumbnails. Since photos aren't rotated automatically, I wrote a few partials that help me identify resources and normalize rotation from .Exif. I soon noticed that portrait images were distorted in my thumbnail list.

This might be related to https://github.com/gohugoio/hugo/issues/6120, but I'm not sure.

Reproduction steps

Create a shortcode to resize images:

{{ $r := .Get "r" }}
{{ with $.Page.Resources.GetMatch (.Get "src") }}
    {{ with .Fill (printf "r%s 200x200 smart" $r) }}
        <img src={{ .RelPermalink }} width={{ .Width }} height={{ .Height }} >
    {{ end }}

    {{ with .Fit (printf "r%s 200x200 smart" $r) }}
        <img src={{ .RelPermalink }} width={{ .Width }} height={{ .Height }} >
    {{ end }}
{{ end }}

Use the shortcode in a post:

<!-- Using images from https://github.com/recurser/exif-orientation-examples to test -->

{{< fill-bug src="Portrait_0.jpg" r="0" >}}

{{< fill-bug src="Portrait_6.jpg" r="270" >}}

You'll get:

20230719-110454

jmooring commented 1 year ago

Please share Portrait_0.jpg and Portrait_6.jpg

It looks like the sample images are from https://github.com/recurser/exif-orientation-examples.

The reported problem:

  1. Affects both the .Crop and .Fill methods.
  2. Affects both landscape and portrait images
  3. Affects 90, 180, and 270 degree rotations[^1].
  4. Is limited to the smart anchor option. Other anchors produce the expected result.

The workaround is to rotate first, then crop or fill. Currently you cannot rotate without specifying a method, so you must use .Resize with the image's final dimensions. That means that you must reverse height and width when rotating by 90 or 270 degrees (see rotation examples).

Workaround ```text {{ with .Resize (printf "%dx%d r0" .Width .Height) }} {{ with .Fill "200x200 smart" }} {{ end }} {{ end }} {{ with .Resize (printf "%dx%d r90" .Height .Width) }} <-- dimensions reversed {{ with .Fill "200x200 smart" }} {{ end }} {{ end }} {{ with .Resize (printf "%dx%d r180" .Width .Height) }} {{ with .Fill "200x200 smart" }} {{ end }} {{ end }} {{ with .Resize (printf "%dx%d r270" .Height .Width) }} <-- dimensions reversed {{ with .Fill "200x200 smart" }} {{ end }} {{ end }} ```


The test site below processes all images from github.com/recurser/exif-orientation-examples. The first group uses the "rotate and fill" method (FAIL), while the second group uses the "rotate then fill" method (PASS). Each image is rendered with 0, 90, 180, and 270 rotation.

git clone --single-branch -b hugo-github-issue-11266 https://github.com/jmooring/hugo-testing hugo-github-issue-11266
cd hugo-github-issue-11266
hugo server

[^1]: And probably every rotation value except zero (e.g., 42), but I don't think we care too much about rotations that are not a multiple of 90.

eiszfuchs commented 1 year ago

Thank you a lot, @jmooring, for the detailed look into it and the workaround!

I will probably use it for the time being, but it adds a lot to the build time, especially with lots of photos, so I hope rotating images can be less complicated in the near future. Working around image processing soon is half of my theme's code. :sweat_smile:

github-actions[bot] commented 4 months ago

This issue has been automatically marked as stale because it has not had recent activity. The resources of the Hugo team are limited, and so we are asking for your help. If this is a bug and you can still reproduce this error on the master branch, please reply with all of the information you have about it in order to keep the issue open. If this is a feature request, and you feel that it is still relevant and valuable, please tell us why. This issue will automatically be closed in the near future if no further activity occurs. Thank you for all your contributions.