From 33d5f805923eb50dfb309d024f6555c59a339846 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Wed, 7 Apr 2021 16:49:34 +0200 Subject: [PATCH] Add webp image encoding support Fixes #5924 --- common/hugo/hugo.go | 6 +- .../image-processing/index.md | 25 +- go.mod | 3 +- go.sum | 16 ++ hugolib/image_test.go | 4 +- media/mediaType.go | 2 + media/mediaType_test.go | 2 +- resources/image.go | 28 +-- resources/image_extended_test.go | 41 ++++ resources/images/config.go | 216 ++++++++++++------ resources/images/config_test.go | 33 ++- resources/images/image.go | 25 +- resources/images/webp/webp.go | 30 +++ resources/images/webp/webp_notavailable.go | 30 +++ resources/testdata/sunset.webp | Bin 0 -> 59826 bytes 15 files changed, 344 insertions(+), 117 deletions(-) create mode 100644 resources/image_extended_test.go create mode 100644 resources/images/webp/webp.go create mode 100644 resources/images/webp/webp_notavailable.go create mode 100644 resources/testdata/sunset.webp diff --git a/common/hugo/hugo.go b/common/hugo/hugo.go index 6e94a8a3..d8d1c7c1 100644 --- a/common/hugo/hugo.go +++ b/common/hugo/hugo.go @@ -120,7 +120,11 @@ func GetDependencyList() []string { } if IsExtended { - deps = append(deps, formatDep("github.com/sass/libsass", "3.6.4")) + deps = append( + deps, + formatDep("github.com/sass/libsass", "3.6.4"), + formatDep("github.com/webmproject/libwebp", "v1.2.0"), + ) } bi, ok := debug.ReadBuildInfo() diff --git a/docs/content/en/content-management/image-processing/index.md b/docs/content/en/content-management/image-processing/index.md index a432b985..8cd00210 100644 --- a/docs/content/en/content-management/image-processing/index.md +++ b/docs/content/en/content-management/image-processing/index.md @@ -167,14 +167,28 @@ For color codes, see https://www.google.com/search?q=color+picker **Note** that you also set a default background color to use, see [Image Processing Config](#image-processing-config). -### JPEG Quality +### JPEG and Webp Quality -Only relevant for JPEG images, values 1 to 100 inclusive, higher is better. Default is 75. +Only relevant for JPEG and Webp images, values 1 to 100 inclusive, higher is better. Default is 75. ```go {{ $image.Resize "600x q50" }} ``` +{{< new-in "0.83.0" >}} Webp support was added in Hugo 0.83.0. + +### Hint {{< new-in "0.83.0" >}} + +Hint about what type of image this is. Currently only used when encoding to Webp. + +Default value is `photo`. + +Valid values are `picture`, `photo`, `drawing`, `icon`, or `text`. + +```go +{{ $image.Resize "600x webp drawing" }} +``` + ### Rotate Rotates an image by the given angle counter-clockwise. The rotation will be performed first to get the dimensions correct. The main use of this is to be able to manually correct for [EXIF orientation](https://github.com/golang/go/issues/4341) of JPEG images. @@ -258,9 +272,14 @@ You can configure an `imaging` section in `config.toml` with default image proce # See https://github.com/disintegration/imaging resampleFilter = "box" -# Default JPEG quality setting. Default is 75. +# Default JPEG or WEBP quality setting. Default is 75. quality = 75 +# Default hint about what type of image. Currently only used for Webp encoding. +# Default is "photo". +# Valid values are "picture", "photo", "drawing", "icon", or "text". +hint = "photo" + # Anchor used when cropping pictures. # Default is "smart" which does Smart Cropping, using https://github.com/muesli/smartcrop # Smart Cropping is content aware and tries to find the best crop for each image. diff --git a/go.mod b/go.mod index 781b53c1..187842a8 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/bep/gitmap v1.1.2 github.com/bep/godartsass v0.12.0 github.com/bep/golibsass v0.7.0 + github.com/bep/gowebp v0.1.0 // indirect github.com/bep/tmc v0.5.1 github.com/cli/safeexec v1.0.0 github.com/disintegration/gift v1.2.1 @@ -59,7 +60,7 @@ require ( github.com/yuin/goldmark v1.3.2 github.com/yuin/goldmark-highlighting v0.0.0-20200307114337-60d527fdb691 gocloud.dev v0.20.0 - golang.org/x/image v0.0.0-20191214001246-9130b4cfad52 + golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/text v0.3.5 diff --git a/go.sum b/go.sum index a1998443..d2b71844 100644 --- a/go.sum +++ b/go.sum @@ -134,6 +134,20 @@ github.com/bep/godartsass v0.12.0 h1:VvGLA4XpXUjKvp53SI05YFLhRFJ78G+Ybnlaz6Oul7E github.com/bep/godartsass v0.12.0/go.mod h1:nXQlHHk4H1ghUk6n/JkYKG5RD43yJfcfp5aHRqT/pc4= github.com/bep/golibsass v0.7.0 h1:/ocxgtPZ5rgp7FA+mktzyent+fAg82tJq4iMsTMBAtA= github.com/bep/golibsass v0.7.0/go.mod h1:DL87K8Un/+pWUS75ggYv41bliGiolxzDKWJAq3eJ1MA= +github.com/bep/gowebp v0.0.0-20210408171434-03ecbe0b5d53 h1:bTIhFx2ZEAZD74LwuVdrdZ4070bE9UE5oR5NTBYLtVs= +github.com/bep/gowebp v0.0.0-20210408171434-03ecbe0b5d53/go.mod h1:ZhFodwdiFp8ehGJpF4LdPl6unxZm9lLFjxD3z2h2AgI= +github.com/bep/gowebp v0.0.0-20210409123354-5e38121e4f6b h1:LLrQFlG0VSxmyz3izTUQnPOGf7Mjiy7wlEu2sDLA+qg= +github.com/bep/gowebp v0.0.0-20210409123354-5e38121e4f6b/go.mod h1:ZhFodwdiFp8ehGJpF4LdPl6unxZm9lLFjxD3z2h2AgI= +github.com/bep/gowebp v0.0.0-20210410152255-50a32861b5a2 h1:uEpPD0fLZs5IjgF/96LqWHUNY9Pr/0KqLWIQ4gJnYhY= +github.com/bep/gowebp v0.0.0-20210410152255-50a32861b5a2/go.mod h1:ZhFodwdiFp8ehGJpF4LdPl6unxZm9lLFjxD3z2h2AgI= +github.com/bep/gowebp v0.0.0-20210410161412-b86a3337b39f h1:hvhG2nwoIvHhFnL8GnYtOquHE6dG+mHwthugLqf4spY= +github.com/bep/gowebp v0.0.0-20210410161412-b86a3337b39f/go.mod h1:ZhFodwdiFp8ehGJpF4LdPl6unxZm9lLFjxD3z2h2AgI= +github.com/bep/gowebp v0.0.0-20210411110227-3a211f6b6461 h1:5HLIo8LF4iKFdxPBDo9CO8oTac18mAx7FJsQG6MNbCU= +github.com/bep/gowebp v0.0.0-20210411110227-3a211f6b6461/go.mod h1:ZhFodwdiFp8ehGJpF4LdPl6unxZm9lLFjxD3z2h2AgI= +github.com/bep/gowebp v0.0.0-20210411155607-38d8f20d562b h1:VIW6UmIG4ogbswbDFBjVm6/7j9I5i0GouDJ2USn/NUI= +github.com/bep/gowebp v0.0.0-20210411155607-38d8f20d562b/go.mod h1:ZhFodwdiFp8ehGJpF4LdPl6unxZm9lLFjxD3z2h2AgI= +github.com/bep/gowebp v0.1.0 h1:4/iQpfnxHyXs3x/aTxMMdOpLEQQhFmF6G7EieWPTQyo= +github.com/bep/gowebp v0.1.0/go.mod h1:ZhFodwdiFp8ehGJpF4LdPl6unxZm9lLFjxD3z2h2AgI= github.com/bep/tmc v0.5.1 h1:CsQnSC6MsomH64gw0cT5f+EwQDcvZz4AazKunFwTpuI= github.com/bep/tmc v0.5.1/go.mod h1:tGYHN8fS85aJPhDLgXETVKp+PR382OvFi2+q2GkGsq0= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= @@ -566,6 +580,8 @@ golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMx golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20191214001246-9130b4cfad52 h1:2fktqPPvDiVEEVT/vSTeoUPXfmRxRaGy6GU8jypvEn0= golang.org/x/image v0.0.0-20191214001246-9130b4cfad52/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb h1:fqpd0EBDzlHRCjiphRR5Zo/RSWWQlWv34418dnEixWk= +golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= diff --git a/hugolib/image_test.go b/hugolib/image_test.go index 1d152046..0dacf2a3 100644 --- a/hugolib/image_test.go +++ b/hugolib/image_test.go @@ -236,10 +236,10 @@ SUNSET2: {{ $resized2.RelPermalink }}/{{ $resized2.Width }}/Lat: {{ $resized2.Ex // Check the file cache b.AssertImage(200, 200, "resources/_gen/images/bundle/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_200x200_resize_q75_box.jpg") - b.AssertFileContent("resources/_gen/images/bundle/sunset_7645215769587362592.json", + b.AssertFileContent("resources/_gen/images/bundle/sunset_3166614710256882113.json", "DateTimeDigitized|time.Time", "PENTAX") b.AssertImage(123, 234, "resources/_gen/images/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_123x234_resize_q75_box.jpg") - b.AssertFileContent("resources/_gen/images/sunset_7645215769587362592.json", + b.AssertFileContent("resources/_gen/images/sunset_3166614710256882113.json", "DateTimeDigitized|time.Time", "PENTAX") // TODO(bep) add this as a default assertion after Build()? diff --git a/media/mediaType.go b/media/mediaType.go index a35d80e3..164ad5fd 100644 --- a/media/mediaType.go +++ b/media/mediaType.go @@ -180,6 +180,7 @@ var ( GIFType = newMediaType("image", "gif", []string{"gif"}) TIFFType = newMediaType("image", "tiff", []string{"tif", "tiff"}) BMPType = newMediaType("image", "bmp", []string{"bmp"}) + WEBPType = newMediaType("image", "webp", []string{"webp"}) // Common video types AVIType = newMediaType("video", "x-msvideo", []string{"avi"}) @@ -214,6 +215,7 @@ var DefaultTypes = Types{ TOMLType, PNGType, JPEGType, + WEBPType, AVIType, MPEGType, MP4Type, diff --git a/media/mediaType_test.go b/media/mediaType_test.go index e44ab27e..6bc42b3d 100644 --- a/media/mediaType_test.go +++ b/media/mediaType_test.go @@ -55,7 +55,7 @@ func TestDefaultTypes(t *testing.T) { } - c.Assert(len(DefaultTypes), qt.Equals, 26) + c.Assert(len(DefaultTypes), qt.Equals, 27) } func TestGetByType(t *testing.T) { diff --git a/resources/image.go b/resources/image.go index 0396c220..edf05639 100644 --- a/resources/image.go +++ b/resources/image.go @@ -207,7 +207,7 @@ func (i *imageResource) Fill(spec string) (resource.Image, error) { } func (i *imageResource) Filter(filters ...interface{}) (resource.Image, error) { - conf := i.Proc.GetDefaultImageConfig("filter") + conf := images.GetDefaultImageConfig("filter", i.Proc.Cfg) var gfilters []gift.Filter @@ -299,28 +299,11 @@ func (i *imageResource) doWithImageConfig(conf images.ImageConfig, f func(src im } func (i *imageResource) decodeImageConfig(action, spec string) (images.ImageConfig, error) { - conf, err := images.DecodeImageConfig(action, spec, i.Proc.Cfg.Cfg) + conf, err := images.DecodeImageConfig(action, spec, i.Proc.Cfg, i.Format) if err != nil { return conf, err } - // default to the source format - if conf.TargetFormat == 0 { - conf.TargetFormat = i.Format - } - - if conf.Quality <= 0 && conf.TargetFormat.RequiresDefaultQuality() { - // We need a quality setting for all JPEGs - conf.Quality = i.Proc.Cfg.Cfg.Quality - } - - if conf.BgColor == nil && conf.TargetFormat != i.Format { - if i.Format.SupportsTransparency() && !conf.TargetFormat.SupportsTransparency() { - conf.BgColor = i.Proc.Cfg.BgColor - conf.BgColorStr = i.Proc.Cfg.Cfg.BgColor - } - } - return conf, nil } @@ -360,15 +343,16 @@ func (i *imageResource) setBasePath(conf images.ImageConfig) { func (i *imageResource) getImageMetaCacheTargetPath() string { const imageMetaVersionNumber = 1 // Increment to invalidate the meta cache - cfg := i.getSpec().imaging.Cfg.Cfg + cfgHash := i.getSpec().imaging.Cfg.CfgHash df := i.getResourcePaths().relTargetDirFile if fi := i.getFileInfo(); fi != nil { df.dir = filepath.Dir(fi.Meta().Path()) } p1, _ := helpers.FileAndExt(df.file) h, _ := i.hash() - idStr := helpers.HashString(h, i.size(), imageMetaVersionNumber, cfg) - return path.Join(df.dir, fmt.Sprintf("%s_%s.json", p1, idStr)) + idStr := helpers.HashString(h, i.size(), imageMetaVersionNumber, cfgHash) + p := path.Join(df.dir, fmt.Sprintf("%s_%s.json", p1, idStr)) + return p } func (i *imageResource) relTargetPathFromConfig(conf images.ImageConfig) dirFile { diff --git a/resources/image_extended_test.go b/resources/image_extended_test.go new file mode 100644 index 00000000..9fd9304d --- /dev/null +++ b/resources/image_extended_test.go @@ -0,0 +1,41 @@ +// Copyright 2019 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. + +// +build extended + +package resources + +import ( + "testing" + + "github.com/gohugoio/hugo/media" + + qt "github.com/frankban/quicktest" +) + +func TestImageResizeWebP(t *testing.T) { + c := qt.New(t) + + image := fetchImage(c, "sunset.webp") + + c.Assert(image.MediaType(), qt.Equals, media.WEBPType) + c.Assert(image.RelPermalink(), qt.Equals, "/a/sunset.webp") + c.Assert(image.ResourceType(), qt.Equals, "image") + c.Assert(image.Exif(), qt.IsNil) + + resized, err := image.Resize("123x") + c.Assert(err, qt.IsNil) + c.Assert(image.MediaType(), qt.Equals, media.WEBPType) + c.Assert(resized.RelPermalink(), qt.Equals, "/a/sunset_hu36ee0b61ba924719ad36da960c273f96_59826_123x0_resize_q68_h2_linear.webp") + c.Assert(resized.Width(), qt.Equals, 123) +} diff --git a/resources/images/config.go b/resources/images/config.go index 7b2ade29..a4942688 100644 --- a/resources/images/config.go +++ b/resources/images/config.go @@ -14,23 +14,22 @@ package images import ( - "errors" "fmt" "image/color" "strconv" "strings" + "github.com/gohugoio/hugo/helpers" + + "github.com/pkg/errors" + + "github.com/bep/gowebp/libwebp/webpoptions" + "github.com/disintegration/gift" "github.com/mitchellh/mapstructure" ) -const ( - defaultJPEGQuality = 75 - defaultResampleFilter = "box" - defaultBgColor = "ffffff" -) - var ( imageFormats = map[string]Format{ ".jpg": JPEG, @@ -40,6 +39,7 @@ var ( ".tiff": TIFF, ".bmp": BMP, ".gif": GIF, + ".webp": WEBP, } // Add or increment if changes to an image format's processing requires @@ -65,6 +65,15 @@ var anchorPositions = map[string]gift.Anchor{ strings.ToLower("BottomRight"): gift.BottomRightAnchor, } +// These encoding hints are currently only relevant for Webp. +var hints = map[string]webpoptions.EncodingPreset{ + "picture": webpoptions.EncodingPresetPicture, + "photo": webpoptions.EncodingPresetPhoto, + "drawing": webpoptions.EncodingPresetDrawing, + "icon": webpoptions.EncodingPresetIcon, + "text": webpoptions.EncodingPresetText, +} + var imageFilters = map[string]gift.Resampling{ strings.ToLower("NearestNeighbor"): gift.NearestNeighborResampling, @@ -89,63 +98,71 @@ func ImageFormatFromExt(ext string) (Format, bool) { return f, found } -func DecodeConfig(m map[string]interface{}) (ImagingConfig, error) { - var i Imaging - var ic ImagingConfig - if err := mapstructure.WeakDecode(m, &i); err != nil { - return ic, err - } +const ( + defaultJPEGQuality = 75 + defaultResampleFilter = "box" + defaultBgColor = "ffffff" + defaultHint = "photo" +) - if i.Quality == 0 { - i.Quality = defaultJPEGQuality - } else if i.Quality < 0 || i.Quality > 100 { - return ic, errors.New("JPEG quality must be a number between 1 and 100") - } - - if i.BgColor != "" { - i.BgColor = strings.TrimPrefix(i.BgColor, "#") - } else { - i.BgColor = defaultBgColor - } - var err error - ic.BgColor, err = hexStringToColor(i.BgColor) - if err != nil { - return ic, err - } - - if i.Anchor == "" || strings.EqualFold(i.Anchor, smartCropIdentifier) { - i.Anchor = smartCropIdentifier - } else { - i.Anchor = strings.ToLower(i.Anchor) - if _, found := anchorPositions[i.Anchor]; !found { - return ic, errors.New("invalid anchor value in imaging config") - } - } - - if i.ResampleFilter == "" { - i.ResampleFilter = defaultResampleFilter - } else { - filter := strings.ToLower(i.ResampleFilter) - _, found := imageFilters[filter] - if !found { - return ic, fmt.Errorf("%q is not a valid resample filter", filter) - } - i.ResampleFilter = filter - } - - if strings.TrimSpace(i.Exif.IncludeFields) == "" && strings.TrimSpace(i.Exif.ExcludeFields) == "" { - // Don't change this for no good reason. Please don't. - i.Exif.ExcludeFields = "GPS|Exif|Exposure[M|P|B]|Contrast|Resolution|Sharp|JPEG|Metering|Sensing|Saturation|ColorSpace|Flash|WhiteBalance" - } - - ic.Cfg = i - - return ic, nil +var defaultImaging = Imaging{ + ResampleFilter: defaultResampleFilter, + BgColor: defaultBgColor, + Hint: defaultHint, + Quality: defaultJPEGQuality, } -func DecodeImageConfig(action, config string, defaults Imaging) (ImageConfig, error) { +func DecodeConfig(m map[string]interface{}) (ImagingConfig, error) { + if m == nil { + m = make(map[string]interface{}) + } + + i := ImagingConfig{ + Cfg: defaultImaging, + CfgHash: helpers.HashString(m), + } + + if err := mapstructure.WeakDecode(m, &i.Cfg); err != nil { + return i, err + } + + if err := i.Cfg.init(); err != nil { + return i, err + } + + var err error + i.BgColor, err = hexStringToColor(i.Cfg.BgColor) + if err != nil { + return i, err + } + + if i.Cfg.Anchor != "" && i.Cfg.Anchor != smartCropIdentifier { + anchor, found := anchorPositions[i.Cfg.Anchor] + if !found { + return i, errors.Errorf("invalid anchor value %q in imaging config", i.Anchor) + } + i.Anchor = anchor + } else { + i.Cfg.Anchor = smartCropIdentifier + } + + filter, found := imageFilters[i.Cfg.ResampleFilter] + if !found { + return i, fmt.Errorf("%q is not a valid resample filter", filter) + } + i.ResampleFilter = filter + + if strings.TrimSpace(i.Cfg.Exif.IncludeFields) == "" && strings.TrimSpace(i.Cfg.Exif.ExcludeFields) == "" { + // Don't change this for no good reason. Please don't. + i.Cfg.Exif.ExcludeFields = "GPS|Exif|Exposure[M|P|B]|Contrast|Resolution|Sharp|JPEG|Metering|Sensing|Saturation|ColorSpace|Flash|WhiteBalance" + } + + return i, nil +} + +func DecodeImageConfig(action, config string, defaults ImagingConfig, sourceFormat Format) (ImageConfig, error) { var ( - c ImageConfig + c ImageConfig = GetDefaultImageConfig(action, defaults) err error ) @@ -167,6 +184,8 @@ func DecodeImageConfig(action, config string, defaults Imaging) (ImageConfig, er } else if filter, ok := imageFilters[part]; ok { c.Filter = filter c.FilterStr = part + } else if hint, ok := hints[part]; ok { + c.Hint = hint } else if part[0] == '#' { c.BgColorStr = part[1:] c.BgColor, err = hexStringToColor(c.BgColorStr) @@ -181,6 +200,7 @@ func DecodeImageConfig(action, config string, defaults Imaging) (ImageConfig, er if c.Quality < 1 || c.Quality > 100 { return c, errors.New("quality ranges from 1 to 100 inclusive") } + c.qualitySetForImage = true } else if part[0] == 'r' { c.Rotate, err = strconv.Atoi(part[1:]) if err != nil { @@ -219,14 +239,33 @@ func DecodeImageConfig(action, config string, defaults Imaging) (ImageConfig, er } if c.FilterStr == "" { - c.FilterStr = defaults.ResampleFilter - c.Filter = imageFilters[c.FilterStr] + c.FilterStr = defaults.Cfg.ResampleFilter + c.Filter = defaults.ResampleFilter + } + + if c.Hint == 0 { + c.Hint = webpoptions.EncodingPresetPhoto } if c.AnchorStr == "" { - c.AnchorStr = defaults.Anchor - if !strings.EqualFold(c.AnchorStr, smartCropIdentifier) { - c.Anchor = anchorPositions[c.AnchorStr] + c.AnchorStr = defaults.Cfg.Anchor + c.Anchor = defaults.Anchor + } + + // default to the source format + if c.TargetFormat == 0 { + c.TargetFormat = sourceFormat + } + + if c.Quality <= 0 && c.TargetFormat.RequiresDefaultQuality() { + // We need a quality setting for all JPEGs and WEBPs. + c.Quality = defaults.Cfg.Quality + } + + if c.BgColor == nil && c.TargetFormat != sourceFormat { + if sourceFormat.SupportsTransparency() && !c.TargetFormat.SupportsTransparency() { + c.BgColor = defaults.BgColor + c.BgColorStr = defaults.Cfg.BgColor } } @@ -235,7 +274,7 @@ func DecodeImageConfig(action, config string, defaults Imaging) (ImageConfig, er // ImageConfig holds configuration to create a new image from an existing one, resize etc. type ImageConfig struct { - // This defines the output format of the output image. It defaults to the source format + // This defines the output format of the output image. It defaults to the source format. TargetFormat Format Action string @@ -244,9 +283,10 @@ type ImageConfig struct { Key string // Quality ranges from 1 to 100 inclusive, higher is better. - // This is only relevant for JPEG images. + // This is only relevant for JPEG and WEBP images. // Default is 75. - Quality int + Quality int + qualitySetForImage bool // Whether the above is set for this image. // Rotate rotates an image by the given angle counter-clockwise. // The rotation will be performed first. @@ -260,6 +300,10 @@ type ImageConfig struct { BgColor color.Color BgColorStr string + // Hint about what type of picture this is. Used to optimize encoding + // when target is set to webp. + Hint webpoptions.EncodingPreset + Width int Height int @@ -279,7 +323,8 @@ func (i ImageConfig) GetKey(format Format) string { if i.Action != "" { k += "_" + i.Action } - if i.Quality > 0 { + // This slightly odd construct is here to preserve the old image keys. + if i.qualitySetForImage || i.TargetFormat.RequiresDefaultQuality() { k += "_q" + strconv.Itoa(i.Quality) } if i.Rotate != 0 { @@ -289,6 +334,10 @@ func (i ImageConfig) GetKey(format Format) string { k += "_bg" + i.BgColorStr } + if i.TargetFormat == WEBP { + k += "_h" + strconv.Itoa(int(i.Hint)) + } + anchor := i.AnchorStr if anchor == smartCropIdentifier { anchor = anchor + strconv.Itoa(smartCropVersionNumber) @@ -312,10 +361,16 @@ func (i ImageConfig) GetKey(format Format) string { } type ImagingConfig struct { - BgColor color.Color + BgColor color.Color + Hint webpoptions.EncodingPreset + ResampleFilter gift.Resampling + Anchor gift.Anchor // Config as provided by the user. Cfg Imaging + + // Hash of the config map provided by the user. + CfgHash string } // Imaging contains default image processing configuration. This will be fetched @@ -324,9 +379,15 @@ type Imaging struct { // Default image quality setting (1-100). Only used for JPEG images. Quality int - // Resample filter to use in resize operations.. + // Resample filter to use in resize operations. ResampleFilter string + // Hint about what type of image this is. + // Currently only used when encoding to Webp. + // Default is "photo". + // Valid values are "picture", "photo", "drawing", "icon", or "text". + Hint string + // The anchor to use in Fill. Default is "smart", i.e. Smart Crop. Anchor string @@ -336,6 +397,19 @@ type Imaging struct { Exif ExifConfig } +func (cfg *Imaging) init() error { + if cfg.Quality < 0 || cfg.Quality > 100 { + return errors.New("image quality must be a number between 1 and 100") + } + + cfg.BgColor = strings.ToLower(strings.TrimPrefix(cfg.BgColor, "#")) + cfg.Anchor = strings.ToLower(cfg.Anchor) + cfg.ResampleFilter = strings.ToLower(cfg.ResampleFilter) + cfg.Hint = strings.ToLower(cfg.Hint) + + return nil +} + type ExifConfig struct { // Regexp matching the Exif fields you want from the (massive) set of Exif info diff --git a/resources/images/config_test.go b/resources/images/config_test.go index 2a0de9ec..7b245925 100644 --- a/resources/images/config_test.go +++ b/resources/images/config_test.go @@ -42,7 +42,6 @@ func TestDecodeConfig(t *testing.T) { imagingConfig, err = DecodeConfig(m) c.Assert(err, qt.IsNil) imaging = imagingConfig.Cfg - c.Assert(imaging.Quality, qt.Equals, defaultJPEGQuality) c.Assert(imaging.ResampleFilter, qt.Equals, "box") c.Assert(imaging.Anchor, qt.Equals, "smart") @@ -84,18 +83,22 @@ func TestDecodeImageConfig(t *testing.T) { in string expect interface{} }{ - {"300x400", newImageConfig(300, 400, 0, 0, "", "", "")}, - {"300x400 #fff", newImageConfig(300, 400, 0, 0, "", "", "fff")}, - {"100x200 bottomRight", newImageConfig(100, 200, 0, 0, "", "BottomRight", "")}, - {"10x20 topleft Lanczos", newImageConfig(10, 20, 0, 0, "Lanczos", "topleft", "")}, - {"linear left 10x r180", newImageConfig(10, 0, 0, 180, "linear", "left", "")}, + {"300x400", newImageConfig(300, 400, 75, 0, "box", "smart", "")}, + {"300x400 #fff", newImageConfig(300, 400, 75, 0, "box", "smart", "fff")}, + {"100x200 bottomRight", newImageConfig(100, 200, 75, 0, "box", "BottomRight", "")}, + {"10x20 topleft Lanczos", newImageConfig(10, 20, 75, 0, "Lanczos", "topleft", "")}, + {"linear left 10x r180", newImageConfig(10, 0, 75, 180, "linear", "left", "")}, {"x20 riGht Cosine q95", newImageConfig(0, 20, 95, 0, "cosine", "right", "")}, {"", false}, {"foo", false}, } { - result, err := DecodeImageConfig("resize", this.in, Imaging{}) + cfg, err := DecodeConfig(nil) + if err != nil { + t.Fatal(err) + } + result, err := DecodeImageConfig("resize", this.in, cfg, PNG) if b, ok := this.expect.(bool); ok && !b { if err == nil { t.Errorf("[%d] parseImageConfig didn't return an expected error", i) @@ -112,11 +115,13 @@ func TestDecodeImageConfig(t *testing.T) { } func newImageConfig(width, height, quality, rotate int, filter, anchor, bgColor string) ImageConfig { - var c ImageConfig - c.Action = "resize" + var c ImageConfig = GetDefaultImageConfig("resize", ImagingConfig{}) + c.TargetFormat = PNG + c.Hint = 2 c.Width = width c.Height = height c.Quality = quality + c.qualitySetForImage = quality != 75 c.Rotate = rotate c.BgColorStr = bgColor c.BgColor, _ = hexStringToColor(bgColor) @@ -130,10 +135,14 @@ func newImageConfig(width, height, quality, rotate int, filter, anchor, bgColor } if anchor != "" { - anchor = strings.ToLower(anchor) - if v, ok := anchorPositions[anchor]; ok { - c.Anchor = v + if anchor == smartCropIdentifier { c.AnchorStr = anchor + } else { + anchor = strings.ToLower(anchor) + if v, ok := anchorPositions[anchor]; ok { + c.Anchor = v + c.AnchorStr = anchor + } } } diff --git a/resources/images/image.go b/resources/images/image.go index b7132124..db7d566a 100644 --- a/resources/images/image.go +++ b/resources/images/image.go @@ -23,6 +23,9 @@ import ( "io" "sync" + "github.com/bep/gowebp/libwebp/webpoptions" + "github.com/gohugoio/hugo/resources/images/webp" + "github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/resources/images/exif" @@ -89,6 +92,15 @@ func (i *Image) EncodeTo(conf ImageConfig, img image.Image, w io.Writer) error { case BMP: return bmp.Encode(w, img) + case WEBP: + return webp.Encode( + w, + img, webpoptions.EncodingOptions{ + Quality: conf.Quality, + EncodingPreset: webpoptions.EncodingPreset(conf.Hint), + UseSharpYuv: true, + }, + ) default: return errors.New("format not supported") } @@ -229,10 +241,11 @@ func (p *ImageProcessor) Filter(src image.Image, filters ...gift.Filter) (image. return dst, nil } -func (p *ImageProcessor) GetDefaultImageConfig(action string) ImageConfig { +func GetDefaultImageConfig(action string, defaults ImagingConfig) ImageConfig { return ImageConfig{ Action: action, - Quality: p.Cfg.Cfg.Quality, + Hint: defaults.Hint, + Quality: defaults.Cfg.Quality, } } @@ -250,11 +263,13 @@ const ( GIF TIFF BMP + WEBP ) -// RequiresDefaultQuality returns if the default quality needs to be applied to images of this format +// RequiresDefaultQuality returns if the default quality needs to be applied to +// images of this format. func (f Format) RequiresDefaultQuality() bool { - return f == JPEG + return f == JPEG || f == WEBP } // SupportsTransparency reports whether it supports transparency in any form. @@ -281,6 +296,8 @@ func (f Format) MediaType() media.Type { return media.TIFFType case BMP: return media.BMPType + case WEBP: + return media.WEBPType default: panic(fmt.Sprintf("%d is not a valid image format", f)) } diff --git a/resources/images/webp/webp.go b/resources/images/webp/webp.go new file mode 100644 index 00000000..d7443ff2 --- /dev/null +++ b/resources/images/webp/webp.go @@ -0,0 +1,30 @@ +// Copyright 2021 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. + +// +build extended + +package webp + +import ( + "image" + "io" + + "github.com/bep/gowebp/libwebp" + "github.com/bep/gowebp/libwebp/webpoptions" +) + +// Encode writes the Image m to w in Webp format with the given +// options. +func Encode(w io.Writer, m image.Image, o webpoptions.EncodingOptions) error { + return libwebp.Encode(w, m, o) +} diff --git a/resources/images/webp/webp_notavailable.go b/resources/images/webp/webp_notavailable.go new file mode 100644 index 00000000..4209eb41 --- /dev/null +++ b/resources/images/webp/webp_notavailable.go @@ -0,0 +1,30 @@ +// Copyright 2021 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. + +// +build !extended + +package webp + +import ( + "image" + "io" + + "github.com/gohugoio/hugo/common/herrors" + + "github.com/bep/gowebp/libwebp/webpoptions" +) + +// Encode is only available in the extended version. +func Encode(w io.Writer, m image.Image, o webpoptions.EncodingOptions) error { + return herrors.ErrFeatureNotAvailable +} diff --git a/resources/testdata/sunset.webp b/resources/testdata/sunset.webp new file mode 100644 index 0000000000000000000000000000000000000000..4365e7b9f9aebe06448143d31cab6ce7886bcb91 GIT binary patch literal 59826 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 literal 0 HcmV?d00001