diff --git a/CHANGELOG.md b/CHANGELOG.md index f91685f9..52cf2adc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ - [Plain source URLs](./docs/generating_the_url_advanced.md#plain) support; - [Serving images from Google Cloud Storage](./docs/serving_files_from_google_cloud_storage.md); -- [Full support of GIFs](./docs/image_formats_support.md) including animated ones; +- [Full support of GIFs](./docs/image_formats_support.md#gif-support) including animated ones; - [Watermarks](./docs/watermark.md); - [New Relic](./docs/new_relic.md) metrics; - [Prometheus](./docs/prometheus.md) metrics; diff --git a/config.go b/config.go index 4e1bc62f..c73a4d79 100644 --- a/config.go +++ b/config.go @@ -141,6 +141,7 @@ type config struct { MaxSrcDimension int MaxSrcResolution int + MaxGifFrames int JpegProgressive bool PngInterlaced bool @@ -201,6 +202,7 @@ var conf = config{ TTL: 3600, IgnoreSslVerification: false, MaxSrcResolution: 16800000, + MaxGifFrames: 1, AllowInsecure: false, SignatureSize: 32, Quality: 80, @@ -240,6 +242,7 @@ func init() { intEnvConfig(&conf.MaxSrcDimension, "IMGPROXY_MAX_SRC_DIMENSION") megaIntEnvConfig(&conf.MaxSrcResolution, "IMGPROXY_MAX_SRC_RESOLUTION") + intEnvConfig(&conf.MaxGifFrames, "IMGPROXY_MAX_GIF_FRAMES") boolEnvConfig(&conf.JpegProgressive, "IMGPROXY_JPEG_PROGRESSIVE") boolEnvConfig(&conf.PngInterlaced, "IMGPROXY_PNG_INTERLACED") @@ -350,6 +353,10 @@ func init() { log.Fatalf("Max src resolution should be greater than 0, now - %d\n", conf.MaxSrcResolution) } + if conf.MaxGifFrames <= 0 { + log.Fatalf("Max GIF frames should be greater than 0, now - %d\n", conf.MaxGifFrames) + } + if conf.Quality <= 0 { log.Fatalf("Quality should be greater than 0, now - %d\n", conf.Quality) } else if conf.Quality > 100 { diff --git a/docs/configuration.md b/docs/configuration.md index 2c4c5e18..af471c11 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -42,6 +42,12 @@ imgproxy protects you from so-called image bombs. Here is how you can specify ma * `IMGPROXY_MAX_SRC_RESOLUTION`: the maximum resolution of the source image, in megapixels. Images with larger actual size will be rejected. Default: `16.8`; +imgproxy can process animated GIFs, but since this operation is pretty heavy, only one frame is processed by default. You can increase the maximum of GIF frames to process with the following variable: + +* `IMGPROXY_MAX_GIF_FRAMES`: the maximum of animated GIF frames to being processed. Default: `1`. + +**Note:** imgproxy summarizes all GIF frames resolutions while checking source image resolution. + You can also specify a secret to enable authorization with the HTTP `Authorization` header for use in production environments: * `IMGPROXY_SECRET`: the authorization token. If specified, the HTTP request should contain the `Authorization: Bearer %secret%` header; diff --git a/docs/image_formats_support.md b/docs/image_formats_support.md index aeb65ea9..6ab6a3bb 100644 --- a/docs/image_formats_support.md +++ b/docs/image_formats_support.md @@ -10,3 +10,9 @@ At the moment, imgproxy supports only the most popular Web image formats: ## GIF support imgproxy supports GIF output only when using libvips 8.7.0+ compiled with ImageMagick support. Official imgproxy Docker image supports GIF out of the box. + +Since processing of animated GIFs is pretty heavy, only one frame is processed by default. You can increase the maximum of GIF frames to process with the following variable: + +* `IMGPROXY_MAX_GIF_FRAMES`: the maximum of animated GIF frames to being processed. Default: `1`. + +**Note:** imgproxy summarizes all GIF frames resolutions while checking source image resolution. diff --git a/process.go b/process.go index ec809f3f..bc948d8f 100644 --- a/process.go +++ b/process.go @@ -425,7 +425,7 @@ func transformGif(ctx context.Context, img **C.struct__VipsImage, po *processing return err } - framesCount := imgHeight / frameHeight + framesCount := minInt(imgHeight/frameHeight, conf.MaxGifFrames) frames := make([]*C.struct__VipsImage, framesCount) defer func() {