diff options
Diffstat (limited to 'resources')
-rw-r--r-- | resources/image.go | 16 | ||||
-rw-r--r-- | resources/images/auto_orient.go | 60 | ||||
-rw-r--r-- | resources/images/filters.go | 8 |
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 { |