-
Notifications
You must be signed in to change notification settings - Fork 0
/
imaging.go
140 lines (112 loc) · 3.55 KB
/
imaging.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package valueobject
import (
"errors"
"fmt"
"github.com/gohugonet/hugoverse/internal/domain/config"
"github.com/gohugonet/hugoverse/pkg/identity"
"github.com/gohugonet/hugoverse/pkg/images"
"github.com/gohugonet/hugoverse/pkg/maps"
"github.com/mitchellh/mapstructure"
"strings"
)
const (
defaultJPEGQuality = 75
defaultResampleFilter = "box"
defaultBgColor = "#ffffff"
defaultHint = "photo"
)
var (
defaultImagingConfig = map[string]any{
"resampleFilter": defaultResampleFilter,
"bgColor": defaultBgColor,
"hint": defaultHint,
"quality": defaultJPEGQuality,
}
)
const (
// Do not change.
smartCropIdentifier = "smart"
// This is just a increment, starting on 1. If Smart Crop improves its cropping, we
// need a way to trigger a re-generation of the crops in the wild, so increment this.
smartCropVersionNumber = 1
)
// ImagingConfig contains default images processing configuration. This will be fetched
// from site (or language) config.
type ImagingConfig struct {
// Default images quality setting (1-100). Only used for JPEG images.
Quality int
// Resample filter to use in resize operations.
ResampleFilter string
// Hint about what type of images 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
// Default color used in fill operations (e.g. "fff" for white).
BgColor string
Exif ExifConfig
}
func DecodeImagingConfig(p config.Provider) (ImagingConfigInternal, error) {
in := p.GetStringMap("imaging")
if in == nil {
in = make(map[string]any)
}
buildConfig := func(in any) (ImagingConfigInternal, error) {
m, err := maps.ToStringMapE(in)
if err != nil {
return ImagingConfigInternal{}, err
}
// Merge in the defaults.
maps.MergeShallow(m, defaultImagingConfig)
var i ImagingConfigInternal
if err := mapstructure.Decode(m, &i.Imaging); err != nil {
return i, err
}
if err := i.Imaging.init(); err != nil {
return i, err
}
i.BgColor, err = images.HexStringToColor(i.Imaging.BgColor)
if err != nil {
return i, err
}
if i.Imaging.Anchor != "" && i.Imaging.Anchor != smartCropIdentifier {
anchor, found := anchorPositions[i.Imaging.Anchor]
if !found {
return i, fmt.Errorf("invalid anchor value %q in imaging config", i.Anchor)
}
i.Anchor = anchor
}
filter, found := images.ImageFilters[i.Imaging.ResampleFilter]
if !found {
return i, fmt.Errorf("%q is not a valid resample filter", filter)
}
i.ResampleFilter = filter
return i, nil
}
// Build the config
c, err := buildConfig(in)
if err != nil {
return ImagingConfigInternal{}, err
}
c.SourceHash = identity.HashString(in)
return c, nil
}
func (cfg *ImagingConfig) init() error {
if cfg.Quality < 0 || cfg.Quality > 100 {
return errors.New("images 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)
if cfg.Anchor == "" {
cfg.Anchor = smartCropIdentifier
}
if strings.TrimSpace(cfg.Exif.IncludeFields) == "" && strings.TrimSpace(cfg.Exif.ExcludeFields) == "" {
// Don't change this for no good reason. Please don't.
cfg.Exif.ExcludeFields = "GPS|Exif|Exposure[M|P|B]|Contrast|Resolution|Sharp|JPEG|Metering|Sensing|Saturation|ColorSpace|Flash|WhiteBalance"
}
return nil
}