summaryrefslogtreecommitdiffstats
path: root/resources
diff options
context:
space:
mode:
authorJoe Mooring <joe.mooring@veriphor.com>2023-12-15 12:04:05 -0800
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2023-12-20 14:18:24 +0100
commit648d00c7d8243d71e33c33e99a6e4f509beddf98 (patch)
tree31e27c902b91101e1273efc4bedd654b2e233a61 /resources
parent8adba648cc130a97d2c814c65aa8396044c251fd (diff)
resources/images: Create AutoOrient image filter
Closes #11717
Diffstat (limited to 'resources')
-rw-r--r--resources/image.go16
-rw-r--r--resources/images/auto_orient.go60
-rw-r--r--resources/images/filters.go8
3 files changed, 78 insertions, 6 deletions
diff --git a/resources/image.go b/resources/image.go
index cb0181a5f..6c34795f8 100644
--- a/resources/image.go
+++ b/resources/image.go
@@ -279,8 +279,8 @@ func (i *imageResource) Filter(filters ...any) (images.ImageResource, error) {
}
return i.doWithImageConfig(conf, func(src image.Image) (image.Image, error) {
- filters := gfilters
- for j, f := range gfilters {
+ var filters []gift.Filter
+ for _, f := range gfilters {
f = images.UnwrapFilter(f)
if specProvider, ok := f.(images.ImageProcessSpecProvider); ok {
processSpec := specProvider.ImageProcessSpec()
@@ -293,10 +293,14 @@ func (i *imageResource) Filter(filters ...any) (images.ImageResource, error) {
if err != nil {
return nil, err
}
- // Replace the filter with the new filters.
- // This slice will be empty if this is just a format conversion.
- filters = append(filters[:j], append(pFilters, filters[j+1:]...)...)
-
+ filters = append(filters, pFilters...)
+ } else if orientationProvider, ok := f.(images.ImageFilterFromOrientationProvider); ok {
+ tf := orientationProvider.AutoOrient(i.Exif())
+ if tf != nil {
+ filters = append(filters, tf)
+ }
+ } else {
+ filters = append(filters, f)
}
}
return i.Proc.Filter(src, filters...)
diff --git a/resources/images/auto_orient.go b/resources/images/auto_orient.go
new file mode 100644
index 000000000..194efefb5
--- /dev/null
+++ b/resources/images/auto_orient.go
@@ -0,0 +1,60 @@
+// Copyright 2023 The Hugo Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package images
+
+import (
+ "image"
+ "image/draw"
+
+ "github.com/disintegration/gift"
+ "github.com/gohugoio/hugo/resources/images/exif"
+)
+
+var _ gift.Filter = (*autoOrientFilter)(nil)
+
+var transformationFilters = map[int]gift.Filter{
+ 2: gift.FlipHorizontal(),
+ 3: gift.Rotate180(),
+ 4: gift.FlipVertical(),
+ 5: gift.Transpose(),
+ 6: gift.Rotate270(),
+ 7: gift.Transverse(),
+ 8: gift.Rotate90(),
+}
+
+type autoOrientFilter struct{}
+
+type ImageFilterFromOrientationProvider interface {
+ AutoOrient(exifInfo *exif.ExifInfo) gift.Filter
+}
+
+func (f autoOrientFilter) Draw(dst draw.Image, src image.Image, options *gift.Options) {
+ panic("not supported")
+}
+
+func (f autoOrientFilter) Bounds(srcBounds image.Rectangle) image.Rectangle {
+ panic("not supported")
+}
+
+func (f autoOrientFilter) AutoOrient(exifInfo *exif.ExifInfo) gift.Filter {
+ if exifInfo != nil {
+ if orientation, ok := exifInfo.Tags["Orientation"].(int); ok {
+ if filter, ok := transformationFilters[orientation]; ok {
+ return filter
+ }
+ }
+ }
+
+ return nil
+}
diff --git a/resources/images/filters.go b/resources/images/filters.go
index 2a1f41a03..572a10d71 100644
--- a/resources/images/filters.go
+++ b/resources/images/filters.go
@@ -174,6 +174,14 @@ func (*Filters) Padding(args ...any) gift.Filter {
}
}
+// AutoOrient creates a filter that rotates and flips an image as needed per
+// its EXIF orientation tag.
+func (*Filters) AutoOrient() gift.Filter {
+ return filter{
+ Filter: autoOrientFilter{},
+ }
+}
+
// Brightness creates a filter that changes the brightness of an image.
// The percentage parameter must be in range (-100, 100).
func (*Filters) Brightness(percentage any) gift.Filter {