Skip to content

Commit

Permalink
Improve error for unsupported multi-page rotation #3940
Browse files Browse the repository at this point in the history
  • Loading branch information
lovell committed Jan 11, 2024
1 parent 45e8071 commit cbf68c1
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 0 deletions.
2 changes: 2 additions & 0 deletions docs/api-operation.md
Expand Up @@ -18,6 +18,8 @@ The use of `rotate` without an angle will remove the EXIF `Orientation` tag, if
Only one rotation can occur per pipeline.
Previous calls to `rotate` in the same pipeline will be ignored.

Multi-page images can only be rotated by 180 degrees.

Method order is important when rotating, resizing and/or extracting regions,
for example `.rotate(x).extract(y)` will produce a different result to `.extract(y).rotate(x)`.

Expand Down
3 changes: 3 additions & 0 deletions docs/changelog.md
Expand Up @@ -13,6 +13,9 @@ Requires libvips v8.15.0
* Ensure `extend` operation stays sequential when copying (regression in 0.32.0).
[#3928](https://github.com/lovell/sharp/issues/3928)

* Improve error handling for unsupported multi-page rotation.
[#3940](https://github.com/lovell/sharp/issues/3940)

### v0.33.1 - 17th December 2023

* Add support for Yarn Plug'n'Play filesystem layout.
Expand Down
2 changes: 2 additions & 0 deletions lib/operation.js
Expand Up @@ -24,6 +24,8 @@ const is = require('./is');
* Only one rotation can occur per pipeline.
* Previous calls to `rotate` in the same pipeline will be ignored.
*
* Multi-page images can only be rotated by 180 degrees.
*
* Method order is important when rotating, resizing and/or extracting regions,
* for example `.rotate(x).extract(y)` will produce a different result to `.extract(y).rotate(x)`.
*
Expand Down
12 changes: 12 additions & 0 deletions src/pipeline.cc
Expand Up @@ -96,6 +96,9 @@ class PipelineWorker : public Napi::AsyncWorker {
baton->rotationAngle != 0.0);

if (autoRotation != VIPS_ANGLE_D0) {
if (autoRotation != VIPS_ANGLE_D180) {
MultiPageUnsupported(nPages, "Rotate");
}
image = image.rot(autoRotation);
autoRotation = VIPS_ANGLE_D0;
}
Expand All @@ -114,6 +117,9 @@ class PipelineWorker : public Napi::AsyncWorker {
baton->flop = FALSE;
}
if (rotation != VIPS_ANGLE_D0) {
if (rotation != VIPS_ANGLE_D180) {
MultiPageUnsupported(nPages, "Rotate");
}
image = image.rot(rotation);
rotation = VIPS_ANGLE_D0;
}
Expand Down Expand Up @@ -397,6 +403,9 @@ class PipelineWorker : public Napi::AsyncWorker {
rotation != VIPS_ANGLE_D0);
// Auto-rotate post-extract
if (autoRotation != VIPS_ANGLE_D0) {
if (autoRotation != VIPS_ANGLE_D180) {
MultiPageUnsupported(nPages, "Rotate");
}
image = image.rot(autoRotation);
}
// Mirror vertically (up-down) about the x-axis
Expand All @@ -409,6 +418,9 @@ class PipelineWorker : public Napi::AsyncWorker {
}
// Rotate post-extract 90-angle
if (rotation != VIPS_ANGLE_D0) {
if (rotation != VIPS_ANGLE_D180) {
MultiPageUnsupported(nPages, "Rotate");
}
image = image.rot(rotation);
}

Expand Down
15 changes: 15 additions & 0 deletions test/unit/rotate.js
Expand Up @@ -353,6 +353,21 @@ describe('Rotation', function () {
)
);

it('Animated image rotate 180', () =>
assert.doesNotReject(() => sharp(fixtures.inputGifAnimated, { animated: true })
.rotate(180)
.toBuffer()
)
);

it('Animated image rotate non-180 rejects', () =>
assert.rejects(() => sharp(fixtures.inputGifAnimated, { animated: true })
.rotate(90)
.toBuffer(),
/Rotate is not supported for multi-page images/
)
);

it('Multiple rotate emits warning', () => {
let warningMessage = '';
const s = sharp();
Expand Down

0 comments on commit cbf68c1

Please sign in to comment.