Skip to content

Commit

Permalink
Support for specifying the default quality per format
Browse files Browse the repository at this point in the history
- Rename weserv_default_quality directive to weserv_quality.
- Rename weserv_default_level directive to weserv_zlib_level.
- Introduce weserv_avif_speed to control AVIF CPU effort setting.
- Change default quality from 85 to 80.
- Regenerate expected fixtures.
  • Loading branch information
kleisauke committed May 30, 2021
1 parent a91eb69 commit 014da7f
Show file tree
Hide file tree
Showing 68 changed files with 199 additions and 43 deletions.
40 changes: 33 additions & 7 deletions include/weserv/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ struct Config {
explicit Config()
: savers(static_cast<uintptr_t>(enums::Output::All)),
limit_input_pixels(71000000), limit_output_pixels(71000000),
max_pages(256), default_quality(85), default_level(6),
max_pages(256), quality(80), avif_quality(80), jpeg_quality(80),
tiff_quality(80), webp_quality(80), avif_speed(5), zlib_level(6),
fail_on_error(0) {}

// Enables or disables image savers to be used within the `&output=` query
Expand All @@ -40,18 +41,43 @@ struct Config {
// weserv_max_pages 256;
intptr_t max_pages;

// The default quality to use for JPEG, WebP and TIFF images.
// Defaults to `85` which usually produces excellent results.
// The default quality to use for JPEG, WebP, TIFF and AVIF images.
// Defaults to `80` which usually produces excellent results.
// NOTE: Can be overridden with `&q=`.
// weserv_default_quality 85;
intptr_t default_quality;
// weserv_quality 80;
intptr_t quality;

// The default quality to use for AVIF images.
// NOTE: Can be overridden with `&q=`.
// weserv_avif_quality 50;
intptr_t avif_quality;

// The default quality to use for JPEG images.
// NOTE: Can be overridden with `&q=`.
// weserv_jpeg_quality 80;
intptr_t jpeg_quality;

// The default quality to use for TIFF images.
// NOTE: Can be overridden with `&q=`.
// weserv_tiff_quality 80;
intptr_t tiff_quality;

// The default quality to use for WebP images.
// NOTE: Can be overridden with `&q=`.
// weserv_webp_quality 80;
intptr_t webp_quality;

// Controls the CPU effort spent on improving AVIF compression.
// Defaults to 5.
// weserv_avif_speed 5;
intptr_t avif_speed;

// zlib compression level, 0-9.
// Defaults to 6 (`Z_DEFAULT_COMPRESSION`) which is intended to be a good
// compromise between speed and compression effectiveness.
// NOTE: Can be overridden `&l=`.
// weserv_default_level 6;
intptr_t default_level;
// weserv_zlib_level 6;
intptr_t zlib_level;

// Do a "best effort" to decode images, even if the data is corrupt or
// invalid. Set this flag to `on` if you would rather to halt processing and
Expand Down
81 changes: 72 additions & 9 deletions ngx_conf/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,25 +116,88 @@ trusted. Set to `0` to remove this limit.
Sets the maximum number of pixels (width × height) of an output image, after
any upscaling. Set to `0` to remove this limit.

### `weserv_default_quality`
### `weserv_quality`

| syntax: | `weserv_default_quality <quality>` |
| syntax: | `weserv_quality <quality>` |
| :----------- | :--------------------------------------------- |
| **default:** | `85` |
| **default:** | `80` |
| **context:** | `http`, `server`, `location`, `if in location` |

Sets the default quality (1-100) to use for JPEG, WebP and TIFF images when
`&q=` is not specified.
Sets the default quality to use for JPEG, WebP, TIFF and AVIF images when
`&q=` is not specified. Acceptable values are in the range from 1 to 100.

### `weserv_default_level`
### `weserv_avif_quality`

| syntax: | `weserv_default_level <level>` |
| syntax: | `weserv_avif_quality <quality>` |
| :----------- | :--------------------------------------------- |
| **default:** ||
| **context:** | `http`, `server`, `location`, `if in location` |

Sets the default quality to use for AVIF images when `&q=` is not specified.
Acceptable values are in the range from 1 to 100.

If the directive is not present, then the quality specified in `weserv_quality`
is used.

### `weserv_jpeg_quality`

| syntax: | `weserv_jpeg_quality <quality>` |
| :----------- | :--------------------------------------------- |
| **default:** ||
| **context:** | `http`, `server`, `location`, `if in location` |

Sets the default quality to use for JPEG images when `&q=` is not specified.
Acceptable values are in the range from 1 to 100.

If the directive is not present, then the quality specified in `weserv_quality`
is used.

### `weserv_tiff_quality`

| syntax: | `weserv_tiff_quality <quality>` |
| :----------- | :--------------------------------------------- |
| **default:** ||
| **context:** | `http`, `server`, `location`, `if in location` |

Sets the default quality to use for TIFF images when `&q=` is not specified.
Acceptable values are in the range from 1 to 100.

If the directive is not present, then the quality specified in `weserv_quality`
is used.

### `weserv_webp_quality`

| syntax: | `weserv_webp_quality <quality>` |
| :----------- | :--------------------------------------------- |
| **default:** ||
| **context:** | `http`, `server`, `location`, `if in location` |

Sets the default quality to use for WebP images when `&q=` is not specified.
Acceptable values are in the range from 1 to 100.

If the directive is not present, then the quality specified in `weserv_quality`
is used.

### `weserv_avif_speed`

| syntax: | `weserv_avif_speed <speed>` |
| :----------- | :----------------------------------------------|
| **default:** | `5` |
| **context:** | `http`, `server`, `location`, `if in location` |

Controls the CPU effort spent on improving AVIF compression. Acceptable
values are in the range from 0 (slowest/smallest) to 9 (fastest/largest).

### `weserv_zlib_level`

| syntax: | `weserv_zlib_level <level>` |
| :----------- | :--------------------------------------------- |
| **default:** | `6` |
| **context:** | `http`, `server`, `location`, `if in location` |

Sets the default zlib compression (0-9) to use for PNG images when `&l=` is
not specified.
Sets the default zlib compression to use for PNG images when `&l=` is not
specified. Acceptable values are in the range from 0 (fastest/largest) to
9 (slowest/smallest).

### `weserv_fail_on_error`

Expand Down
22 changes: 11 additions & 11 deletions src/api/processors/stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,9 +288,9 @@ void Stream::append_save_options<Output::Jpeg>(vips::VOption *options) const {
// of 1 - 100
return q >= 1 && q <= 100;
},
static_cast<int>(config_.default_quality));
static_cast<int>(config_.jpeg_quality));

