From fbd4970b5717a08bd6ea29d366b8ed0acc9b4d74 Mon Sep 17 00:00:00 2001 From: Lovell Fuller Date: Wed, 7 Sep 2022 14:17:40 +0100 Subject: [PATCH] Ensure auto-rotation works with shrink-on-load #3352 Fixes regression in 0.31.0 --- docs/changelog.md | 3 +++ lib/resize.js | 2 +- src/common.cc | 1 + src/pipeline.cc | 7 +++++-- test/unit/extract.js | 4 ++-- test/unit/rotate.js | 12 ++++++++++++ 6 files changed, 24 insertions(+), 5 deletions(-) diff --git a/docs/changelog.md b/docs/changelog.md index c587d333..811e0bac 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -10,6 +10,9 @@ Requires libvips v8.13.1 [#3349](https://github.com/lovell/sharp/pull/3349) [@marcosc90](https://github.com/marcosc90) +* Ensure auto-rotation works with shrink-on-load and extract (regression in 0.31.0). + [#3352](https://github.com/lovell/sharp/issues/3352) + ### v0.31.0 - 5th September 2022 * Drop support for Node.js 12, now requires Node.js >= 14.15.0. diff --git a/lib/resize.js b/lib/resize.js index 161c9f2c..e5bc4596 100644 --- a/lib/resize.js +++ b/lib/resize.js @@ -428,7 +428,7 @@ function extend (extend) { * @throws {Error} Invalid parameters */ function extract (options) { - const suffix = isResizeExpected(this.options) || isRotationExpected(this.options) ? 'Post' : 'Pre'; + const suffix = isResizeExpected(this.options) || this.options.widthPre !== -1 ? 'Post' : 'Pre'; if (this.options[`width${suffix}`] !== -1) { this.options.debuglog('ignoring previous extract options'); } diff --git a/src/common.cc b/src/common.cc index 00ad47dc..0c6302a3 100644 --- a/src/common.cc +++ b/src/common.cc @@ -557,6 +557,7 @@ namespace sharp { VImage RemoveExifOrientation(VImage image) { VImage copy = image.copy(); copy.remove(VIPS_META_ORIENTATION); + copy.remove("exif-ifd0-Orientation"); return copy; } diff --git a/src/pipeline.cc b/src/pipeline.cc index db52063d..5209d46b 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -92,7 +92,10 @@ class PipelineWorker : public Napi::AsyncWorker { } // Rotate pre-extract - if (baton->rotateBeforePreExtract) { + bool const shouldRotateBefore = baton->rotateBeforePreExtract && + (rotation != VIPS_ANGLE_D0 || flip || flop || baton->rotationAngle != 0.0); + + if (shouldRotateBefore) { if (rotation != VIPS_ANGLE_D0) { image = image.rot(rotation); } @@ -167,7 +170,7 @@ class PipelineWorker : public Napi::AsyncWorker { // - input colourspace is not specified; bool const shouldPreShrink = (targetResizeWidth > 0 || targetResizeHeight > 0) && baton->gamma == 0 && baton->topOffsetPre == -1 && baton->trimThreshold == 0.0 && - baton->colourspaceInput == VIPS_INTERPRETATION_LAST; + baton->colourspaceInput == VIPS_INTERPRETATION_LAST && !shouldRotateBefore; if (shouldPreShrink) { // The common part of the shrink: the bit by which both axes must be shrunk diff --git a/test/unit/extract.js b/test/unit/extract.js index cd064ef3..eb51fc82 100644 --- a/test/unit/extract.js +++ b/test/unit/extract.js @@ -300,7 +300,7 @@ describe('Partial image extraction', function () { const s = sharp(); s.on('warning', function (msg) { warningMessage = msg; }); const options = { top: 0, left: 0, width: 1, height: 1 }; - s.extract(options); + s.extract(options).extract(options); assert.strictEqual(warningMessage, ''); s.extract(options); assert.strictEqual(warningMessage, 'ignoring previous extract options'); @@ -311,7 +311,7 @@ describe('Partial image extraction', function () { const s = sharp().rotate(); s.on('warning', function (msg) { warningMessage = msg; }); const options = { top: 0, left: 0, width: 1, height: 1 }; - s.extract(options); + s.extract(options).extract(options); assert.strictEqual(warningMessage, ''); s.extract(options); assert.strictEqual(warningMessage, 'ignoring previous extract options'); diff --git a/test/unit/rotate.js b/test/unit/rotate.js index b7dae87a..7f4946fc 100644 --- a/test/unit/rotate.js +++ b/test/unit/rotate.js @@ -406,4 +406,16 @@ describe('Rotation', function () { fixtures.assertSimilar(fixtures.expected('rotate-and-flop.jpg'), data, done); }); }); + + it('Auto-rotate and shrink-on-load', async () => { + const [r, g, b] = await sharp(fixtures.inputJpgWithLandscapeExif3) + .rotate() + .resize(8) + .raw() + .toBuffer(); + + assert.strictEqual(r, 60); + assert.strictEqual(g, 73); + assert.strictEqual(b, 52); + }); });