Skip to content

Commit

Permalink
Simplify 90/270 orient-before-resize logic (#3762)
Browse files Browse the repository at this point in the history
  • Loading branch information
kleisauke committed Aug 15, 2023
1 parent 5c19f6d commit a2cac61
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 20 deletions.
10 changes: 1 addition & 9 deletions src/common.cc
Expand Up @@ -964,15 +964,7 @@ namespace sharp {
}

std::pair<double, double> ResolveShrink(int width, int height, int targetWidth, int targetHeight,
Canvas canvas, bool swap, bool withoutEnlargement, bool withoutReduction) {
if (swap && canvas != Canvas::IGNORE_ASPECT) {
// Swap input width and height when requested.
std::swap(width, height);
if (canvas == Canvas::MAX) {
std::swap(targetWidth, targetHeight);
}
}

Canvas canvas, bool withoutEnlargement, bool withoutReduction) {
double hshrink = 1.0;
double vshrink = 1.0;

Expand Down
7 changes: 2 additions & 5 deletions src/common.h
Expand Up @@ -362,13 +362,10 @@ namespace sharp {
VImage EnsureAlpha(VImage image, double const value);

/*
Calculate the shrink factor, taking into account auto-rotate, the canvas
mode, and so on. The hshrink/vshrink are the amount to shrink the input
image axes by in order for the output axes (ie. after rotation) to match
the required thumbnail width/height and canvas mode.
Calculate the horizontal and vertical shrink factors, taking the canvas mode into account.
*/
std::pair<double, double> ResolveShrink(int width, int height, int targetWidth, int targetHeight,
Canvas canvas, bool swap, bool withoutEnlargement, bool withoutReduction);
Canvas canvas, bool withoutEnlargement, bool withoutReduction);

/*
Ensure decoding remains sequential.
Expand Down
15 changes: 9 additions & 6 deletions src/pipeline.cc
Expand Up @@ -157,15 +157,18 @@ class PipelineWorker : public Napi::AsyncWorker {
int targetResizeWidth = baton->width;
int targetResizeHeight = baton->height;

// Swap input output width and height when rotating by 90 or 270 degrees
bool swap = !baton->rotateBeforePreExtract &&
(rotation == VIPS_ANGLE_D90 || rotation == VIPS_ANGLE_D270 ||
autoRotation == VIPS_ANGLE_D90 || autoRotation == VIPS_ANGLE_D270);
// When auto-rotating by 90 or 270 degrees, swap the target width and
// height to ensure the behavior aligns with how it would have been if
// the rotation had taken place *before* resizing.
if (!baton->rotateBeforePreExtract &&
(autoRotation == VIPS_ANGLE_D90 || autoRotation == VIPS_ANGLE_D270)) {
std::swap(targetResizeWidth, targetResizeHeight);
}

// Shrink to pageHeight, so we work for multi-page images
std::tie(hshrink, vshrink) = sharp::ResolveShrink(
inputWidth, pageHeight, targetResizeWidth, targetResizeHeight,
baton->canvas, swap, baton->withoutEnlargement, baton->withoutReduction);
baton->canvas, baton->withoutEnlargement, baton->withoutReduction);

// The jpeg preload shrink.
int jpegShrinkOnLoad = 1;
Expand Down Expand Up @@ -299,7 +302,7 @@ class PipelineWorker : public Napi::AsyncWorker {
// Shrink to pageHeight, so we work for multi-page images
std::tie(hshrink, vshrink) = sharp::ResolveShrink(
inputWidth, pageHeight, targetResizeWidth, targetResizeHeight,
baton->canvas, swap, baton->withoutEnlargement, baton->withoutReduction);
baton->canvas, baton->withoutEnlargement, baton->withoutReduction);

int targetHeight = static_cast<int>(std::rint(static_cast<double>(pageHeight) / vshrink));
int targetPageHeight = targetHeight;
Expand Down
17 changes: 17 additions & 0 deletions test/unit/rotate.js
Expand Up @@ -192,6 +192,23 @@ describe('Rotation', function () {
});
});

it('Auto-rotate by 270 degrees, rectangular output ignoring aspect ratio', function (done) {
sharp(fixtures.inputJpgWithLandscapeExif8)
.resize(320, 240, { fit: sharp.fit.fill })
.rotate()
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual(320, info.width);
assert.strictEqual(240, info.height);
sharp(data).metadata(function (err, metadata) {
if (err) throw err;
assert.strictEqual(320, metadata.width);
assert.strictEqual(240, metadata.height);
done();
});
});
});

it('Rotate by 30 degrees, rectangular output ignoring aspect ratio', function (done) {
sharp(fixtures.inputJpg)
.resize(320, 240, { fit: sharp.fit.fill })
Expand Down

0 comments on commit a2cac61

Please sign in to comment.