From cdec892c45ad2af66991432cbc284d9279bbf330 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5vard=20Lindset?= Date: Wed, 17 Jun 2026 10:38:53 +0200 Subject: [PATCH] Use `rot` for right-angle rotations Use `Operation.rot/2` for rotations that are multiples of 90 when no displacement options are set. Fall back to `Operation.rotate/3` otherwise. --- lib/image.ex | 39 +++++++++++++++++- lib/image/options/rotate.ex | 12 ++++++ test/support/validate/Kip_small_rotate-90.jpg | Bin 24670 -> 24484 bytes test/support/validate/Kip_small_rotate90.jpg | Bin 24117 -> 23111 bytes 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/lib/image.ex b/lib/image.ex index 8565604..2437986 100644 --- a/lib/image.ex +++ b/lib/image.ex @@ -5907,6 +5907,12 @@ defmodule Image do a list of 3 or 4 float values depending on the image color space. + ## Discrete rotation + + When `angle` is a multiple of 90, and all displacement options + are unset, `nil`, `0` or `0.0`, the rotation will be done as a + discrete operation in order to preserve source pixel values. + ## Notes The displacement parameters cause the image canvas to be @@ -5935,10 +5941,41 @@ defmodule Image do def rotate(%Vimage{} = image, angle, options \\ []) when is_number(angle) do with {:ok, options} <- Options.Rotate.validate_options(options) do - Operation.rotate(image, angle, options) + rot_angle = rot_angle(angle, options) + + if rot_angle do + Operation.rot(image, rot_angle) + else + Operation.rotate(image, angle, options) + end + end + end + + defp rot_angle(angle, options) do + if Options.Rotate.no_displacement?(options) do + to_rot_angle(angle) end end + defp to_rot_angle(angle) when is_integer(angle) and rem(angle, 90) == 0 do + angle + |> Integer.mod(360) + |> rot_angle_from_degrees() + end + + defp to_rot_angle(angle) when is_float(angle) and angle == trunc(angle) do + angle + |> trunc() + |> to_rot_angle() + end + + defp to_rot_angle(_angle), do: nil + + defp rot_angle_from_degrees(0), do: :VIPS_ANGLE_D0 + defp rot_angle_from_degrees(90), do: :VIPS_ANGLE_D90 + defp rot_angle_from_degrees(180), do: :VIPS_ANGLE_D180 + defp rot_angle_from_degrees(270), do: :VIPS_ANGLE_D270 + @doc """ Rotate an image clockwise (to the right) by a number of degrees. diff --git a/lib/image/options/rotate.ex b/lib/image/options/rotate.ex index 0b5b739..4195f34 100644 --- a/lib/image/options/rotate.ex +++ b/lib/image/options/rotate.ex @@ -64,4 +64,16 @@ defmodule Image.Options.Rotate do defp invalid_option(option) do "Invalid option or option value: #{inspect(option)}" end + + @doc false + def no_displacement?(options) do + empty_displacement?(options, :idx) and + empty_displacement?(options, :idy) and + empty_displacement?(options, :odx) and + empty_displacement?(options, :ody) + end + + defp empty_displacement?(options, key) do + Keyword.get(options, key, 0) in [nil, 0, 0.0] + end end diff --git a/test/support/validate/Kip_small_rotate-90.jpg b/test/support/validate/Kip_small_rotate-90.jpg index 9e4dc56b13b7421d8a64d0ed869cdcbe59b66f71..4209473d5de9273abe71ebea2b3314b634304452 100644 GIT binary patch delta 9308 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 delta 9496 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 diff --git a/test/support/validate/Kip_small_rotate90.jpg b/test/support/validate/Kip_small_rotate90.jpg index 94d3c4574c1fe3efdaa433ee45a0320ff1220912..5d83ce80d7540bdde4de7139f665002acc63a8db 100644 GIT binary patch delta 7924 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 delta 8916 zcmY+KcRZV2`0(#YQChTWk7&^%M(rI!AG1d6npLA#?NwUtpc9QvYo=DLP?NVYB zv^7IfyG41^=lT8K_w)X7lH57xbMAAEbDis)@9D0A)V4t0r7M9iRGd5If4(086{Yt!d$D?O6*wX&ItQiERt4oBwX7N?T8;^u&o1 zh0lNsJ{~^y7{wqgw3cae6a|@%7Mwv+GHny00czcQ>xQ{#2q9W%wg}kJAlCyix96e- zA+tq!wM-yjq`?Ht?R{-A>DCp5B%7>afq>j-K_E9e*d2JWkHaJf7s6_QBOxs{ZHsh3 zXtuZp1uZJzreuQjYrcME;2$raFW}qBt74>uWqOVWlyFR5Ct-htnv3p#M?;$t{(8<| zM+Rqe(+PrX*z+%bs~`DWHFw1VUk?Cz;l3nbIy4wEbQvrc#0w%lJ;X8WfD4`2HB?`o?@ zJzdvkjnDuToE{FEYuznypR{|^opkMb_pLSI>rKX*%L-;`C7DCihJ>u?QtP=+Kl#TB zYYfKjU)%w~Tre6C#08NDLqXQJAf#qIYNgGHZ%a)vY9!3uMUr_tkJz9*h+RwQ!5_Fj2NGBhHYNecziku=mr`B>^Py;a5KB#*zONP9#PWKLFI2Sb@4Ga(eYT+A~vZdBt-YZsaRaXU5n|%DFkO0Xj zyDYH-uI({c*a@<*M74 zuO~0kk0q58i5-%km8+X0SX184PaN)@ZRhO5qC>66LfAf?YMCB(%~bsl%2cw|%W z3^<$x0;Me!V0l3}pV#qtG^+{t zC+6GCY7+>ZA~CKyb-KJ(;GR22YONnm<)5pET?@Y_6oNg9Y> z9iLkDW-B#n{R*KUh7?|y5`;yEK*bOLrr!z&3H0{u$5`dT2n7Y2v(+}GAA;|A# z`8reb#g9vXQcsz6TfSZjerTqg)l`N>w%HDWiDu+R39qPb4TLR3TnjI*woAQp>b(W4 z^*GFGfYoGMDpw8w776)8mEa;V=0$bOc@UFh)uJ91?UGvV3Z=m>B~<-hIR2uS`nig+ z9K!uPlth^uPe1KA16Crr{9m%ddpqGXN@9y&k1THcx^Z5Ps5vYw$evF_xI$AOY))&A z%q5G_PtUfEROJ`-a{m#&{Cc4lhIanj-`44MqAeeCbZ>b`77O(Slh>cg z`Owpyyj1C)sqT6_fAlaq)ZfB$gJbt%0SyV03{g|FS&~$WPPwYnK2}EnpVer-5iMnP za*&EGSz+d!5#olp6vb?WqiX*)Hqqr z1$4`>ud1ZHb;UU7@R{*LJA$$29TjY!V+*cZqKh{#yhin(bH$b7<=ndag0*Hy$SYH7 zqO-)Hy6yXxY;ec7D(xwcG;<0%a!IHuq{`RNul_7=f{F`moNn-mE1(CXz~)z&jmqcn zT~K$ULQEoI0?{f+k^duB4whRjW|q%paUNH-FXLd_osN@IEZ4Fdh3INCQVL)<_3zu* zNc4TmXrIQ@Tut<|vI{F=eRW;H3PcIB}pk5KH^kg2ykt6BRIH(bmbw^`O|~ zwg}Z4(C5~rVxsps&X%8p%UP>;t|o8j-gLMwuwXo=RT^)pO?*(Ecg(@W=Wc&AR#cP1 zwi5gpMJ?U*cob1=1}E9#TXWxa4JKE+3G=d^2tq%vJiqv!4s4LIc61qUMwsZBQhV&C zFKvqQ>(H|*?_+82^v{7vR?v>bNTJ=UnU?DZssOLjt`Jo0u}%op7_cL_+6@Hz>3xueRn zp+P*6N^0mBG~IIXt*KAr>R+q1x74(!lx0THY#4WE1okXe&>`83t-F3$YNd&ZYdA3; zq=|^LTVESG11=q&ri>3(+FX&orNDRnAz$2hBw{RTX^w74h z7GHpklE7=GT>IFI3Zh732I^X)RN_rh>!ibtEz4khtyJa^l}4{AEPMaU8tbj=7U|6; zwka1&*DZtM*$d|d^p??l_3zS2Rf@s*bybE)bX6d;zrm|Zu>#Chg+brtf40>?($l4d zVDm{4*{&=oP02~<@T0Ncp37kK;W0rp=D`Xc09};c=LD)M;`uQf$CWka({8y2hDPQl zw^6{?e^vZOKuD^~oXImu>QOk>BRGe@z8r`^h zd;sqxGoQ<6#XmyfT^TA?!16#I6a$t#3N`gEj2cNGk!;zjdjwo`pMIN}sBj0~-+|3M z`3lR;2yBdR&|;)q-ym5_c4zCO8eXQ*aA8&mXa$`u4rYg(kOpDXm7qkT#x?DTHH5E~ zVyxixxfrsqg7hA|9$EqdisKlP_CEtBwCO9@xG{pV8hB=*Adl( zy@!CP-w8Zc=&+!*g;k7Vo5MH93Mku=Vl-s`-U|IDo3*ko7i{q6&b^r&b&oHVQJ98` zd%rY*xPRIkynnli^BnepD@Q}rq5bvC``@uSu5qwh;eq9o?#+V|R+D@E^dHeepO4x8 z2xp9W9e6pf$C~4bGbt}tLu3Z-hAsP#aG|J}`@KBBjPAg1D_5e52iJGz}Pxaq8pZ-qZ07}xPFP}QiB`g^d(-Uq&-LQ{SB!^!8 z!ZMrZnhPG7&ZaoL#-&}pWLRc+05CAHLr(J~Uwy2XK28Yq&isxHfz?Kc&xkRgB+LVv zz$IUxL)lX-|$Gx9)R1#Kf2q2s{DoI z*&5vV?a-pr#DIU~jn4ZLmGlQyBpng^B`z3{wmq=*dMY7Z=UE|wy|M8;?T)6z_ z$D<>2f#*2*;`>*EdZA4}QzCSj!1P9IbWX zqakYjJoi!%r+KW%2oGWJOMJ6%49*HOsK@3H)Uy$15&qVR!Zm97^9jfc9{#-Y4l|E@ zt$p3YtsD%ZewC(W_Hugdm!vW3`{hb|mUVl7Lvkz6iN1^c+QHwO)Oja*S$N&}XAh_E zf@jFa$}@t@<7CMS{_((PZvzVkD*1z+w>TC6p%)J?Ysor+8HhCxPXiWyVX)BuB(PVf z$--UcO4D^os6mb;;|Bm0w1 z<}c?dpQ+LU!z#R~hXyR)czR=*;HpcdE>Dkwivo)aV>B*FeOtVnu@)j-m*jRZdA_Kq z%ol?>Z2T`T~tn2!syeh`v~{J`RvSfPM<&IEsphv z9gd~iuUedS3l)UsV5Fq#b1sX^-}UERNi(>8EWP5|oYI?*ISoojBhId%rz5Xe*g-(4 zoK!bO;+I{A#*CRa*W;@ioV$PSGXeDk_Gi}1ACBizP!0<3=ogcq!L91m+PJHk$490w zf}420&E|BWSpqsg^@Ru|7~Sj{?%f)&Y`;1SJ^9Dq41mE;z{lj7|&p!6=b@MKELR+!!vobM`pUFedG_K$ZWJy46d_pf96Qr+`E7+>w)3Ic} zgwZdvsDjrUDX;At_~YEeBiK0bU7Imz5I)uNp;{zL{+tT|EpH3^q4GA^`?BAV9w)4; znQenTxrZnma0E^$eCubr9g~#F`ue%IoyQR0&M4da>C!p0LQIytm;Byl=5nRigZ!uL zKfj^*Ll?sTP_quoj{siE|#qb<{tj6!)|l*bz5U}KxC;s zMtMTbBd?d&1^@BP{`x9;%Zw9op8mMGh_Ge=qYt)%~uo;20u36h#2 zl#q@@!h>dWf|_oJDH88xY|#SQM8Wq6E#0g)ZEd5I-($JFi?vbtC`u)?ZTQN-Jjrxi zh8m-La3BMQ+l@xI3whfKLPa;!;^W03x!P@3b-lZb0o-m*HsuQ3YmZ_M~vl+%TT*Gx7$Df{UhVCk*SfV^#j0*Wk2q>U>Lb(1(?gyt+dJkOFHM$d(F~5+t`r_dG4kD&rvavG4Rz-G zq9?0Z`XJSG8Q8}(XRRxbOZSR{!AAvvbcGCwhi2=Og~h?eU%RF{Z2Npsc0r21#xpkh z9&oVVYlExAkKGkY5)sBRn_K&+IIr8eeLDkQToJk>qd?=}b7TK#0&DHAxh$dV$%q+8sVy$6ZQ?J}cice!^oVeQZ*No}*o z{AK2!)Wexas=N67gxeG|hqS>Vg~+F`y;e(WutM2N37^?i^+R*AKjqvaS7#4rq;m2O zD%Itzr#lFiFl#;hs%f(A~7J1T0mO6aG z6r9jtU4V#@yP7ifi%_LYwH%(EylyFn{Xmo$(1!~lLmkjki(tkw$8M-OJn9gz@PKbxNBZi;?z5XfaYsJ-g|uGPOJ-|rTtS-rwm zZ)a)|UOXc}vgLX1xd1<84C|Soc<0Y&P>FrNs#OqZlxMvf$<{uu-5j^j3EW>h*j{DNXz&MyolA+H!@qn@d%X~>3L zOp;27NMt1+e)iOQZ4i(MFui{6W|Yw?%c@iYOIuVkajxkkE2V_w=VxUe&GX zJkE>ZwF%35$={TtvT7g`S___@tSgT~+NTp#KPH^`mN!wp+V}>t4;o3GtS25@gF&wk z8RfR^$>A)7`jd503Sav(A@bTF%ExKFQ=vVy|GL&zg|q05w$FLGF>S7>yNcNc`a$96 zwgm~^se`1xX}xfB)%Wv%LV?4S$3Ct4x|`}H2h{0b>N4Q@dwj8GdlGGekdN~oj9F3x zsIluid^1epo*keMHo)c(FOGBTHW;0+ENhnvTLbcNR$-VPVKEYeNSI-0m7}Hhjk1go ziilOAZDdUE;vo|-nL9|c3J>n18LCk8^(@;pI6%sNpjODA!ymUVZj{1;$u%#K;shwS2N~VDmylMkh?3 za>2$1e_=lCU-fi+K42VccRkz&Mh@6czar@zjz*_iB>8lEU<^&#?9#V=hSsW)SI$L5 ztQ$|drM`QZOIbNI_{Nj2Er{uO>+qJ#s!)2qUSOkvAGSgoGB#QDC)3{k$dphWOfvn! zc0qf41WZqsV}hLPjPaxyPe-F~1>tlKNrDunHh|WxTeTvdJ0sjhkaG6;IIGmB<;i3{j`tg;_Q&e#chV1^EpeN_5(ehFhRmeFW0|jQMF}lW!`j!K9-mSqTDGK3QaSPMFxxh=4~G451;`L+S`eCznY#aijpq>S z^mfgi_dO$`c96Fq+sx-$GQ5eWeGV_$i7#I5I6u_XS++t2 ztN{vd<)ps0tv23YA*5>>7@82!>>A2pBk8CXTENw;8{tkq_bi}c>s2i<^tkWEe;!}o zcx1lFQfYm2b0X=)t_Cvt(4>=GcYGR!=qp1aqy$_W=*krjY}gH3%2^tW6H#OE=ZQ1 z0YPd}NbX33wweXSq#WI@=-OgN;}^H5H_E^WoU}c>$$0^^+mW;TueGx_9P% zJI!ND#o!O0^#Ki0t~at)zB=SFG(hy7iQ=uU6g|n3nfn`eI8w`xoCr1%yWl_ch;^e> zv$zM3ljaGPUNsTH;;eeMa$fMzD@dAeZ^~;aGYH)JFstAigB+>$bQR zEOoQ!)o?hEit?zp;t*vWm=yhV#q?{Sj2X@fFEZ&cE5D9pS`iOSDXLDR^# z8sOlwFIw~0%VS*0@u>bzrG4-ShFk0cg(o*C+f(>3 zl4pQW`CGA@4vU=)!JQ93nJ6>z7X?*imOh%eMU4S#8(1$Was>;GqY zao1<6joRe{m|}z5qOA>0ZW3DnlGfs`WAU%>Wuizh3!!mype7n186T)1_1k`kw@K>F^=c6k0Or$fN$l1W;ZVw$S-g*^jTD8b6S`>0P% zl_$JqK>0Qp@Losh@}IFSE0pc5UL#{lcj+#YyWa-4ts8R&KufCE#?2R28r8OJWOhEA zHtTK9`jc!13w(Zl%Mbg}y=2h1frO>_gWvxsGJ7V5Jb~dNYzpxUI!i7rWfZUrqV^y1 zZS=AOKfzzGw&hsq1WXl%#h~*8x#@uWHuE-f#LN8U9V4KX_Ej1`>xy19f(BoDmx1lw zPQyw>J>G`n0ZN6>c5CesijrGZ8^t8?dz9K4ukC3k>*5&Mopa9upDHXLth1{FCNzX@ zTUrEf2*uOqLw=#4o8=$Wi~I~hBU5T!2@FE0brtd#KmF&1pKlWi`P`_o7?+uNUMWnO zCL!tU473dPFq2;cq(_9NtsB3Z>V3KhD@1eGQ_~HNdeH`ublHlgLrg|Z`s^uMiZ_rK z4K&={B+dYQ&ZH>nr83w}n z6cCWH-QyQ++=Y#%x_qEo+GIeQdBW9K?uD`b;NfZK0+MWWd% zN0KP(7+S2Els3Pby^<9@ym5=5x`O0jsdJbYo0rZ~Nx2_aVMWHlS<@MFXm0Yye{2{a zd}iS?vo&Etu8=O{PZ5My zKZwSj1z1W*Jsr+h*`Z$KE6YJ&`zK<0G0tk?aBHO2m1U89wk^M-|8K8kkV(FiL4N(e zeEu(^r-=3rCDZi(;C?hn{_%H+8e}?-rX?%qKSj{*ZH`V00$b#J3lI%5?ML%yNJax; zOnrioJrgqL4+~#CGTz9)+oY20B@NWdv^HkjBNSA1E3BqN1?z~^{JTh2Q%V#omW`=~ zAg=u%Ki5OJLiSMPdlmmHBKcbrNh!9b`~QhgzDDssZ~Cw8zt7V3(#hnZ{2k8U@>hRr M|9k6z;cV*v0PiFB8vp