Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/gohugoio/hugo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--media/mediaType.go7
-rw-r--r--resources/image.go24
-rw-r--r--resources/image_test.go40
-rw-r--r--resources/images/config.go6
-rw-r--r--resources/images/image.go32
-rw-r--r--resources/resource.go4
-rw-r--r--resources/resource_metadata.go2
7 files changed, 100 insertions, 15 deletions
diff --git a/media/mediaType.go b/media/mediaType.go
index 434672c43..baf7b7e27 100644
--- a/media/mediaType.go
+++ b/media/mediaType.go
@@ -140,8 +140,11 @@ var (
YAMLType = Type{MainType: "application", SubType: "yaml", Suffixes: []string{"yaml", "yml"}, Delimiter: defaultDelimiter}
// Common image types
- PNGType = Type{MainType: "image", SubType: "png", Suffixes: []string{"png"}, Delimiter: defaultDelimiter}
- JPGType = Type{MainType: "image", SubType: "jpg", Suffixes: []string{"jpg", "jpeg"}, Delimiter: defaultDelimiter}
+ PNGType = Type{MainType: "image", SubType: "png", Suffixes: []string{"png"}, Delimiter: defaultDelimiter}
+ JPGType = Type{MainType: "image", SubType: "jpg", Suffixes: []string{"jpg", "jpeg"}, Delimiter: defaultDelimiter}
+ GIFType = Type{MainType: "image", SubType: "gif", Suffixes: []string{"gif"}, Delimiter: defaultDelimiter}
+ TIFFType = Type{MainType: "image", SubType: "tiff", Suffixes: []string{"tif", "tiff"}, Delimiter: defaultDelimiter}
+ BMPType = Type{MainType: "image", SubType: "bmp", Suffixes: []string{"bmp"}, Delimiter: defaultDelimiter}
OctetType = Type{MainType: "application", SubType: "octet-stream"}
)
diff --git a/resources/image.go b/resources/image.go
index 26b9b8710..bb9c987a5 100644
--- a/resources/image.go
+++ b/resources/image.go
@@ -43,8 +43,6 @@ import (
"github.com/gohugoio/hugo/resources/images"
// Blind import for image.Decode
-
- // Blind import for image.Decode
_ "golang.org/x/image/webp"
)
@@ -220,17 +218,13 @@ func (i *imageResource) Filter(filters ...interface{}) (resource.Image, error) {
}
conf.Key = internal.HashString(gfilters)
+ conf.TargetFormat = i.Format
return i.doWithImageConfig(conf, func(src image.Image) (image.Image, error) {
return i.Proc.Filter(src, gfilters...)
})
}
-func (i *imageResource) isJPEG() bool {
- name := strings.ToLower(i.getResourcePaths().relTargetDirFile.file)
- return strings.HasSuffix(name, ".jpg") || strings.HasSuffix(name, ".jpeg")
-}
-
// Serialize image processing. The imaging library spins up its own set of Go routines,
// so there is not much to gain from adding more load to the mix. That
// can even have negative effect in low resource scenarios.
@@ -260,7 +254,7 @@ func (i *imageResource) doWithImageConfig(conf images.ImageConfig, f func(src im
return nil, nil, &os.PathError{Op: errOp, Path: errPath, Err: err}
}
- if i.Format == images.PNG {
+ if conf.TargetFormat == images.PNG {
// Apply the colour palette from the source
if paletted, ok := src.(*image.Paletted); ok {
tmp := image.NewPaletted(converted.Bounds(), paletted.Palette)
@@ -271,6 +265,8 @@ func (i *imageResource) doWithImageConfig(conf images.ImageConfig, f func(src im
ci := i.clone(converted)
ci.setBasePath(conf)
+ ci.Format = conf.TargetFormat
+ ci.setMediaType(conf.TargetFormat.MediaType())
return ci, converted, nil
})
@@ -282,11 +278,14 @@ func (i *imageResource) decodeImageConfig(action, spec string) (images.ImageConf
return conf, err
}
- iconf := i.Proc.Cfg
+ // default to the source format
+ if conf.TargetFormat == 0 {
+ conf.TargetFormat = i.Format
+ }
- if conf.Quality <= 0 && i.isJPEG() {
+ if conf.Quality <= 0 && conf.TargetFormat.RequiresDefaultQuality() {
// We need a quality setting for all JPEGs
- conf.Quality = iconf.Quality
+ conf.Quality = i.Proc.Cfg.Quality
}
return conf, nil
@@ -339,6 +338,9 @@ func (i *imageResource) getImageMetaCacheTargetPath() string {
func (i *imageResource) relTargetPathFromConfig(conf images.ImageConfig) dirFile {
p1, p2 := helpers.FileAndExt(i.getResourcePaths().relTargetDirFile.file)
+ if conf.TargetFormat != i.Format {
+ p2 = conf.TargetFormat.DefaultExtension()
+ }
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 59d6b7c9a..5fa5021c9 100644
--- a/resources/image_test.go
+++ b/resources/image_test.go
@@ -133,6 +133,46 @@ func TestImageTransformBasic(t *testing.T) {
c.Assert(filled, eq, filledAgain)
}
+func TestImageTransformFormat(t *testing.T) {
+ c := qt.New(t)
+
+ image := fetchSunset(c)
+
+ fileCache := image.(specProvider).getSpec().FileCaches.ImageCache().Fs
+
+ assertExtWidthHeight := func(img resource.Image, ext string, w, h int) {
+ c.Helper()
+ c.Assert(img, qt.Not(qt.IsNil))
+ c.Assert(helpers.Ext(img.RelPermalink()), qt.Equals, ext)
+ c.Assert(img.Width(), qt.Equals, w)
+ c.Assert(img.Height(), qt.Equals, h)
+ }
+
+ c.Assert(image.RelPermalink(), qt.Equals, "/a/sunset.jpg")
+ c.Assert(image.ResourceType(), qt.Equals, "image")
+ assertExtWidthHeight(image, ".jpg", 900, 562)
+
+ imagePng, err := image.Resize("450x png")
+ c.Assert(err, qt.IsNil)
+ c.Assert(imagePng.RelPermalink(), qt.Equals, "/a/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_450x0_resize_linear.png")
+ c.Assert(imagePng.ResourceType(), qt.Equals, "image")
+ assertExtWidthHeight(imagePng, ".png", 450, 281)
+ c.Assert(imagePng.Name(), qt.Equals, "sunset.jpg")
+ c.Assert(imagePng.MediaType().String(), qt.Equals, "image/png")
+
+ assertFileCache(c, fileCache, path.Base(imagePng.RelPermalink()), 450, 281)
+
+ imageGif, err := image.Resize("225x gif")
+ c.Assert(err, qt.IsNil)
+ c.Assert(imageGif.RelPermalink(), qt.Equals, "/a/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_225x0_resize_linear.gif")
+ c.Assert(imageGif.ResourceType(), qt.Equals, "image")
+ assertExtWidthHeight(imageGif, ".gif", 225, 141)
+ c.Assert(imageGif.Name(), qt.Equals, "sunset.jpg")
+ c.Assert(imageGif.MediaType().String(), qt.Equals, "image/gif")
+
+ assertFileCache(c, fileCache, path.Base(imageGif.RelPermalink()), 225, 141)
+}
+
// https://github.com/gohugoio/hugo/issues/4261
func TestImageTransformLongFilename(t *testing.T) {
c := qt.New(t)
diff --git a/resources/images/config.go b/resources/images/config.go
index a290922ab..6bc701bfe 100644
--- a/resources/images/config.go
+++ b/resources/images/config.go
@@ -187,7 +187,8 @@ func DecodeImageConfig(action, config string, defaults Imaging) (ImageConfig, er
} else {
return c, errors.New("invalid image dimensions")
}
-
+ } else if f, ok := ImageFormatFromExt("." + part); ok {
+ c.TargetFormat = f
}
}
@@ -212,6 +213,9 @@ 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
+ TargetFormat Format
+
Action string
// If set, this will be used as the key in filenames etc.
diff --git a/resources/images/image.go b/resources/images/image.go
index e72d96837..bd7500c28 100644
--- a/resources/images/image.go
+++ b/resources/images/image.go
@@ -23,6 +23,7 @@ import (
"io"
"sync"
+ "github.com/gohugoio/hugo/media"
"github.com/gohugoio/hugo/resources/images/exif"
"github.com/disintegration/gift"
@@ -59,7 +60,7 @@ type Image struct {
}
func (i *Image) EncodeTo(conf ImageConfig, img image.Image, w io.Writer) error {
- switch i.Format {
+ switch conf.TargetFormat {
case JPEG:
var rgba *image.RGBA
@@ -250,6 +251,35 @@ const (
BMP
)
+// RequiresDefaultQuality returns if the default quality needs to be applied to images of this format
+func (f Format) RequiresDefaultQuality() bool {
+ return f == JPEG
+}
+
+// DefaultExtension returns the default file extension of this format, starting with a dot.
+// For example: .jpg for JPEG
+func (f Format) DefaultExtension() string {
+ return f.MediaType().FullSuffix()
+}
+
+// MediaType returns the media type of this image, e.g. image/jpeg for JPEG
+func (f Format) MediaType() media.Type {
+ switch f {
+ case JPEG:
+ return media.JPGType
+ case PNG:
+ return media.PNGType
+ case GIF:
+ return media.GIFType
+ case TIFF:
+ return media.TIFFType
+ case BMP:
+ return media.BMPType
+ default:
+ panic(fmt.Sprintf("%d is not a valid image format", f))
+ }
+}
+
type imageConfig struct {
config image.Config
configInit sync.Once
diff --git a/resources/resource.go b/resources/resource.go
index 7f52a7135..acf8e37c0 100644
--- a/resources/resource.go
+++ b/resources/resource.go
@@ -220,6 +220,10 @@ func (l *genericResource) MediaType() media.Type {
return l.mediaType
}
+func (l *genericResource) setMediaType(mediaType media.Type) {
+ l.mediaType = mediaType
+}
+
func (l *genericResource) Name() string {
return l.name
}
diff --git a/resources/resource_metadata.go b/resources/resource_metadata.go
index 79e61e1a0..ce17df022 100644
--- a/resources/resource_metadata.go
+++ b/resources/resource_metadata.go
@@ -18,6 +18,7 @@ import (
"strconv"
"github.com/gohugoio/hugo/hugofs/glob"
+ "github.com/gohugoio/hugo/media"
"github.com/gohugoio/hugo/resources/resource"
"github.com/pkg/errors"
@@ -42,6 +43,7 @@ type metaAssignerProvider interface {
type metaAssigner interface {
setTitle(title string)
setName(name string)
+ setMediaType(mediaType media.Type)
updateParams(params map[string]interface{})
}