From d8f129851110a59916cd12352b8e6b06b37411bc Mon Sep 17 00:00:00 2001 From: Lovell Fuller Date: Sat, 8 Jan 2022 18:48:11 +0000 Subject: [PATCH] Ensure rotate-then-extract works with EXIF mirroring #3024 --- docs/changelog.md | 3 ++ src/pipeline.cc | 33 ++++++++++++------ .../expected/rotate-mirror-extract.jpg | Bin 0 -> 1457 bytes test/unit/extract.js | 10 ++++++ 4 files changed, 36 insertions(+), 10 deletions(-) create mode 100644 test/fixtures/expected/rotate-mirror-extract.jpg diff --git a/docs/changelog.md b/docs/changelog.md index c54b2a17..d2e1d042 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -43,6 +43,9 @@ Requires libvips v8.12.1 [#3006](https://github.com/lovell/sharp/pull/3006) [@christopherbradleybanks](https://github.com/christopherbradleybanks) +* Ensure rotate-then-extract works with EXIF mirroring. + [#3024](https://github.com/lovell/sharp/issues/3024) + ## v0.29 - *circle* Requires libvips v8.11.3 diff --git a/src/pipeline.cc b/src/pipeline.cc index b88d8944..23988535 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -80,13 +80,11 @@ class PipelineWorker : public Napi::AsyncWorker { // Calculate angle of rotation VipsAngle rotation; + bool flip = FALSE; + bool flop = FALSE; if (baton->useExifOrientation) { // Rotate and flip image according to Exif orientation - bool flip; - bool flop; std::tie(rotation, flip, flop) = CalculateExifRotationAndFlip(sharp::ExifOrientation(image)); - baton->flip = baton->flip || flip; - baton->flop = baton->flop || flop; } else { rotation = CalculateAngleRotation(baton->angle); } @@ -95,6 +93,14 @@ class PipelineWorker : public Napi::AsyncWorker { if (baton->rotateBeforePreExtract) { if (rotation != VIPS_ANGLE_D0) { image = image.rot(rotation); + if (flip) { + image = image.flip(VIPS_DIRECTION_VERTICAL); + flip = FALSE; + } + if (flop) { + image = image.flip(VIPS_DIRECTION_HORIZONTAL); + flop = FALSE; + } image = sharp::RemoveExifOrientation(image); } if (baton->rotationAngle != 0.0) { @@ -384,20 +390,27 @@ class PipelineWorker : public Napi::AsyncWorker { } // Rotate post-extract 90-angle - if (!baton->rotateBeforePreExtract && rotation != VIPS_ANGLE_D0) { - image = image.rot(rotation); - image = sharp::RemoveExifOrientation(image); + if (!baton->rotateBeforePreExtract && rotation != VIPS_ANGLE_D0) { + image = image.rot(rotation); + if (flip) { + image = image.flip(VIPS_DIRECTION_VERTICAL); + flip = FALSE; + } + if (flop) { + image = image.flip(VIPS_DIRECTION_HORIZONTAL); + flop = FALSE; + } + image = sharp::RemoveExifOrientation(image); } - // Flip (mirror about Y axis) - if (baton->flip) { + if (baton->flip || flip) { image = image.flip(VIPS_DIRECTION_VERTICAL); image = sharp::RemoveExifOrientation(image); } // Flop (mirror about X axis) - if (baton->flop) { + if (baton->flop || flop) { image = image.flip(VIPS_DIRECTION_HORIZONTAL); image = sharp::RemoveExifOrientation(image); } diff --git a/test/fixtures/expected/rotate-mirror-extract.jpg b/test/fixtures/expected/rotate-mirror-extract.jpg new file mode 100644 index 0000000000000000000000000000000000000000..46d5a93b65106352fbc2e83599a9a742fb6930a1 GIT binary patch literal 1457 zcmb7+doEgO8FrHArJ_p1X3P} zl&7d*RVe>E;&uQn0Z;&Q2uK3}qd^cfNZbM7000aDfk42oz~BHB0g(Xjj{33y2nvFL zp)e>2_7ebsAy707fXm6NV>I*+Bi#KXGbI!Z46!7ufTaB0iwfwc@0Se#ATSUZ3czO%LkTFH0mJOfRjzvj1=Vc!Hr!gcV&4n9+GCQuf=4U;DApwr`9uwhW z!%s$6D&4)UlCoYlUdU+RGpVpnvd&-a&npGDX{pLKth+>dLHvJixt07^+cNqnUbdWsCS3D2yLa6x+R=ExbB^o&zxN>f4|cl9~R*J zT7BOOewA_}SdKRkW~9U4*a|Z=l{6gp-p8ZAsrFza{p9D%JFVZTac{o7IYUeA@WhU_ zwl@}D&b_25T(~dstPI`Cau_l7nj?J;G*}EgP<@PA)svF{VQNeam<_Da*q0xW>P1P% zn|!H0*9bOt=f%K+!n0(rGc9EYaBB(la~lKaF3qyHEw0t(Ubm*r3ORB&y=+@o) z#>#1*suB&^m|rdKYdWYk$Ru^d97xR8eRafyPu6a%83{(=F1*TaD41%1!}li0LowDX zQ9P7OU{1YY>vVBpFcX}Qb-Z}~ECUA4z zEJBQ^TEQXA;l&Jtw2#vr%*mZDM#gl$i3#n*G!Av}> zR4@|OWLC<39pu@tEQ*#&zhD+gf80c{!qe}wWSSq7F_9R+OYybm$uZT`_p~J!E$85H zzZNx%^h`~|9ul#!Cus8Oqnix&MPi(S-_8X*z1p5L9Hr3XfG5vKy0B0LonzF3-w$2; z{s41laKQkx1-9Z$!UYacVcd4uC+dyNlpCrG=llElCc?B68F(k#+g%N-`IZxxP-iu; ziGlHKN*t6R^sDpK>qfM&$qZ_MIS)w@ntzlrVd>vjLI%7lvnlai9M z3PlIv-n7&jN#kCPE_aW675;^HTJJk78BG^GF$>>xlET_Ir!0-H8yiXHs9h=F6BJB+ zpE)&|N#h;QTEI@YMB2U$jzSDnTW+im+bw6zRqgR=q;UZY`$1FPL5i1@+m6j>O-V_G zZW-Y&dnKoPNZ=dwblXwnR(X(#{j93v3p1OH49}+eJ3}hBDMK7pQ3@kr(UI