From 690bc43abe9732994c0fa5d4dbc95a0e57380f2f Mon Sep 17 00:00:00 2001 From: Ilya Ovdin Date: Fri, 26 Jul 2019 22:28:45 +0300 Subject: [PATCH] Fix rotate/extract ordering for non-90 angles (#1755) --- lib/resize.js | 2 +- src/pipeline.cc | 26 ++++++++++++------- test/fixtures/expected/extract-rotate-45.jpg | Bin 0 -> 5416 bytes test/fixtures/expected/rotate-extract-45.jpg | Bin 0 -> 3485 bytes test/unit/extract.js | 26 +++++++++++++++++++ 5 files changed, 44 insertions(+), 10 deletions(-) create mode 100644 test/fixtures/expected/extract-rotate-45.jpg create mode 100644 test/fixtures/expected/rotate-extract-45.jpg diff --git a/lib/resize.js b/lib/resize.js index 8444fda5..76680ad4 100644 --- a/lib/resize.js +++ b/lib/resize.js @@ -353,7 +353,7 @@ function extract (options) { } }, this); // Ensure existing rotation occurs before pre-resize extraction - if (suffix === 'Pre' && ((this.options.angle % 360) !== 0 || this.options.useExifOrientation === true)) { + if (suffix === 'Pre' && ((this.options.angle % 360) !== 0 || this.options.useExifOrientation === true || this.options.rotationAngle !== 0)) { this.options.rotateBeforePreExtract = true; } return this; diff --git a/src/pipeline.cc b/src/pipeline.cc index bc5e67a6..a4e1b4e7 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -108,9 +108,16 @@ class PipelineWorker : public Nan::AsyncWorker { } // Rotate pre-extract - if (baton->rotateBeforePreExtract && rotation != VIPS_ANGLE_D0) { - image = image.rot(rotation); - sharp::RemoveExifOrientation(image); + if (baton->rotateBeforePreExtract) { + if (rotation != VIPS_ANGLE_D0) { + image = image.rot(rotation); + sharp::RemoveExifOrientation(image); + } + if (baton->rotationAngle != 0.0) { + std::vector background; + std::tie(image, background) = sharp::ApplyAlpha(image, baton->rotationBackground); + image = image.rotate(baton->rotationAngle, VImage::option()->set("background", background)); + } } // Trim @@ -403,12 +410,13 @@ class PipelineWorker : public Nan::AsyncWorker { ->set("kernel", kernel)); } - // Rotate - if (!baton->rotateBeforePreExtract && rotation != VIPS_ANGLE_D0) { - image = image.rot(rotation); - sharp::RemoveExifOrientation(image); + // Rotate post-extract 90-angle + if (!baton->rotateBeforePreExtract && rotation != VIPS_ANGLE_D0) { + image = image.rot(rotation); + sharp::RemoveExifOrientation(image); } + // Flip (mirror about Y axis) if (baton->flip) { image = image.flip(VIPS_DIRECTION_VERTICAL); @@ -491,8 +499,8 @@ class PipelineWorker : public Nan::AsyncWorker { } } - // Rotate by degree - if (baton->rotationAngle != 0.0) { + // Rotate post-extract non-90 angle + if (!baton->rotateBeforePreExtract && baton->rotationAngle != 0.0) { std::vector background; std::tie(image, background) = sharp::ApplyAlpha(image, baton->rotationBackground); image = image.rotate(baton->rotationAngle, VImage::option()->set("background", background)); diff --git a/test/fixtures/expected/extract-rotate-45.jpg b/test/fixtures/expected/extract-rotate-45.jpg new file mode 100644 index 0000000000000000000000000000000000000000..38efece21febc6b1d230fea74384c576208c4939 GIT binary patch literal 5416 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 literal 0 HcmV?d00001 diff --git a/test/fixtures/expected/rotate-extract-45.jpg b/test/fixtures/expected/rotate-extract-45.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e97349bdb8e15bfc3436ae5a688c644681eb8b5d GIT binary patch literal 3485 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