From bb894ceaf8d3655dd14bc63bf4a4557e3a16f530 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Wed, 4 Sep 2019 14:07:10 +0200 Subject: [PATCH] Allow slices in the image Filter funcs, not just varargs [ci skip] See #6255 --- hugolib/image_test.go | 24 ++++++++++++++++++-- resources/image.go | 19 ++++++++++------ resources/image_test.go | 2 +- resources/images/filters_test.go | 34 +++++++++++++++++++++++++++++ resources/images/image.go | 18 +++++++++++++++ resources/resource/resourcetypes.go | 3 +-- resources/transform.go | 3 +-- tpl/images/images.go | 8 +------ 8 files changed, 90 insertions(+), 21 deletions(-) create mode 100644 resources/images/filters_test.go diff --git a/hugolib/image_test.go b/hugolib/image_test.go index 0cd781018..4db57e4a5 100644 --- a/hugolib/image_test.go +++ b/hugolib/image_test.go @@ -28,7 +28,7 @@ import ( // We have many tests for the different resize operations etc. in the resource package, // this is an integration test. -func TestImageResize(t *testing.T) { +func TestImageOps(t *testing.T) { c := qt.New(t) // Make this a real as possible. workDir, clean, err := htesting.CreateTempDir(hugofs.Os, "image-resize") @@ -69,6 +69,22 @@ title: "My bundle" {{ printf "Resized%d:" (add $i 1) }} {{ $r.Name }}|{{ $r.Width }}|{{ $r.Height }}|{{ $r.MediaType }}|{{ $r.RelPermalink }}| {{ end }} +{{ $blurryGrayscale1 := $r | images.Filter images.Grayscale (images.GaussianBlur 8) }} +BG1: {{ $blurryGrayscale1.RelPermalink }}/{{ $blurryGrayscale1.Width }} +{{ $blurryGrayscale2 := $r.Filter images.Grayscale (images.GaussianBlur 8) }} +BG2: {{ $blurryGrayscale2.RelPermalink }}/{{ $blurryGrayscale2.Width }} +{{ $blurryGrayscale2_2 := $r.Filter images.Grayscale (images.GaussianBlur 8) }} +BG2_2: {{ $blurryGrayscale2_2.RelPermalink }}/{{ $blurryGrayscale2_2.Width }} + +{{ $filters := slice images.Grayscale (images.GaussianBlur 9) }} +{{ $blurryGrayscale3 := $r | images.Filter $filters }} +BG3: {{ $blurryGrayscale3.RelPermalink }}/{{ $blurryGrayscale3.Width }} + +{{ $blurryGrayscale4 := $r.Filter $filters }} +BG4: {{ $blurryGrayscale4.RelPermalink }}/{{ $blurryGrayscale4.Width }} + + + `) return b @@ -106,7 +122,10 @@ Resized3: sunset.jpg|345|678|image/jpg|/mybundle/sunset_hu59e56ffff1bc1d8d122b14 Resized4: sunset.jpg|34|67|image/jpg|/mybundle/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_44d8c928664d7c5a67377c6ec58425ce.jpg| Resized5: images/sunset.jpg|456|789|image/jpg|/images/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_456x789_resize_q75_box.jpg| Resized6: images/sunset.jpg|350|219|image/jpg|/images/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_350x0_resize_q75_box.a86fe88d894e5db613f6aa8a80538fefc25b20fa24ba0d782c057adcef616f56.jpg| - +BG1: /images/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_2ae8bb993431ec1aec40fe59927b46b4.jpg/123 +BG2: /images/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_2ae8bb993431ec1aec40fe59927b46b4.jpg/123 +BG3: /images/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_ed7740a90b82802261c2fbdb98bc8082.jpg/123 +BG4: /images/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_ed7740a90b82802261c2fbdb98bc8082.jpg/123 ` b.AssertFileContent(filepath.Join(workDir, "public/index.html"), imgExpect) @@ -171,6 +190,7 @@ No bundle for {{ $.Site.Language.Lang }} {{ $resized2 := $sunset2.Resize "123x234" }} SUNSET2: {{ $resized2.RelPermalink }}/{{ $resized2.Width }}/Lat: {{ $resized2.Exif.Lat }} + `) b.Build(BuildCfg{}) diff --git a/resources/image.go b/resources/image.go index 8a9e6fde4..26b9b8710 100644 --- a/resources/image.go +++ b/resources/image.go @@ -28,6 +28,8 @@ import ( "strings" "sync" + "github.com/disintegration/gift" + "github.com/gohugoio/hugo/cache/filecache" "github.com/gohugoio/hugo/resources/images/exif" @@ -37,7 +39,6 @@ import ( _errors "github.com/pkg/errors" - "github.com/disintegration/gift" "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/resources/images" @@ -209,12 +210,19 @@ func (i *imageResource) Fill(spec string) (resource.Image, error) { }) } -func (i *imageResource) Filter(filters ...gift.Filter) (resource.Image, error) { +func (i *imageResource) Filter(filters ...interface{}) (resource.Image, error) { conf := i.Proc.GetDefaultImageConfig("filter") - conf.Key = internal.HashString(filters) + + var gfilters []gift.Filter + + for _, f := range filters { + gfilters = append(gfilters, images.ToFilters(f)...) + } + + conf.Key = internal.HashString(gfilters) return i.doWithImageConfig(conf, func(src image.Image) (image.Image, error) { - return i.Proc.Filter(src, filters...) + return i.Proc.Filter(src, gfilters...) }) } @@ -331,9 +339,6 @@ func (i *imageResource) getImageMetaCacheTargetPath() string { func (i *imageResource) relTargetPathFromConfig(conf images.ImageConfig) dirFile { p1, p2 := helpers.FileAndExt(i.getResourcePaths().relTargetDirFile.file) - if conf.Action == "trace" { - p2 = ".svg" - } h, _ := i.hash() idStr := fmt.Sprintf("_hu%s_%d", h, i.size()) diff --git a/resources/image_test.go b/resources/image_test.go index 0146e8bdd..59d6b7c9a 100644 --- a/resources/image_test.go +++ b/resources/image_test.go @@ -512,7 +512,7 @@ func TestImageOperationsGolden(t *testing.T) { c.Assert(rel, qt.Not(qt.Equals), "") } - resized, err = resized.Filter(filters[0:4]...) + resized, err = resized.Filter(filters[0:4]) c.Assert(err, qt.IsNil) rel := resized.RelPermalink() c.Log("filter all", rel) diff --git a/resources/images/filters_test.go b/resources/images/filters_test.go new file mode 100644 index 000000000..658a9a427 --- /dev/null +++ b/resources/images/filters_test.go @@ -0,0 +1,34 @@ +// 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. + +package images + +import ( + "testing" + + "github.com/gohugoio/hugo/resources/internal" + + qt "github.com/frankban/quicktest" +) + +func TestFilterHash(t *testing.T) { + c := qt.New(t) + + f := &Filters{} + + c.Assert(internal.HashString(f.Grayscale()), qt.Equals, internal.HashString(f.Grayscale())) + c.Assert(internal.HashString(f.Grayscale()), qt.Not(qt.Equals), internal.HashString(f.Invert())) + c.Assert(internal.HashString(f.Gamma(32)), qt.Not(qt.Equals), internal.HashString(f.Gamma(33))) + c.Assert(internal.HashString(f.Gamma(32)), qt.Equals, internal.HashString(f.Gamma(32))) + +} diff --git a/resources/images/image.go b/resources/images/image.go index aa7d567aa..e72d96837 100644 --- a/resources/images/image.go +++ b/resources/images/image.go @@ -14,6 +14,7 @@ package images import ( + "fmt" "image" "image/color" "image/gif" @@ -259,3 +260,20 @@ func imageConfigFromImage(img image.Image) image.Config { b := img.Bounds() return image.Config{Width: b.Max.X, Height: b.Max.Y} } + +func ToFilters(in interface{}) []gift.Filter { + switch v := in.(type) { + case []gift.Filter: + return v + case []filter: + vv := make([]gift.Filter, len(v)) + for i, f := range v { + vv[i] = f + } + return vv + case gift.Filter: + return []gift.Filter{v} + default: + panic(fmt.Sprintf("%T is not an image filter", in)) + } +} diff --git a/resources/resource/resourcetypes.go b/resources/resource/resourcetypes.go index f6b6d2af1..7a055b25d 100644 --- a/resources/resource/resourcetypes.go +++ b/resources/resource/resourcetypes.go @@ -14,7 +14,6 @@ package resource import ( - "github.com/disintegration/gift" "github.com/gohugoio/hugo/langs" "github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/resources/images/exif" @@ -49,7 +48,7 @@ type ImageOps interface { Fill(spec string) (Image, error) Fit(spec string) (Image, error) Resize(spec string) (Image, error) - Filter(filters ...gift.Filter) (Image, error) + Filter(filters ...interface{}) (Image, error) Exif() (*exif.Exif, error) } diff --git a/resources/transform.go b/resources/transform.go index eb282eab6..1fb3ed4da 100644 --- a/resources/transform.go +++ b/resources/transform.go @@ -21,7 +21,6 @@ import ( "strings" "sync" - "github.com/disintegration/gift" "github.com/gohugoio/hugo/resources/images/exif" "github.com/spf13/afero" @@ -174,7 +173,7 @@ func (r *resourceAdapter) Fit(spec string) (resource.Image, error) { return r.getImageOps().Fit(spec) } -func (r *resourceAdapter) Filter(filters ...gift.Filter) (resource.Image, error) { +func (r *resourceAdapter) Filter(filters ...interface{}) (resource.Image, error) { return r.getImageOps().Filter(filters...) } diff --git a/tpl/images/images.go b/tpl/images/images.go index b64456876..1d12aea72 100644 --- a/tpl/images/images.go +++ b/tpl/images/images.go @@ -18,8 +18,6 @@ import ( "image" "sync" - "github.com/disintegration/gift" - "github.com/pkg/errors" "github.com/gohugoio/hugo/resources/images" @@ -101,10 +99,6 @@ func (ns *Namespace) Filter(args ...interface{}) (resource.Image, error) { img := args[len(args)-1].(resource.Image) filtersv := args[:len(args)-1] - filters := make([]gift.Filter, len(filtersv)) - for i, f := range filtersv { - filters[i] = f.(gift.Filter) - } - return img.Filter(filters...) + return img.Filter(filtersv...) }