summaryrefslogtreecommitdiffstats
path: root/resource/image.go
diff options
context:
space:
mode:
Diffstat (limited to 'resource/image.go')
-rw-r--r--resource/image.go53
1 files changed, 41 insertions, 12 deletions
diff --git a/resource/image.go b/resource/image.go
index 7ec65f3bc..c9ee90bf1 100644
--- a/resource/image.go
+++ b/resource/image.go
@@ -35,7 +35,6 @@ import (
_ "image/png"
"github.com/disintegration/imaging"
-
// Import webp codec
"sync"
@@ -56,6 +55,9 @@ type Imaging struct {
// Resample filter used. See https://github.com/disintegration/imaging
ResampleFilter string
+
+ // The anchor used in Fill. Default is "smart", i.e. Smart Crop.
+ Anchor string
}
const (
@@ -157,6 +159,9 @@ func (i *Image) Fit(spec string) (*Image, error) {
// Space delimited config: 200x300 TopLeft
func (i *Image) Fill(spec string) (*Image, error) {
return i.doWithImageConfig("fill", spec, func(src image.Image, conf imageConfig) (image.Image, error) {
+ if conf.AnchorStr == smartCropIdentifier {
+ return smartCrop(src, conf.Width, conf.Height, conf.Anchor, conf.Filter)
+ }
return imaging.Fill(src, conf.Width, conf.Height, conf.Anchor, conf.Filter), nil
})
}
@@ -206,6 +211,13 @@ func (i *Image) doWithImageConfig(action, spec string, f func(src image.Image, c
conf.Filter = imageFilters[conf.FilterStr]
}
+ if conf.AnchorStr == "" {
+ conf.AnchorStr = i.imaging.Anchor
+ if !strings.EqualFold(conf.AnchorStr, smartCropIdentifier) {
+ conf.Anchor = anchorPositions[conf.AnchorStr]
+ }
+ }
+
key := i.relTargetPathForRel(i.filenameFromConfig(conf), false)
return i.spec.imageCache.getOrCreate(i, key, func(resourceCacheFilename string) (*Image, error) {
@@ -248,18 +260,22 @@ func (i imageConfig) key() string {
if i.Rotate != 0 {
k += "_r" + strconv.Itoa(i.Rotate)
}
- k += "_" + i.FilterStr + "_" + i.AnchorStr
- return k
-}
+ anchor := i.AnchorStr
+ if anchor == smartCropIdentifier {
+ anchor = anchor + strconv.Itoa(smartCropVersionNumber)
+ }
-var defaultImageConfig = imageConfig{
- Action: "",
- Anchor: imaging.Center,
- AnchorStr: strings.ToLower("Center"),
+ k += "_" + i.FilterStr
+
+ if strings.EqualFold(i.Action, "fill") {
+ k += "_" + anchor
+ }
+
+ return k
}
func newImageConfig(width, height, quality, rotate int, filter, anchor string) imageConfig {
- c := defaultImageConfig
+ var c imageConfig
c.Width = width
c.Height = height
@@ -287,7 +303,7 @@ func newImageConfig(width, height, quality, rotate int, filter, anchor string) i
func parseImageConfig(config string) (imageConfig, error) {
var (
- c = defaultImageConfig
+ c imageConfig
err error
)
@@ -299,7 +315,9 @@ func parseImageConfig(config string) (imageConfig, error) {
for _, part := range parts {
part = strings.ToLower(part)
- if pos, ok := anchorPositions[part]; ok {
+ if part == smartCropIdentifier {
+ c.AnchorStr = smartCropIdentifier
+ } else if pos, ok := anchorPositions[part]; ok {
c.Anchor = pos
c.AnchorStr = part
} else if filter, ok := imageFilters[part]; ok {
@@ -561,8 +579,19 @@ func decodeImaging(m map[string]interface{}) (Imaging, error) {
return i, err
}
- if i.Quality <= 0 || i.Quality > 100 {
+ if i.Quality == 0 {
i.Quality = defaultJPEGQuality
+ } else if i.Quality < 0 || i.Quality > 100 {
+ return i, errors.New("JPEG quality must be a number between 1 and 100")
+ }
+
+ 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 i, errors.New("invalid anchor value in imaging config")
+ }
}
if i.ResampleFilter == "" {