Skip to content

Commit

Permalink
Add webp image encoding support
Browse files Browse the repository at this point in the history
  • Loading branch information
bep committed Apr 10, 2021
1 parent 9b83f45 commit c73ba3b
Show file tree
Hide file tree
Showing 12 changed files with 138 additions and 4 deletions.
6 changes: 5 additions & 1 deletion common/hugo/hugo.go
Expand Up @@ -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()
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Expand Up @@ -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.0.0-20210410161412-b86a3337b39f
github.com/bep/tmc v0.5.1
github.com/cli/safeexec v1.0.0
github.com/disintegration/gift v1.2.1
Expand Down Expand Up @@ -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-20201224014010-6772e930b67b
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a
golang.org/x/text v0.3.4
Expand Down
10 changes: 10 additions & 0 deletions go.sum
Expand Up @@ -161,6 +161,14 @@ 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/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 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
Expand Down Expand Up @@ -712,6 +720,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=
Expand Down
2 changes: 2 additions & 0 deletions media/mediaType.go
Expand Up @@ -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"})
Expand Down Expand Up @@ -214,6 +215,7 @@ var DefaultTypes = Types{
TOMLType,
PNGType,
JPEGType,
WEBPType,
AVIType,
MPEGType,
MP4Type,
Expand Down
2 changes: 1 addition & 1 deletion media/mediaType_test.go
Expand Up @@ -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) {
Expand Down
41 changes: 41 additions & 0 deletions 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_linear.webp")
c.Assert(resized.Width(), qt.Equals, 123)
}
3 changes: 2 additions & 1 deletion resources/images/config.go
Expand Up @@ -40,6 +40,7 @@ var (
".tiff": TIFF,
".bmp": BMP,
".gif": GIF,
".webp": WEBP,
}

// Add or increment if changes to an image format's processing requires
Expand Down Expand Up @@ -244,7 +245,7 @@ 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

Expand Down
15 changes: 15 additions & 0 deletions resources/images/image.go
Expand Up @@ -23,6 +23,9 @@ import (
"io"
"sync"

"github.com/bep/gowebp/libwebp/options"
"github.com/gohugoio/hugo/resources/images/webp"

"github.com/gohugoio/hugo/media"
"github.com/gohugoio/hugo/resources/images/exif"

Expand Down Expand Up @@ -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, options.EncodingOptions{
Quality: conf.Quality,
EncodingPreset: options.PresetPhoto,
UseSharpYuv: true,
},
)
default:
return errors.New("format not supported")
}
Expand Down Expand Up @@ -250,6 +262,7 @@ const (
GIF
TIFF
BMP
WEBP
)

// RequiresDefaultQuality returns if the default quality needs to be applied to images of this format
Expand Down Expand Up @@ -281,6 +294,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))
}
Expand Down
30 changes: 30 additions & 0 deletions 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/options"
)

// Encode writes the Image m to w in Webp format with the given
// options.
func Encode(w io.Writer, m image.Image, o options.EncodingOptions) error {
return libwebp.Encode(w, m, o)
}
30 changes: 30 additions & 0 deletions 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/options"
)

// Encode is only available in the extended version.
func Encode(w io.Writer, m image.Image, o options.EncodingOptions) error {
return herrors.ErrFeatureNotAvailable
}
Binary file added resources/testdata/col2.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/testdata/sunset.webp
Binary file not shown.

0 comments on commit c73ba3b

Please sign in to comment.