// Set quality (default is 85)
// Set quality (default is 80)
options->set("Q", quality);

// Use progressive (interlace) scan, if necessary
Expand All @@ -309,7 +309,7 @@ void Stream::append_save_options<Output::Png>(vips::VOption *options) const {
// 0 (no Deflate) - 9 (maximum Deflate)
return l >= 0 && l <= 9;
},
static_cast<int>(config_.default_level));
static_cast<int>(config_.zlib_level));

auto filter = query_->get<bool>("af", false) ? VIPS_FOREIGN_PNG_FILTER_ALL
: VIPS_FOREIGN_PNG_FILTER_NONE;
Expand All @@ -333,9 +333,9 @@ void Stream::append_save_options<Output::Webp>(vips::VOption *options) const {
// of 1 - 100
return q >= 1 && q <= 100;
},
static_cast<int>(config_.default_quality));
static_cast<int>(config_.webp_quality));

// Set quality (default is 85)
// Set quality (default is 80)
options->set("Q", quality);

// Set quality of alpha layer to 100
Expand All @@ -351,17 +351,17 @@ void Stream::append_save_options<Output::Avif>(vips::VOption *options) const {
// of 1 - 100
return q >= 1 && q <= 100;
},
static_cast<int>(config_.default_quality));
static_cast<int>(config_.avif_quality));

// Set quality (default is 85)
// Set quality (default is 80)
options->set("Q", quality);

// Set compression format to AV1
options->set("compression", VIPS_FOREIGN_HEIF_COMPRESSION_AV1);

#if VIPS_VERSION_AT_LEAST(8, 10, 2)
// Control the CPU effort spent on improving compression
options->set("speed", 6);
// Control the CPU effort spent on improving compression (default 5)
options->set("speed", static_cast<int>(config_.avif_speed));
#endif
}

Expand All @@ -374,9 +374,9 @@ void Stream::append_save_options<Output::Tiff>(vips::VOption *options) const {
// of 1 - 100
return q >= 1 && q <= 100;
},
static_cast<int>(config_.default_quality));
static_cast<int>(config_.tiff_quality));

// Set quality (default is 85)
// Set quality (default is 80)
options->set("Q", quality);

// Set the tiff compression to jpeg
Expand Down
99 changes: 83 additions & 16 deletions src/nginx/module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,19 @@ ngx_conf_bitmask_t ngx_weserv_savers[] = {
{ngx_null_string, 0} // last entry
};

ngx_conf_num_bounds_t ngx_weserv_quality_bounds = {
ngx_conf_check_num_bounds, 1, 100
};

ngx_conf_num_bounds_t ngx_weserv_avif_speed_bounds = {
ngx_conf_check_num_bounds, 0, 9
};

