diff --git a/docs/configuration.md b/docs/configuration.md index ed32c340..078f91db 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -132,6 +132,8 @@ imgproxy can use the `Accept` HTTP header to detect if the browser supports AVIF **📝Note:** imgproxy prefers AVIF over WebP. This means that if both AVIF and WebP detection/enforcement are enabled and the browser supports both of them, AVIF will be used. +**📝Note:** If both the source and the requested image formats support animation and AVIF detection/enforcement is enabled, AVIF won't be used as AVIF sequence is not supported yet. + **📝Note:** When AVIF/WebP support detection is enabled, please take care to configure your CDN or caching proxy to take the `Accept` HTTP header into account while caching. **⚠️Warning:** Headers cannot be signed. This means that an attacker can bypass your CDN cache by changing the `Accept` HTTP headers. Have this in mind when configuring your production caching setup. diff --git a/process.go b/process.go index 6d62594a..1b84afbf 100644 --- a/process.go +++ b/process.go @@ -34,6 +34,13 @@ func imageTypeGoodForWeb(imgtype imageType) bool { imgtype != imageTypeBMP } +func canSwitchFormat(src, dst, want imageType) bool { + return imageTypeSaveSupport(want) && + (!vipsSupportAnimation(src) || + (dst != imageTypeUnknown && !vipsSupportAnimation(dst)) || + vipsSupportAnimation(want)) +} + func extractMeta(img *vipsImage, baseAngle int, useOrientation bool) (int, int, int, bool) { width := img.Width() height := img.Height() @@ -745,18 +752,18 @@ func processImage(ctx context.Context) ([]byte, context.CancelFunc, error) { switch { case po.Format == imageTypeUnknown: switch { - case po.PreferAvif && imageTypeSaveSupport(imageTypeAVIF): + case po.PreferAvif && canSwitchFormat(imgdata.Type, imageTypeUnknown, imageTypeAVIF): po.Format = imageTypeAVIF - case po.PreferWebP && imageTypeSaveSupport(imageTypeWEBP): + case po.PreferWebP && canSwitchFormat(imgdata.Type, imageTypeUnknown, imageTypeWEBP): po.Format = imageTypeWEBP case imageTypeSaveSupport(imgdata.Type) && imageTypeGoodForWeb(imgdata.Type): po.Format = imgdata.Type default: po.Format = imageTypeJPEG } - case po.EnforceAvif && imageTypeSaveSupport(imageTypeAVIF): + case po.EnforceAvif && canSwitchFormat(imgdata.Type, po.Format, imageTypeAVIF): po.Format = imageTypeAVIF - case po.EnforceWebP && imageTypeSaveSupport(imageTypeWEBP): + case po.EnforceWebP && canSwitchFormat(imgdata.Type, po.Format, imageTypeWEBP): po.Format = imageTypeWEBP }