diff --git a/lib/constructor.js b/lib/constructor.js index 2031359b..bdf10776 100644 --- a/lib/constructor.js +++ b/lib/constructor.js @@ -362,6 +362,7 @@ const Sharp = function (input, options) { } }; this.options.input = this._createInputDescriptor(input, options, { allowStream: true }); + this.options.useExifOrientation = !!this.options.input.autoOrient; return this; }; Object.setPrototypeOf(Sharp.prototype, stream.Duplex.prototype); diff --git a/lib/index.d.ts b/lib/index.d.ts index a33008bd..27631e2b 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -948,6 +948,13 @@ declare namespace sharp { } interface SharpOptions { + /** + * Auto-orient based on the EXIF `Orientation` tag, if present. + * Mirroring is supported and may infer the use of a flip operation. + * + * Using this option will remove the EXIF `Orientation` tag, if any. + */ + autoOrient?: boolean; /** * When to abort processing of invalid pixel data, one of (in order of sensitivity): * 'none' (least), 'truncated', 'error' or 'warning' (most), highers level imply lower levels, invalid metadata will always abort. (optional, default 'warning') diff --git a/lib/input.js b/lib/input.js index 3a1562d4..41233094 100644 --- a/lib/input.js +++ b/lib/input.js @@ -24,9 +24,9 @@ const align = { * @private */ function _inputOptionsFromObject (obj) { - const { raw, density, limitInputPixels, ignoreIcc, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd, pdfBackground } = obj; - return [raw, density, limitInputPixels, ignoreIcc, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd, pdfBackground].some(is.defined) - ? { raw, density, limitInputPixels, ignoreIcc, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd, pdfBackground } + const { raw, density, limitInputPixels, ignoreIcc, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd, pdfBackground, autoOrient } = obj; + return [raw, density, limitInputPixels, ignoreIcc, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd, pdfBackground, autoOrient].some(is.defined) + ? { raw, density, limitInputPixels, ignoreIcc, unlimited, sequentialRead, failOn, failOnError, animated, page, pages, subifd, pdfBackground, autoOrient } : undefined; } @@ -93,6 +93,14 @@ function _createInputDescriptor (input, inputOptions, containerOptions) { throw is.invalidParameterError('failOn', 'one of: none, truncated, error, warning', inputOptions.failOn); } } + // autoOrient + if (is.defined(inputOptions.autoOrient)) { + if (is.bool(inputOptions.autoOrient)) { + inputDescriptor.autoOrient = inputOptions.autoOrient; + } else { + throw is.invalidParameterError('autoOrient', 'boolean', inputOptions.autoOrient); + } + } // Density if (is.defined(inputOptions.density)) { if (is.inRange(inputOptions.density, 1, 100000)) {