From 70840467d02d3ff14090f104ed1556c60939bd93 Mon Sep 17 00:00:00 2001 From: DarthSim Date: Wed, 29 Sep 2021 19:49:18 +0600 Subject: [PATCH] format_quality processing option --- CHANGELOG.md | 1 + docs/generating_the_url.md | 11 +++++++++- options/processing_options.go | 39 +++++++++++++++++++++++++++++++++-- structdiff/diff.go | 4 ++++ 4 files changed, 52 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index af08df37..1e880582 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - [Datadog](./docs/datadog.md) metrics. - `force` and `fill-down` resizing types. - [min-width](https://docs.imgproxy.net/generating_the_url?id=min-width) and [min-height](https://docs.imgproxy.net/generating_the_url?id=min-height) processing options. +- [format_quality](https://docs.imgproxy.net/generating_the_url?id=format-quality) processing option. ### Removed - Removed basic URL format, use [advanced one](./docs/generating_the_url.md) instead. diff --git a/docs/generating_the_url.md b/docs/generating_the_url.md index 409124e6..a42000bb 100644 --- a/docs/generating_the_url.md +++ b/docs/generating_the_url.md @@ -466,10 +466,19 @@ quality:%quality q:%quality ``` -Redefines quality of the resulting image, percentage. When `0`, quality is assumed based on `IMGPROXY_QUALITY` and `IMGPROXY_FORMAT_QUALITY`. +Redefines quality of the resulting image, percentage. When `0`, quality is assumed based on `IMGPROXY_QUALITY` and [format_quality](#format-quality). Default: 0. +### Format quality + +``` +format_quality:%format1:%quality1:%format2:%quality2:...:%formatN:%qualityN +fq:%format1:%quality1:%format2:%quality2:...:%formatN:%qualityN +``` + +Adds or redefines `IMGPROXY_FORMAT_QUALITY` values. + ### Autoquality ``` diff --git a/options/processing_options.go b/options/processing_options.go index 460e5cfb..022e1a07 100644 --- a/options/processing_options.go +++ b/options/processing_options.go @@ -79,6 +79,7 @@ type ProcessingOptions struct { Rotate int Format imagetype.Type Quality int + FormatQuality map[imagetype.Type]int MaxBytes int Flatten bool Background vips.Color @@ -103,6 +104,8 @@ type ProcessingOptions struct { Filename string UsedPresets []string + + defaultQuality int } var ( @@ -133,6 +136,9 @@ func NewProcessingOptions() *ProcessingOptions { StripMetadata: config.StripMetadata, StripColorProfile: config.StripColorProfile, AutoRotate: config.AutoRotate, + + // Basically, we need this to update ETag when `IMGPROXY_QUALITY` is changed + defaultQuality: config.Quality, } }) @@ -140,6 +146,11 @@ func NewProcessingOptions() *ProcessingOptions { po.SkipProcessingFormats = append([]imagetype.Type(nil), config.SkipProcessingFormats...) po.UsedPresets = make([]string, 0, len(config.Presets)) + po.FormatQuality = make(map[imagetype.Type]int) + for k, v := range config.FormatQuality { + po.FormatQuality[k] = v + } + return &po } @@ -147,11 +158,11 @@ func (po *ProcessingOptions) GetQuality() int { q := po.Quality if q == 0 { - q = config.FormatQuality[po.Format] + q = po.FormatQuality[po.Format] } if q == 0 { - q = config.Quality + q = po.defaultQuality } return q @@ -522,6 +533,28 @@ func applyQualityOption(po *ProcessingOptions, args []string) error { return nil } +func applyFormatQualityOption(po *ProcessingOptions, args []string) error { + argsLen := len(args) + if len(args)%2 != 0 { + return fmt.Errorf("Missing quality for: %s", args[argsLen-1]) + } + + for i := 0; i < argsLen; i += 2 { + f, ok := imagetype.Types[args[i]] + if !ok { + return fmt.Errorf("Invalid image format: %s", args[i]) + } + + if q, err := strconv.Atoi(args[i+1]); err == nil && q >= 0 && q <= 100 { + po.FormatQuality[f] = q + } else { + return fmt.Errorf("Invalid quality for %s: %s", args[i], args[i+1]) + } + } + + return nil +} + func applyMaxBytesOption(po *ProcessingOptions, args []string) error { if len(args) > 1 { return fmt.Errorf("Invalid max_bytes arguments: %v", args) @@ -832,6 +865,8 @@ func applyURLOption(po *ProcessingOptions, name string, args []string) error { // Saving options case "quality", "q": return applyQualityOption(po, args) + case "format_quality", "fq": + return applyFormatQualityOption(po, args) case "max_bytes", "mb": return applyMaxBytesOption(po, args) case "format", "f", "ext": diff --git a/structdiff/diff.go b/structdiff/diff.go index 7a77a8c4..dcf980c6 100644 --- a/structdiff/diff.go +++ b/structdiff/diff.go @@ -94,6 +94,10 @@ func Diff(a, b interface{}) Entries { fieldA := valA.Field(i) fieldB := valB.Field(i) + if !fieldA.CanInterface() || !fieldB.CanInterface() { + continue + } + intA := fieldA.Interface() intB := fieldB.Interface()