mirror of
https://github.com/imgproxy/imgproxy.git
synced 2025-09-16 09:36:18 +02:00
IMGPROXY_PREFERRED_FORMATS config
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
- Add support of 16-bit BMP.
|
||||
- Add `IMGPROXY_NEW_RELIC_LABELS` config.
|
||||
- Add support of JPEG files with differential Huffman coding or arithmetic coding.
|
||||
- Add `IMGPROXY_PREFERRED_FORMATS` config.
|
||||
|
||||
### Fix
|
||||
- Fix trimming of CMYK images.
|
||||
|
@@ -59,6 +59,8 @@ var (
|
||||
EnforceAvif bool
|
||||
EnableClientHints bool
|
||||
|
||||
PreferredFormats []imagetype.Type
|
||||
|
||||
SkipProcessingFormats []imagetype.Type
|
||||
|
||||
UseLinearColorspace bool
|
||||
@@ -220,6 +222,15 @@ func Reset() {
|
||||
EnforceAvif = false
|
||||
EnableClientHints = false
|
||||
|
||||
PreferredFormats = []imagetype.Type{
|
||||
imagetype.JPEG,
|
||||
imagetype.PNG,
|
||||
imagetype.GIF,
|
||||
imagetype.WEBP,
|
||||
imagetype.AVIF,
|
||||
imagetype.ICO,
|
||||
}
|
||||
|
||||
SkipProcessingFormats = make([]imagetype.Type, 0)
|
||||
|
||||
UseLinearColorspace = false
|
||||
@@ -376,6 +387,10 @@ func Configure() error {
|
||||
|
||||
configurators.String(&HealthCheckPath, "IMGPROXY_HEALTH_CHECK_PATH")
|
||||
|
||||
if err := configurators.ImageTypes(&PreferredFormats, "IMGPROXY_PREFERRED_FORMATS"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := configurators.ImageTypes(&SkipProcessingFormats, "IMGPROXY_SKIP_PROCESSING_FORMATS"); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -557,6 +572,10 @@ func Configure() error {
|
||||
return fmt.Errorf("Quality can't be greater than 100, now - %d\n", Quality)
|
||||
}
|
||||
|
||||
if len(PreferredFormats) == 0 {
|
||||
return fmt.Errorf("At least one preferred format should be specified")
|
||||
}
|
||||
|
||||
if IgnoreSslVerification {
|
||||
log.Warning("Ignoring SSL verification is very unsafe")
|
||||
}
|
||||
|
@@ -103,17 +103,17 @@ func Bool(b *bool, name string) {
|
||||
}
|
||||
|
||||
func ImageTypes(it *[]imagetype.Type, name string) error {
|
||||
*it = []imagetype.Type{}
|
||||
|
||||
if env := os.Getenv(name); len(env) > 0 {
|
||||
parts := strings.Split(env, ",")
|
||||
|
||||
*it = make([]imagetype.Type, 0, len(parts))
|
||||
|
||||
for _, p := range parts {
|
||||
pt := strings.TrimSpace(p)
|
||||
if t, ok := imagetype.Types[pt]; ok {
|
||||
*it = append(*it, t)
|
||||
} else {
|
||||
return fmt.Errorf("Unknown image format to skip: %s", pt)
|
||||
return fmt.Errorf("Unknown image format: %s", pt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -249,6 +249,22 @@ You can set up a fallback image that will be used in case imgproxy is unable to
|
||||
* `IMGPROXY_FALLBACK_IMAGE_TTL`: a duration (in seconds) sent via the `Expires` and `Cache-Control: max-age` HTTP headers when a fallback image was used. When blank or `0`, the value from `IMGPROXY_TTL` is used.
|
||||
* `IMGPROXY_FALLBACK_IMAGES_CACHE_SIZE`:  the size of custom fallback images cache. When set to `0`, the fallback image cache is disabled. 256 fallback images are cached by default.
|
||||
|
||||
## Preferred formats
|
||||
|
||||
When the resulting image format is not explicitly specified in the imgproxy URL via the extension or the `format` processing option, imgproxy will choose one of the preferred formats as the resultant:
|
||||
|
||||
* `IMGPROXY_PREFERRED_FORMATS`: a list of preferred formats, comma divided. Default: `jpeg,png,gif,webp,avif,ico`
|
||||
|
||||
imgproxy is guided by the following rules when choosing the resulting format:
|
||||
|
||||
1. If the preferred formats list contains the source image format, it will be used as the resultant
|
||||
2. If the resulting image is animated, the resulting image format should support animations
|
||||
3. If the resulting image contains transparency, the resulting image format should support transparency
|
||||
4. imgproxy chooses the first preferred format that meets those requirements
|
||||
5. If none of the preferred formats meet the requirements, the first preferred format is used as the resultant
|
||||
|
||||
**📝Note:** When AVIF/WebP support detection is enabled and the browser supports AVIF/WebP, it may be used as the resultant format even if the preferred formats list doesn't contain it.
|
||||
|
||||
## Skip processing
|
||||
|
||||
You can configure imgproxy to skip processing of some formats:
|
||||
|
6
main.go
6
main.go
@@ -20,6 +20,7 @@ import (
|
||||
"github.com/imgproxy/imgproxy/v3/metrics"
|
||||
"github.com/imgproxy/imgproxy/v3/metrics/prometheus"
|
||||
"github.com/imgproxy/imgproxy/v3/options"
|
||||
"github.com/imgproxy/imgproxy/v3/processing"
|
||||
"github.com/imgproxy/imgproxy/v3/version"
|
||||
"github.com/imgproxy/imgproxy/v3/vips"
|
||||
)
|
||||
@@ -51,6 +52,11 @@ func initialize() error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := processing.ValidatePreferredFormats(); err != nil {
|
||||
vips.Shutdown()
|
||||
return err
|
||||
}
|
||||
|
||||
if err := options.ParsePresets(config.Presets); err != nil {
|
||||
vips.Shutdown()
|
||||
return err
|
||||
|
@@ -37,9 +37,40 @@ var mainPipeline = pipeline{
|
||||
finalize,
|
||||
}
|
||||
|
||||
func imageTypeGoodForWeb(imgtype imagetype.Type) bool {
|
||||
return imgtype != imagetype.TIFF &&
|
||||
imgtype != imagetype.BMP
|
||||
func isImageTypePreferred(imgtype imagetype.Type) bool {
|
||||
for _, t := range config.PreferredFormats {
|
||||
if imgtype == t {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func findBestFormat(srcType imagetype.Type, animated, expectAlpha bool) imagetype.Type {
|
||||
for _, t := range config.PreferredFormats {
|
||||
if animated && !t.SupportsAnimation() {
|
||||
continue
|
||||
}
|
||||
|
||||
if expectAlpha && !t.SupportsAlpha() {
|
||||
continue
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
return config.PreferredFormats[0]
|
||||
}
|
||||
|
||||
func ValidatePreferredFormats() error {
|
||||
for _, t := range config.PreferredFormats {
|
||||
if !vips.SupportsSave(t) {
|
||||
return fmt.Errorf("%s can't be a preferred format as it's saving is not supported", t)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func canFitToBytes(imgtype imagetype.Type) bool {
|
||||
@@ -223,6 +254,7 @@ func ProcessImage(ctx context.Context, imgdata *imagedata.ImageData, po *options
|
||||
originWidth, originHeight := getImageSize(img)
|
||||
|
||||
animated := img.IsAnimated()
|
||||
expectAlpha := !po.Flatten && (img.HasAlpha() || po.Padding.Enabled || po.Extend.Enabled)
|
||||
|
||||
switch {
|
||||
case po.Format == imagetype.Unknown:
|
||||
@@ -231,10 +263,10 @@ func ProcessImage(ctx context.Context, imgdata *imagedata.ImageData, po *options
|
||||
po.Format = imagetype.AVIF
|
||||
case po.PreferWebP:
|
||||
po.Format = imagetype.WEBP
|
||||
case vips.SupportsSave(imgdata.Type) && imageTypeGoodForWeb(imgdata.Type):
|
||||
case isImageTypePreferred(imgdata.Type):
|
||||
po.Format = imgdata.Type
|
||||
default:
|
||||
po.Format = imagetype.JPEG
|
||||
po.Format = findBestFormat(imgdata.Type, animated, expectAlpha)
|
||||
}
|
||||
case po.EnforceAvif && !animated:
|
||||
po.Format = imagetype.AVIF
|
||||
|
Reference in New Issue
Block a user