ngx_conf_num_bounds_t ngx_weserv_zlib_level_bounds = {
ngx_conf_check_num_bounds, 0, 9
};


// clang-format off
/**
* The module commands contain list of configurable properties for this module.
Expand Down Expand Up @@ -151,21 +164,61 @@ ngx_command_t ngx_weserv_commands[] = {
offsetof(ngx_weserv_loc_conf_t, api_conf.limit_output_pixels),
nullptr},

{ngx_string("weserv_default_quality"),
{ngx_string("weserv_quality"),
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF |
NGX_HTTP_LIF_CONF | NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_weserv_loc_conf_t, api_conf.default_quality),
nullptr},
offsetof(ngx_weserv_loc_conf_t, api_conf.quality),
&ngx_weserv_quality_bounds},

{ngx_string("weserv_default_level"),
{ngx_string("weserv_avif_quality"),
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF |
NGX_HTTP_LIF_CONF | NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_weserv_loc_conf_t, api_conf.default_level),
nullptr},
offsetof(ngx_weserv_loc_conf_t, api_conf.avif_quality),
&ngx_weserv_quality_bounds},

{ngx_string("weserv_jpeg_quality"),
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF |
NGX_HTTP_LIF_CONF | NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_weserv_loc_conf_t, api_conf.jpeg_quality),
&ngx_weserv_quality_bounds},

{ngx_string("weserv_tiff_quality"),
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF |
NGX_HTTP_LIF_CONF | NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_weserv_loc_conf_t, api_conf.tiff_quality),
&ngx_weserv_quality_bounds},

{ngx_string("weserv_webp_quality"),
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF |
NGX_HTTP_LIF_CONF | NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_weserv_loc_conf_t, api_conf.webp_quality),
&ngx_weserv_quality_bounds},

{ngx_string("weserv_avif_speed"),
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF |
NGX_HTTP_LIF_CONF | NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_weserv_loc_conf_t, api_conf.avif_speed),
&ngx_weserv_avif_speed_bounds},

{ngx_string("weserv_zlib_level"),
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF |
NGX_HTTP_LIF_CONF | NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_weserv_loc_conf_t, api_conf.zlib_level),
&ngx_weserv_zlib_level_bounds},

{ngx_string("weserv_fail_on_error"),
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF |
Expand Down Expand Up @@ -312,8 +365,13 @@ void *ngx_weserv_create_loc_conf(ngx_conf_t *cf) {
lc->api_conf.limit_input_pixels = NGX_CONF_UNSET_UINT;
lc->api_conf.limit_output_pixels = NGX_CONF_UNSET_UINT;
lc->api_conf.max_pages = NGX_CONF_UNSET;
lc->api_conf.default_quality = NGX_CONF_UNSET;
lc->api_conf.default_level = NGX_CONF_UNSET;
lc->api_conf.quality = NGX_CONF_UNSET;
lc->api_conf.avif_quality = NGX_CONF_UNSET;
lc->api_conf.jpeg_quality = NGX_CONF_UNSET;
lc->api_conf.tiff_quality = NGX_CONF_UNSET;
lc->api_conf.webp_quality = NGX_CONF_UNSET;
lc->api_conf.avif_speed = NGX_CONF_UNSET;
lc->api_conf.zlib_level = NGX_CONF_UNSET;
lc->api_conf.fail_on_error = NGX_CONF_UNSET;

return lc;
Expand Down Expand Up @@ -364,14 +422,23 @@ char *ngx_weserv_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) {
ngx_conf_merge_uint_value(conf->api_conf.limit_output_pixels,
prev->api_conf.limit_output_pixels, 71000000);

// The default quality of 85 usually produces excellent results
ngx_conf_merge_value(conf->api_conf.default_quality,
prev->api_conf.default_quality, 85);

// A default compromise between speed and compression
// (Z_DEFAULT_COMPRESSION)
ngx_conf_merge_value(conf->api_conf.default_level,
prev->api_conf.default_level, 6);
// The default quality of 80 usually produces excellent results
ngx_conf_merge_value(conf->api_conf.quality, prev->api_conf.quality, 80);
ngx_conf_merge_value(conf->api_conf.avif_quality,
prev->api_conf.avif_quality, conf->api_conf.quality);
ngx_conf_merge_value(conf->api_conf.jpeg_quality,
prev->api_conf.jpeg_quality, conf->api_conf.quality);
ngx_conf_merge_value(conf->api_conf.tiff_quality,
prev->api_conf.tiff_quality, conf->api_conf.quality);
ngx_conf_merge_value(conf->api_conf.webp_quality,
prev->api_conf.webp_quality, conf->api_conf.quality);

// A default compromise between speed and compression effectiveness
// (corresponds to the default values in libvips)
ngx_conf_merge_value(conf->api_conf.avif_speed, prev->api_conf.avif_speed,
5);
ngx_conf_merge_value(conf->api_conf.zlib_level, prev->api_conf.zlib_level,
6);

// Do a "best effort" to decode images, even if the data is corrupt or
// invalid
Expand Down
Binary file modified test/api/fixtures/expected/Landscape_1-out.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/api/fixtures/expected/Landscape_2-out.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/api/fixtures/expected/Landscape_3-out.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/api/fixtures/expected/Landscape_4-out.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/api/fixtures/expected/Landscape_5-out.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/api/fixtures/expected/Landscape_6-out.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/api/fixtures/expected/Landscape_7-out.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/api/fixtures/expected/Landscape_8-out.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/api/fixtures/expected/Portrait_1-out.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/api/fixtures/expected/Portrait_2-out.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/api/fixtures/expected/Portrait_3-out.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/api/fixtures/expected/Portrait_4-out.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/api/fixtures/expected/Portrait_5-out.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/api/fixtures/expected/Portrait_6-out.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/api/fixtures/expected/Portrait_7-out.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/api/fixtures/expected/Portrait_8-out.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/api/fixtures/expected/alpha-layer-2-trim-resize.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/api/fixtures/expected/blur-0.3.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/api/fixtures/expected/blur-1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/api/fixtures/expected/blur-10.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/api/fixtures/expected/blur-mild.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/api/fixtures/expected/colourspace.cmyk-without-profile.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/api/fixtures/expected/colourspace.cmyk.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/api/fixtures/expected/contrast-decrease.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/api/fixtures/expected/contrast-increase.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/api/fixtures/expected/crop-strategy-attention.jpg
Binary file modified test/api/fixtures/expected/crop-strategy-entropy.jpg
Binary file modified test/api/fixtures/expected/duotone.jpg
Binary file modified test/api/fixtures/expected/extract-resize.jpg
Binary file modified test/api/fixtures/expected/extract.jpg
Binary file modified test/api/fixtures/expected/extract.tiff
Binary file not shown.
Binary file modified test/api/fixtures/expected/extract.webp
Binary file not shown.
Binary file modified test/api/fixtures/expected/greyscale.jpg
Binary file modified test/api/fixtures/expected/heif-thumbnail.jpg
Binary file modified test/api/fixtures/expected/individual-page.webp
Binary file not shown.
Binary file modified test/api/fixtures/expected/modulate-all.jpg
Binary file modified test/api/fixtures/expected/modulate-brightness-0-5.jpg
Binary file modified test/api/fixtures/expected/modulate-brightness-2.jpg
Binary file modified test/api/fixtures/expected/modulate-hue-120.jpg
Binary file modified test/api/fixtures/expected/modulate-saturation-0.5.jpg
Binary file modified test/api/fixtures/expected/negate-trans.webp
Binary file not shown.
Binary file modified test/api/fixtures/expected/negate.jpg
Binary file modified test/api/fixtures/expected/negate.webp
Binary file not shown.
Binary file modified test/api/fixtures/expected/position-bottom.jpg
Binary file modified test/api/fixtures/expected/position-center.jpg
Binary file modified test/api/fixtures/expected/position-centre.jpg
Binary file modified test/api/fixtures/expected/position-left.jpg
Binary file modified test/api/fixtures/expected/position-right.jpg
Binary file modified test/api/fixtures/expected/position-top.jpg
Binary file modified test/api/fixtures/expected/radiance.jpg
Binary file modified test/api/fixtures/expected/resize-crop-extract.jpg
Binary file modified test/api/fixtures/expected/rotate-solid-bg.jpg
Binary file modified test/api/fixtures/expected/sepia.jpg
Binary file modified test/api/fixtures/expected/sharpen-10.jpg
Binary file modified test/api/fixtures/expected/sharpen-3-0.5-2.5.jpg
Binary file modified test/api/fixtures/expected/sharpen-5-2-4.jpg
Binary file modified test/api/fixtures/expected/sharpen-cmyk.jpg
Binary file modified test/api/fixtures/expected/sharpen-mild.jpg
Binary file modified test/api/fixtures/expected/tiff-pyramid.tiff
Binary file not shown.
Binary file modified test/api/fixtures/expected/tint-blue.jpg
Binary file modified test/api/fixtures/expected/tint-cmyk.jpg
Binary file modified test/api/fixtures/expected/tint-green.jpg
Binary file modified test/api/fixtures/expected/tint-red.jpg
Binary file modified test/api/fixtures/expected/tint-sepia.jpg

0 comments on commit 014da7f

Please sign in to comment.