Ver Fonte

format_quality processing option

DarthSim há 3 anos atrás
pai
commit
70840467d0
4 ficheiros alterados com 52 adições e 3 exclusões
  1. 1 0
      CHANGELOG.md
  2. 10 1
      docs/generating_the_url.md
  3. 37 2
      options/processing_options.go
  4. 4 0
      structdiff/diff.go

+ 1 - 0
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.

+ 10 - 1
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
 
 ```

+ 37 - 2
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":

+ 4 - 0
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()