mirror of
https://github.com/lovell/sharp.git
synced 2025-12-19 15:25:07 +01:00
Ensure op ordering is respected where possible #3319
Emit warnings when previous ops might be ignored Flip and flop now occur before rotate, if any
This commit is contained in:
@@ -18,8 +18,11 @@ const is = require('./is');
|
||||
*
|
||||
* The use of `rotate` implies the removal of the EXIF `Orientation` tag, if any.
|
||||
*
|
||||
* Method order is important when both rotating and extracting regions,
|
||||
* for example `rotate(x).extract(y)` will produce a different result to `extract(y).rotate(x)`.
|
||||
* Only one rotation can occur per pipeline.
|
||||
* Previous calls to `rotate` in the same pipeline will be ignored.
|
||||
*
|
||||
* 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)`.
|
||||
*
|
||||
* @example
|
||||
* const pipeline = sharp()
|
||||
@@ -32,6 +35,16 @@ const is = require('./is');
|
||||
* });
|
||||
* readableStream.pipe(pipeline);
|
||||
*
|
||||
* @example
|
||||
* const rotateThenResize = await sharp(input)
|
||||
* .rotate(90)
|
||||
* .resize({ width: 16, height: 8, fit: 'fill' })
|
||||
* .toBuffer();
|
||||
* const resizeThenRotate = await sharp(input)
|
||||
* .resize({ width: 16, height: 8, fit: 'fill' })
|
||||
* .rotate(90)
|
||||
* .toBuffer();
|
||||
*
|
||||
* @param {number} [angle=auto] angle of rotation.
|
||||
* @param {Object} [options] - if present, is an Object with optional attributes.
|
||||
* @param {string|Object} [options.background="#000000"] parsed by the [color](https://www.npmjs.org/package/color) module to extract values for red, green, blue and alpha.
|
||||
@@ -39,6 +52,9 @@ const is = require('./is');
|
||||
* @throws {Error} Invalid parameters
|
||||
*/
|
||||
function rotate (angle, options) {
|
||||
if (this.options.useExifOrientation || this.options.angle || this.options.rotationAngle) {
|
||||
this.options.debuglog('ignoring previous rotate options');
|
||||
}
|
||||
if (!is.defined(angle)) {
|
||||
this.options.useExifOrientation = true;
|
||||
} else if (is.integer(angle) && !(angle % 90)) {
|
||||
@@ -61,7 +77,7 @@ function rotate (angle, options) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Flip the image about the vertical Y axis. This always occurs after rotation, if any.
|
||||
* Flip the image about the vertical Y axis. This always occurs before rotation, if any.
|
||||
* The use of `flip` implies the removal of the EXIF `Orientation` tag, if any.
|
||||
*
|
||||
* @example
|
||||
@@ -76,7 +92,7 @@ function flip (flip) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Flop the image about the horizontal X axis. This always occurs after rotation, if any.
|
||||
* Flop the image about the horizontal X axis. This always occurs before rotation, if any.
|
||||
* The use of `flop` implies the removal of the EXIF `Orientation` tag, if any.
|
||||
*
|
||||
* @example
|
||||
|
||||
@@ -92,6 +92,13 @@ function isRotationExpected (options) {
|
||||
return (options.angle % 360) !== 0 || options.useExifOrientation === true || options.rotationAngle !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
function isResizeExpected (options) {
|
||||
return options.width !== -1 || options.height !== -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize image to `width`, `height` or `width x height`.
|
||||
*
|
||||
@@ -123,6 +130,9 @@ function isRotationExpected (options) {
|
||||
* - `lanczos2`: Use a [Lanczos kernel](https://en.wikipedia.org/wiki/Lanczos_resampling#Lanczos_kernel) with `a=2`.
|
||||
* - `lanczos3`: Use a Lanczos kernel with `a=3` (the default).
|
||||
*
|
||||
* Only one resize can occur per pipeline.
|
||||
* Previous calls to `resize` in the same pipeline will be ignored.
|
||||
*
|
||||
* @example
|
||||
* sharp(input)
|
||||
* .resize({ width: 100 })
|
||||
@@ -220,6 +230,9 @@ function isRotationExpected (options) {
|
||||
* @throws {Error} Invalid parameters
|
||||
*/
|
||||
function resize (width, height, options) {
|
||||
if (isResizeExpected(this.options)) {
|
||||
this.options.debuglog('ignoring previous resize options');
|
||||
}
|
||||
if (is.defined(width)) {
|
||||
if (is.object(width) && !is.defined(options)) {
|
||||
options = width;
|
||||
@@ -300,6 +313,9 @@ function resize (width, height, options) {
|
||||
this._setBooleanOption('fastShrinkOnLoad', options.fastShrinkOnLoad);
|
||||
}
|
||||
}
|
||||
if (isRotationExpected(this.options) && isResizeExpected(this.options)) {
|
||||
this.options.rotateBeforePreExtract = true;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -412,7 +428,10 @@ function extend (extend) {
|
||||
* @throws {Error} Invalid parameters
|
||||
*/
|
||||
function extract (options) {
|
||||
const suffix = this.options.width === -1 && this.options.height === -1 ? 'Pre' : 'Post';
|
||||
const suffix = isResizeExpected(this.options) || isRotationExpected(this.options) ? 'Post' : 'Pre';
|
||||
if (this.options[`width${suffix}`] !== -1) {
|
||||
this.options.debuglog('ignoring previous extract options');
|
||||
}
|
||||
['left', 'top', 'width', 'height'].forEach(function (name) {
|
||||
const value = options[name];
|
||||
if (is.integer(value) && value >= 0) {
|
||||
@@ -422,8 +441,10 @@ function extract (options) {
|
||||
}
|
||||
}, this);
|
||||
// Ensure existing rotation occurs before pre-resize extraction
|
||||
if (suffix === 'Pre' && isRotationExpected(this.options)) {
|
||||
this.options.rotateBeforePreExtract = true;
|
||||
if (isRotationExpected(this.options) && !isResizeExpected(this.options)) {
|
||||
if (this.options.widthPre === -1 || this.options.widthPost === -1) {
|
||||
this.options.rotateBeforePreExtract = true;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user