Skip to content

Commit 55afd03

Browse files
Add autoOrient to composite options
1 parent e88bb07 commit 55afd03

File tree

5 files changed

+36
-1
lines changed

5 files changed

+36
-1
lines changed

lib/composite.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ const blend = {
110110
* @param {number} [images[].input.text.dpi=72] - the resolution (size) at which to render the text. Does not take effect if `height` is specified.
111111
* @param {boolean} [images[].input.text.rgba=false] - set this to true to enable RGBA output. This is useful for colour emoji rendering, or support for Pango markup features like `<span foreground="red">Red!</span>`.
112112
* @param {number} [images[].input.text.spacing=0] - text line height in points. Will use the font line height if none is specified.
113+
* @param {Boolean} [images[].autoOrient=false] - set to true to use EXIF orientation data, if present, to orient the image.
113114
* @param {String} [images[].blend='over'] - how to blend this image with the image below.
114115
* @param {String} [images[].gravity='centre'] - gravity at which to place the overlay.
115116
* @param {Number} [images[].top] - the pixel offset from the top edge.
@@ -136,8 +137,11 @@ function composite (images) {
136137
throw is.invalidParameterError('image to composite', 'object', image);
137138
}
138139
const inputOptions = this._inputOptionsFromObject(image);
140+
const descriptor = this._createInputDescriptor(image.input, inputOptions, { allowStream: false });
141+
console.log('inputOptions', inputOptions);
142+
console.log('descriptor', descriptor);
139143
const composite = {
140-
input: this._createInputDescriptor(image.input, inputOptions, { allowStream: false }),
144+
input: descriptor,
141145
blend: 'over',
142146
tile: false,
143147
left: 0,

lib/input.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ function _inputOptionsFromObject (obj) {
3636
*/
3737
function _createInputDescriptor (input, inputOptions, containerOptions) {
3838
const inputDescriptor = {
39+
autoOrient: false,
3940
failOn: 'warning',
4041
limitInputPixels: Math.pow(0x3FFF, 2),
4142
ignoreIcc: false,

src/common.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ namespace sharp {
162162
descriptor->access = AttrAsBool(input, "sequentialRead") ? VIPS_ACCESS_SEQUENTIAL : VIPS_ACCESS_RANDOM;
163163
// Remove safety features and allow unlimited input
164164
descriptor->unlimited = AttrAsBool(input, "unlimited");
165+
// Use the EXIF orientation to auto orient the image
166+
descriptor->autoOrient = AttrAsBool(input, "autoOrient");
165167
return descriptor;
166168
}
167169

src/common.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ namespace sharp {
3737
struct InputDescriptor { // NOLINT(runtime/indentation_namespace)
3838
std::string name;
3939
std::string file;
40+
bool autoOrient;
4041
char *buffer;
4142
VipsFailOn failOn;
4243
uint64_t limitInputPixels;
@@ -76,6 +77,7 @@ namespace sharp {
7677
int textAutofitDpi;
7778

7879
InputDescriptor():
80+
autoOrient(false),
7981
buffer(nullptr),
8082
failOn(VIPS_FAIL_ON_WARNING),
8183
limitInputPixels(0x3FFF * 0x3FFF),

src/pipeline.cc

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,32 @@ class PipelineWorker : public Napi::AsyncWorker {
636636
composite->input->access = access;
637637
std::tie(compositeImage, compositeImageType) = sharp::OpenInput(composite->input);
638638
compositeImage = sharp::EnsureColourspace(compositeImage, baton->colourspacePipeline);
639+
640+
if (composite->input->autoOrient) {
641+
// Calculate angle of rotation
642+
VipsAngle compositeAutoRotation = VIPS_ANGLE_D0;
643+
bool compositeAutoFlip = false;
644+
bool compositeAutoFlop = false;
645+
646+
// Rotate and flip image according to Exif orientation
647+
std::tie(compositeAutoRotation, compositeAutoFlip, compositeAutoFlop) =
648+
CalculateExifRotationAndFlip(sharp::ExifOrientation(compositeImage));
649+
650+
compositeImage = sharp::RemoveExifOrientation(compositeImage);
651+
652+
if (compositeAutoRotation != VIPS_ANGLE_D0) {
653+
compositeImage = compositeImage.rot(compositeAutoRotation);
654+
}
655+
// Mirror vertically (up-down) about the x-axis
656+
if (compositeAutoFlip) {
657+
compositeImage = compositeImage.flip(VIPS_DIRECTION_VERTICAL);
658+
}
659+
// Mirror horizontally (left-right) about the y-axis
660+
if (compositeAutoFlop) {
661+
compositeImage = compositeImage.flip(VIPS_DIRECTION_HORIZONTAL);
662+
}
663+
}
664+
639665
// Verify within current dimensions
640666
if (compositeImage.width() > image.width() || compositeImage.height() > image.height()) {
641667
throw vips::VError("Image to composite must have same dimensions or smaller");

0 commit comments

Comments
 (0)