Simplify 90/270 orient-before-resize logic (#3762)

This commit is contained in:
Kleis Auke Wolthuizen 2023-08-15 08:56:07 +02:00 committed by GitHub
parent 5c19f6dd9b
commit a2cac61209
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 29 additions and 20 deletions

View File

@ -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;

View File

@ -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.

View File

@ -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;
@ -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;

View File

@ -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 })