diff --git a/docs/api-resize.md b/docs/api-resize.md
index 6dc78ead1..8f0d7d20f 100644
--- a/docs/api-resize.md
+++ b/docs/api-resize.md
@@ -21,18 +21,22 @@ When using a **fit** of `cover` or `contain`, the default **position** is `centr
Some of these values are based on the [object-position](https://developer.mozilla.org/en-US/docs/Web/CSS/object-position) CSS property.
-The experimental strategy-based approach resizes so one dimension is at its target length
+The strategy-based approach initially resizes so one dimension is at its target length
then repeatedly ranks edge regions, discarding the edge with the lowest score based on the selected strategy.
- `entropy`: focus on the region with the highest [Shannon entropy](https://en.wikipedia.org/wiki/Entropy_%28information_theory%29).
- `attention`: focus on the region with the highest luminance frequency, colour saturation and presence of skin tones.
-Possible interpolation kernels are:
+Possible downsizing kernels are:
- `nearest`: Use [nearest neighbour interpolation](http://en.wikipedia.org/wiki/Nearest-neighbor_interpolation).
+- `linear`: Use a [triangle filter](https://en.wikipedia.org/wiki/Triangular_function).
- `cubic`: Use a [Catmull-Rom spline](https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline).
- `mitchell`: Use a [Mitchell-Netravali spline](https://www.cs.utexas.edu/~fussell/courses/cs384g-fall2013/lectures/mitchell/Mitchell.pdf).
- `lanczos2`: Use a [Lanczos kernel](https://en.wikipedia.org/wiki/Lanczos_resampling#Lanczos_kernel) with `a=2`.
- `lanczos3`: Use a Lanczos kernel with `a=3` (the default).
+When upsampling, these kernels map to `nearest`, `linear` and `cubic` interpolators.
+Downsampling kernels without a matching upsampling interpolator map to `cubic`.
+
Only one resize can occur per pipeline.
Previous calls to `resize` in the same pipeline will be ignored.
@@ -52,7 +56,7 @@ Previous calls to `resize` in the same pipeline will be ignored.
| [options.fit] | String
| 'cover'
| How the image should be resized/cropped to fit the target dimension(s), one of `cover`, `contain`, `fill`, `inside` or `outside`. |
| [options.position] | String
| 'centre'
| A position, gravity or strategy to use when `fit` is `cover` or `contain`. |
| [options.background] | String
\| Object
| {r: 0, g: 0, b: 0, alpha: 1}
| background colour when `fit` is `contain`, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to black without transparency. |
-| [options.kernel] | String
| 'lanczos3'
| The kernel to use for image reduction. Use the `fastShrinkOnLoad` option to control kernel vs shrink-on-load. |
+| [options.kernel] | String
| 'lanczos3'
| The kernel to use for image reduction and the inferred interpolator to use for upsampling. Use the `fastShrinkOnLoad` option to control kernel vs shrink-on-load. |
| [options.withoutEnlargement] | Boolean
| false
| Do not scale up if the width *or* height are already less than the target dimensions, equivalent to GraphicsMagick's `>` geometry option. This may result in output dimensions smaller than the target dimensions. |
| [options.withoutReduction] | Boolean
| false
| Do not scale down if the width *or* height are already greater than the target dimensions, equivalent to GraphicsMagick's `<` geometry option. This may still result in a crop to reach the target dimensions. |
| [options.fastShrinkOnLoad] | Boolean
| true
| Take greater advantage of the JPEG and WebP shrink-on-load feature, which can lead to a slight moiré pattern or round-down of an auto-scaled dimension. |
diff --git a/docs/changelog.md b/docs/changelog.md
index a359cda98..ab64857cc 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -10,6 +10,9 @@ Requires libvips v8.15.2
[#4048](https://github.com/lovell/sharp/pull/4048)
[@ike-gg](https://github.com/ike-gg)
+* Expose `bilinear` resizing kernel (and interpolator).
+ [#4061](https://github.com/lovell/sharp/issues/4061)
+
### v0.33.3 - 23rd March 2024
* Upgrade to libvips v8.15.2 for upstream bug fixes.
diff --git a/lib/resize.js b/lib/resize.js
index e4fcdd616..e31f85271 100644
--- a/lib/resize.js
+++ b/lib/resize.js
@@ -68,6 +68,7 @@ const strategy = {
*/
const kernel = {
nearest: 'nearest',
+ linear: 'linear',
cubic: 'cubic',
mitchell: 'mitchell',
lanczos2: 'lanczos2',
@@ -135,18 +136,22 @@ function isResizeExpected (options) {
*
* Some of these values are based on the [object-position](https://developer.mozilla.org/en-US/docs/Web/CSS/object-position) CSS property.
*
- * The experimental strategy-based approach resizes so one dimension is at its target length
+ * The strategy-based approach initially resizes so one dimension is at its target length
* then repeatedly ranks edge regions, discarding the edge with the lowest score based on the selected strategy.
* - `entropy`: focus on the region with the highest [Shannon entropy](https://en.wikipedia.org/wiki/Entropy_%28information_theory%29).
* - `attention`: focus on the region with the highest luminance frequency, colour saturation and presence of skin tones.
*
- * Possible interpolation kernels are:
+ * Possible downsizing kernels are:
* - `nearest`: Use [nearest neighbour interpolation](http://en.wikipedia.org/wiki/Nearest-neighbor_interpolation).
+ * - `linear`: Use a [triangle filter](https://en.wikipedia.org/wiki/Triangular_function).
* - `cubic`: Use a [Catmull-Rom spline](https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline).
* - `mitchell`: Use a [Mitchell-Netravali spline](https://www.cs.utexas.edu/~fussell/courses/cs384g-fall2013/lectures/mitchell/Mitchell.pdf).
* - `lanczos2`: Use a [Lanczos kernel](https://en.wikipedia.org/wiki/Lanczos_resampling#Lanczos_kernel) with `a=2`.
* - `lanczos3`: Use a Lanczos kernel with `a=3` (the default).
*
+ * When upsampling, these kernels map to `nearest`, `linear` and `cubic` interpolators.
+ * Downsampling kernels without a matching upsampling interpolator map to `cubic`.
+ *
* Only one resize can occur per pipeline.
* Previous calls to `resize` in the same pipeline will be ignored.
*
@@ -239,7 +244,7 @@ function isResizeExpected (options) {
* @param {String} [options.fit='cover'] - How the image should be resized/cropped to fit the target dimension(s), one of `cover`, `contain`, `fill`, `inside` or `outside`.
* @param {String} [options.position='centre'] - A position, gravity or strategy to use when `fit` is `cover` or `contain`.
* @param {String|Object} [options.background={r: 0, g: 0, b: 0, alpha: 1}] - background colour when `fit` is `contain`, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to black without transparency.
- * @param {String} [options.kernel='lanczos3'] - The kernel to use for image reduction. Use the `fastShrinkOnLoad` option to control kernel vs shrink-on-load.
+ * @param {String} [options.kernel='lanczos3'] - The kernel to use for image reduction and the inferred interpolator to use for upsampling. Use the `fastShrinkOnLoad` option to control kernel vs shrink-on-load.
* @param {Boolean} [options.withoutEnlargement=false] - Do not scale up if the width *or* height are already less than the target dimensions, equivalent to GraphicsMagick's `>` geometry option. This may result in output dimensions smaller than the target dimensions.
* @param {Boolean} [options.withoutReduction=false] - Do not scale down if the width *or* height are already greater than the target dimensions, equivalent to GraphicsMagick's `<` geometry option. This may still result in a crop to reach the target dimensions.
* @param {Boolean} [options.fastShrinkOnLoad=true] - Take greater advantage of the JPEG and WebP shrink-on-load feature, which can lead to a slight moiré pattern or round-down of an auto-scaled dimension.