diff --git a/docs/changelog.md b/docs/changelog.md index fe07427c..c90427e0 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -4,6 +4,11 @@ Requires libvips v8.12.2 +### v0.30.1 - TBD + +* Skip shrink-on-load for known libjpeg rounding errors. + [#3066](https://github.com/lovell/sharp/issues/3066) + ### v0.30.0 - 1st February 2022 * Add support for GIF output to prebuilt binaries. diff --git a/src/pipeline.cc b/src/pipeline.cc index c6239ccf..4c35876d 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -193,6 +193,10 @@ class PipelineWorker : public Napi::AsyncWorker { } else if (shrink >= 2 * factor) { jpegShrinkOnLoad = 2; } + // Skip shrink-on-load for known libjpeg rounding errors + if (jpegShrinkOnLoad > 1 && shrink == jpegShrinkOnLoad) { + jpegShrinkOnLoad /= 2; + } } else if (inputImageType == sharp::ImageType::WEBP || inputImageType == sharp::ImageType::SVG || inputImageType == sharp::ImageType::PDF) { diff --git a/test/unit/resize.js b/test/unit/resize.js index fa0eb66b..b2777bfd 100644 --- a/test/unit/resize.js +++ b/test/unit/resize.js @@ -780,6 +780,27 @@ describe('Resize dimensions', function () { assert.strictEqual(info.height, 1); }); + it('Skip JPEG shrink-on-load for known libjpeg rounding errors', async () => { + const input = await sharp({ + create: { + width: 1000, + height: 667, + channels: 3, + background: 'red' + } + }) + .jpeg() + .toBuffer(); + + const output = await sharp(input) + .resize({ width: 500 }) + .toBuffer(); + + const { width, height } = await sharp(output).metadata(); + assert.strictEqual(width, 500); + assert.strictEqual(height, 334); + }); + it('unknown kernel throws', function () { assert.throws(function () { sharp().resize(null, null, { kernel: 'unknown' });