Refactor: autoOrient() is primary, rotate() is alias

This commit is contained in:
Don Denton 2024-07-13 23:44:45 -04:00
parent 5afbe3a1d0
commit 8e7c7b4196
4 changed files with 46 additions and 53 deletions

View File

@ -1,19 +1,15 @@
## rotate ## rotate
> rotate([angle], [options]) ⇒ <code>Sharp</code> > rotate([angle], [options]) ⇒ <code>Sharp</code>
Rotate the output image by either an explicit angle Rotate the output image.
or auto-orient based on the EXIF `Orientation` tag.
If an angle is provided, it is converted to a valid positive degree rotation. The provided angle is converted to a valid positive degree rotation.
For example, `-450` will produce a 270 degree rotation. For example, `-450` will produce a 270 degree rotation.
When rotating by an angle other than a multiple of 90, When rotating by an angle other than a multiple of 90,
the background colour can be provided with the `background` option. the background colour can be provided with the `background` option.
If no angle is provided, it is determined from the EXIF data. For backwards compatibility, if no angle is provided, `.autoOrient()` will be called.
Mirroring is supported and may infer the use of a flip operation.
The use of `rotate` without an angle will remove the EXIF `Orientation` tag, if any.
Only one rotation can occur per pipeline (aside from an initial call without Only one rotation can occur per pipeline (aside from an initial call without
arguments to orient via EXIF data). Previous calls to `rotate` in the same arguments to orient via EXIF data). Previous calls to `rotate` in the same
@ -36,18 +32,6 @@ for example `.rotate(x).extract(y)` will produce a different result to `.extract
| [options] | <code>Object</code> | | if present, is an Object with optional attributes. | | [options] | <code>Object</code> | | if present, is an Object with optional attributes. |
| [options.background] | <code>string</code> \| <code>Object</code> | <code>&quot;\&quot;#000000\&quot;&quot;</code> | parsed by the [color](https://www.npmjs.org/package/color) module to extract values for red, green, blue and alpha. | | [options.background] | <code>string</code> \| <code>Object</code> | <code>&quot;\&quot;#000000\&quot;&quot;</code> | parsed by the [color](https://www.npmjs.org/package/color) module to extract values for red, green, blue and alpha. |
**Example**
```js
const pipeline = sharp()
.rotate()
.resize(null, 200)
.toBuffer(function (err, outputBuffer, info) {
// outputBuffer contains 200px high JPEG image data,
// auto-rotated using EXIF Orientation tag
// info.width and info.height contain the dimensions of the resized image
});
readableStream.pipe(pipeline);
```
**Example** **Example**
```js ```js
const rotateThenResize = await sharp(input) const rotateThenResize = await sharp(input)
@ -64,17 +48,29 @@ const resizeThenRotate = await sharp(input)
## autoOrient ## autoOrient
> autoOrient() ⇒ <code>Sharp</code> > autoOrient() ⇒ <code>Sharp</code>
Alias for calling `rotate()` with no arguments, which orients the image based Auto-orient based on the EXIF `Orientation` tag, then remove the tag.
on EXIF orientsion. Mirroring is supported and may infer the use of a flip operation.
This operation is aliased to emphasize its purpose, helping to remove any Previous or subsequent use of `rotate(angle)` and either `flip()` or `flop()`
confusion between rotation and orientation. will logically occur after auto-orientation, regardless of call order.
**Example** **Example**
```js ```js
const output = await sharp(input).autoOrient().toBuffer(); const output = await sharp(input).autoOrient().toBuffer();
``` ```
**Example**
```js
const pipeline = sharp()
.autoOrient()
.resize(null, 200)
.toBuffer(function (err, outputBuffer, info) {
// outputBuffer contains 200px high JPEG image data,
// auto-oriented using EXIF Orientation tag
// info.width and info.height contain the dimensions of the resized image
});
readableStream.pipe(pipeline);
```
## flip ## flip

File diff suppressed because one or more lines are too long

View File

@ -18,19 +18,15 @@ const vipsPrecision = {
}; };
/** /**
* Rotate the output image by either an explicit angle * Rotate the output image.
* or auto-orient based on the EXIF `Orientation` tag.
* *
* If an angle is provided, it is converted to a valid positive degree rotation. * The provided angle is converted to a valid positive degree rotation.
* For example, `-450` will produce a 270 degree rotation. * For example, `-450` will produce a 270 degree rotation.
* *
* When rotating by an angle other than a multiple of 90, * When rotating by an angle other than a multiple of 90,
* the background colour can be provided with the `background` option. * the background colour can be provided with the `background` option.
* *
* If no angle is provided, it is determined from the EXIF data. * For backwards compatibility, if no angle is provided, `.autoOrient()` will be called.
* Mirroring is supported and may infer the use of a flip operation.
*
* The use of `rotate` without an angle will remove the EXIF `Orientation` tag, if any.
* *
* Only one rotation can occur per pipeline (aside from an initial call without * Only one rotation can occur per pipeline (aside from an initial call without
* arguments to orient via EXIF data). Previous calls to `rotate` in the same * arguments to orient via EXIF data). Previous calls to `rotate` in the same
@ -42,17 +38,6 @@ const vipsPrecision = {
* for example `.rotate(x).extract(y)` will produce a different result to `.extract(y).rotate(x)`. * for example `.rotate(x).extract(y)` will produce a different result to `.extract(y).rotate(x)`.
* *
* @example * @example
* const pipeline = sharp()
* .rotate()
* .resize(null, 200)
* .toBuffer(function (err, outputBuffer, info) {
* // outputBuffer contains 200px high JPEG image data,
* // auto-rotated using EXIF Orientation tag
* // info.width and info.height contain the dimensions of the resized image
* });
* readableStream.pipe(pipeline);
*
* @example
* const rotateThenResize = await sharp(input) * const rotateThenResize = await sharp(input)
* .rotate(90) * .rotate(90)
* .resize({ width: 16, height: 8, fit: 'fill' }) * .resize({ width: 16, height: 8, fit: 'fill' })
@ -69,12 +54,12 @@ const vipsPrecision = {
* @throws {Error} Invalid parameters * @throws {Error} Invalid parameters
*/ */
function rotate (angle, options) { function rotate (angle, options) {
if (this.options.useExifOrientation || this.options.angle || this.options.rotationAngle) { if (!is.defined(angle)) { return this.autoOrient(); }
if (this.options.angle || this.options.rotationAngle) {
this.options.debuglog('ignoring previous rotate options'); this.options.debuglog('ignoring previous rotate options');
} }
if (!is.defined(angle)) { if (is.integer(angle) && !(angle % 90)) {
this.options.useExifOrientation = true;
} else if (is.integer(angle) && !(angle % 90)) {
this.options.angle = angle; this.options.angle = angle;
} else if (is.number(angle)) { } else if (is.number(angle)) {
this.options.rotationAngle = angle; this.options.rotationAngle = angle;
@ -94,19 +79,31 @@ function rotate (angle, options) {
} }
/** /**
* Alias for calling `rotate()` with no arguments, which orients the image based * Auto-orient based on the EXIF `Orientation` tag, then remove the tag.
* on EXIF orientsion. * Mirroring is supported and may infer the use of a flip operation.
* *
* This operation is aliased to emphasize its purpose, helping to remove any * Previous or subsequent use of `rotate(angle)` and either `flip()` or `flop()`
* confusion between rotation and orientation. * will logically occur after auto-orientation, regardless of call order.
* *
* @example * @example
* const output = await sharp(input).autoOrient().toBuffer(); * const output = await sharp(input).autoOrient().toBuffer();
* *
* @example
* const pipeline = sharp()
* .autoOrient()
* .resize(null, 200)
* .toBuffer(function (err, outputBuffer, info) {
* // outputBuffer contains 200px high JPEG image data,
* // auto-oriented using EXIF Orientation tag
* // info.width and info.height contain the dimensions of the resized image
* });
* readableStream.pipe(pipeline);
*
* @returns {Sharp} * @returns {Sharp}
*/ */
function autoOrient () { function autoOrient () {
return this.rotate(); this.options.useExifOrientation = true;
return this;
} }
/** /**

View File

@ -441,9 +441,9 @@ describe('Rotation', function () {
let warningMessage = ''; let warningMessage = '';
const s = sharp(); const s = sharp();
s.on('warning', function (msg) { warningMessage = msg; }); s.on('warning', function (msg) { warningMessage = msg; });
s.rotate(); s.rotate(90);
assert.strictEqual(warningMessage, ''); assert.strictEqual(warningMessage, '');
s.rotate(); s.rotate(180);
assert.strictEqual(warningMessage, 'ignoring previous rotate options'); assert.strictEqual(warningMessage, 'ignoring previous rotate options');
}); });