From e77986c7e02f8f315495625e5c36f5455001277f Mon Sep 17 00:00:00 2001 From: Mirco Miranda Date: Sun, 2 Mar 2025 08:03:28 +0000 Subject: [PATCH] Added support for resolution and EXIF/XMP metadata to HEIF --- autotests/read/heif/metadata.heif | Bin 0 -> 25296 bytes autotests/read/heif/metadata.heif.json | 59 ++++++++++++++++++++++ autotests/read/heif/metadata.png | Bin 0 -> 14638 bytes autotests/write/basic/heif.json | 61 +++++++++++++++++++++++ src/imageformats/CMakeLists.txt | 2 +- src/imageformats/heif.cpp | 66 ++++++++++++++++++++++++- 6 files changed, 186 insertions(+), 2 deletions(-) create mode 100644 autotests/read/heif/metadata.heif create mode 100644 autotests/read/heif/metadata.heif.json create mode 100644 autotests/read/heif/metadata.png create mode 100644 autotests/write/basic/heif.json diff --git a/autotests/read/heif/metadata.heif b/autotests/read/heif/metadata.heif new file mode 100644 index 0000000000000000000000000000000000000000..df7bfb49c068ed4fcdad6a111c9789417c524bdc GIT binary patch literal 25296 zcmbUIbzBus_&yFFx+SGMl*O^L>7Q{4Q?pYj$>L&+N?X?94s)Kp+rGJ8wUC2U|yL2nZKPJD&Tni=(9-1cF@c zV(V>r9}j}g!N%G1Ul0OuceM8YpYZ?iBX>t{mxlucP%Ah(yFJ`eP6~nqxsQP$Pyb^G zL^%_JcpszT{Xa2?N#Io=v@rfB2EP|Pv~qNG1v3KT{_JD$!1f^_cs~bUYo7ZP{}YLD ze@pq-jt`f!{&yw9eL5FM7h8y>ySuZawWYVCn=6;6jUC%-7w7xbNQI8>p6(z=Il5cB zff294`^q99qu-x=0B{7k1Fo(h5L_f$FmEJM2-pY!aDM?3BvbeyV?Yz46dibuO$Om1 z<^P^YKtO;5RWB+t2@G|}N(bLx4Q3rw==5L!T@Inso!g>{76L(Bw{~;(boX=vvyb@O z+1kYmSqjX#tGB1Nq71E}(FWFR<O-! z>R%WvFbI+TLl_bJKJ2NhEek#yEf}V?|3AW3|3}!`!4qsjh*ID+j5c1@_hIliAc8h7 zt{@|3fMHP=XCE+c4*-i2f^F-nrvoxM_)iJ(f@nh&Au?bYSwVatju2;v4TJ+^SFkMq z@9DT7(rG~4z%pl&fpob3Z+f?E2t@cCj8FLAIL0in zv4ue(bzT1(XO#kh)JH-fq_ggpo|X^4g9K_sJFvZ+6ha_4Mi2<$CKfVsol| z&+V>Uh-hByud9v-{!Am%CCi0j_29R7Gv;56A2ezvHPx24c%7$f%RFOY@c>XN;)DEF zDg&(ikxb^&h{KQ_f;U)cSlrh&ghI+jOT^*oZz?U;Z-zdnHa!nIS3aB2k!=U~@03SQ za%f*`K;USj75twvHJx=l%Y^W^ztgT^sJK0OkzFD1TRikPQFOxgWmjg7K+cOK&%gYk ztL9Q44atABpsq$+KO#jC6oEkKrFzJ%uS{P@F!iO~+Fh@`gsBYJ20GkWd)+iXg65Rx z+ip7rOBUN=pPV!tg*36EmEI~~7YQqpdi`E&k26<$f>b-dT77w9d(~Z1>nj+g*3a3+ z)x?+mlx30Z1I-1|tfS-}M^cBn-iTo>Leyi$jif-I-#*FRr55!M0O;c8Cx=Wc1zpATp;4qF(1JlJtB2$O3LLHLR zY}9P0bNyunDyQ*|Ao^bo&E0soT21&iAvVUrGe4X5DyIGh{Ar7e-+^KU0<)S^X* zD_Y9GK2h+TkALF2?teUYOGP`aI&oP6bU)5zhf2p?#uRPvQ`m3&ITVW*?|Sl#3={Nf&gUt+Bl^+Ll^m ztU$;tzrLgVO|?1ZSV1SA>|ZW&eC;obv4AN;lRqt{xjRd5f=p#EhK&3Kr`!Y!e@j!M zX!-0j+w$2rK;HfE*_W>QVM%e6Rud=*;p$_~skg(P1@VDwj&zCq1HKDLY09QY}!4jl+t^wh_|uT?wULebIemj&5aWllA< zHu?3WE`=IXBUW*_8Te3VBtp1c{*f{O+8NSjq5d`j*&n}g`dZ}|H#$D$_H&6pT*dKt zq_9WY+%Nn|<4s$f7sj7FZldK>)26>9I3+v)4bkwc~#f~M>Rp$)e6~}%;>(3w< z$@pOf5f1hO1~@%6n7e2{Ax?2gvd@Q+#m4)hl8S?vE4udd4z2nttw-Q zsH1Bh4^Og4xpwMZkjYc}*cg_P1U>>`IZTWePkpv5qPaP)_6_y%st{E zA!}RjxW3V;*P>JEn5lFk7@DVN0WkHO$n9m`qYBJ>nZa?N!SQ~M4?P8r{A96jr4Cqv zQ_4bchO;6^P>|j_b6Ew1s!dB4i&mA8mn^74S4V!d-DW;Z!G;&WWDgZn)sNm8+F_0? zLL1>T1*N>pmvPPQ&ob+p^%sqet&C3*T?<~&#h2MlQm>h|`TCTwJ}-FXfob^_nitu^ zRoGfukD-?rL*4t;1aPJf;4xsw_<20hip}!9orTf2aQ=1ox_K!hvj%MD_9LuJ?>Ra! z?wOYm6+KRNMkjQJxG7GIqvmLC92%U?0nb^EI8W8845rFk{^?C+N{*yEPjiM~UzAGZ zdKoa{+8;9obhAW!^c0>ntB~I<9jApj(*U}yC0~$|=ModeJ*EYp4%?@j>3gt$TJ7XE zP5OjRHi{AJ%-ZwFcf&Eiu0Doc7Zrh$WHJ(4A3x=Xz0Fd^7d`LBM}5Ry^3=2fl@4LZ zA$^XKJ+Z4&5K%P>$xFZC?}GEMpz&7#D5ta2hrq0NRevr2qmMfhAK&f_Wz6}NMVX^AbE?3vnzH3N4{QAAqI z)1M`kDLXx;1O?F+^%CiWkL*aHn<*=V2?e5WLQZl*+%@&wg0W1H_yikq1t ziRP(GB(>6>HeDeyIdx3%A^Tv@nSV-pUVFT^38%bcI~)+TYL)2=!v99bF&$LR5jVHj zH+`!eyJkZpF2wz1?@ zhEu&WAw;(+ZWz0|OvbzMLh7V{gD0v|=l5U6CI|k4k??1^`Ykwo+yN@D z6IaCIfeS@a z@CrHK)0=1qP07?CD0Sl(Twv?%VQeU~hqZ`2G1jC%itf5 z3jnX-)R9v6rH2F#j{pFEL%e+DwbI-XcUn{ehgFtn5~FzQDDUjiP3jfeh2{7He#Kr) zzw%twhFkhcdfNfp?>Jh$lpbSo!fSDY?X*zfWM?Dc1D^T|aLD9ja`Qh>dw&y2*L{10YHFZR5ZQaPJ{KQ= z4JKJ!$_ynpwgqhVjs$w!My3Fl`>v{?{J%n~P|=^PbRvoP18^7eyhw%D2j!+Bl?;Uf zqk(P)z?zVv=5Knx20VIHTIsD4;F>Z6=~Ddk$jFSXx_Q?FTM}?T4=z8s&BU(eVX-j` zUIse6`WjkIwca24$1fe8`s{Tungh2A;hD8DA)~@KYkTqK5{)!+Z}86)$No|KS#`lS z^s3W%P7&Fg?dN<{E1|uANNoTlH9pX-yPb6Bh$FeAI#pGb#yoOgOBbKsUm3z zNumnFiEnOt=&){TKc(jzS+GIAP9Ku#=&D9(SA=F@UWs({``ya3kCzk?XaB`zD)L$k zyYTyh{~6B)hs2dq#K3`2bFCy-cZ}`SBY%fs3r-uL#ZL7hRNp-`w1osY4Q6yxxO4z% zECbFk(VEE&eKi>nxoJ>7>~MbAT3e1C$(8;?#QgTlw=zWtCl~n#yTJ*Nb&yk+|CuaSL~&a2963H8ke^4JL^j3$KQX`P|n9)IB(e0 z>|3;MV+lCc!^0lk=X{h)^MU)9PQ;rlc+Y9bU(_RF& zdn*$qDicNZU>%ro&QVz{yiEQ#+S(W+6V;ZH|K^Fzxr|d=r&;{8H~)=noI`4g@Y(7~ zhomZb1n}Y2XUH}^R2hONmLgt_&hPwe0tm%xOIIqv4T-JWRIHb4K9|e zZm~0p^}oK<&*K~8^W2#Hv*RT=ioyW@qRcHvsh>=1g-UDbYoodsI_;*R&;iQ~SorI? z)BYCXuvVQtgF|^pb~3sHMN31XVK!5F-D9U?EahmOpdcO)^I>S+Z2b+Zjkt?Kw}ooM zPg{6-ORQThGnwSy4~|{hE4mn?oPU~51llIWRw%Y#OEo~v<1;;PuiStuuseJaq-O@Z zy*$PwV%E%&A>n{fR9Zu`DA-a#WG6h}9UcTpKalb`^u^d)p#AU`m^y!BZU8FNNBkvu zz^&X0Ni>^&*^3#CFQVQ%gU>j&`yak_!3m4s1p3y31?*Im7f>51-C0sk0oxZrmAqcx z-nzoEdDJ$tfZo8W%%;8aHt_qQL;WJ}FelEM8E>1%LEYjKEUvMn5U?h{l@wA&r zr>q&csT#FcNVST~4fB*okJ4BM+Og7}ev~^DrWGTV@>W}o@deI#Sjj#n$YEPZ!l|Or zX(kID)th1Zj;CEs@BL@){)XXqjbCI0RR(_O*wj%v0B-InFC#+YzMYAk7)3kmYy!#ylU$e z`>^>qg|{(v-C^?Slo`W-)QNlUX=g$Tmm;ZjHCNq7JCrkBqjtiai3ZvpC%Hz6$D6 zQeQD1X*#_XI7cC5(7glrcLQ#=7KCo1YIr2DMNF5pI>wG?t(7BUJ0i!`62{1y82HKK zmzT4XMHg-m+h%Lar;i>Fn7-!a$&I0!2hh2z1zyeqB=DM3ADH~yTP+uxPi1k37oUw5 zgL7iG@0c21z84M!PUHp2vQyXKq+~?6n^~UCNl)^hcYUQBMnznS0LtgXtVtRn=tX3U zCcQ1JB0t2CI-aeB(N-dQ#5y1Bb#U3T;xt0I%=fXFRo9s@^ z22Fdp^stO31XGOsAREje3wYoKI_XY~}kiz}s-$@Z8Ycth?vU52pkZ7~GuY%@s|i-#+Kr7|nCm zbZ?1~b(i$ za9Y;iQwawO4&SAbe{90r;ntbFWX|Q-4|sE3HwIw($~J$#uvE#h9P*Pamg#6zeh>X2 z_lEzOMV0_F*&#Ps`!a%9& z*tC*hU#*i3#U}ZphOAINw6_vtYx&toz2R}8OrYuWNVqG51Irw6IM5V$#e+@Twc%04~>3P&92M(ocgBG!H1!k};iU4ghu%*ONYZdK)Y-2%4s+GdcO~I~87YG6zPLOlC{norjAJfU@TRLX&0r)8@+SPIo{ME$4_3Y(cuV1V0 za#b(sZ%uvY?xFEOGni+gRqg~MCNg_~hQ5E)I;n5;Ny+$^_!9Tqmq82G64B=!<@3#Ay?^{>OuD8R1 zX;d7uP5hcZnGn*fp}reXc={@V2i4u~s^R#Vr+L##AdHV+)GC@$NaGpty+N^^kshzE z9k__a5_cj)$@Vz!odGA&p7&GdhiNoO(atxj0KoeClWU^ju|b>Jb-)U%xrKPp`97X_ z&;`;=O)~XtMOkNmakt#w$v%O?vpE!&X{BG4D~N~F(s5xGt+=vyvPc5knRszRieA@J zVmUSF(7PAAEGHCOK!Nz@3+vf=HjZwL+SjygUkDHvF4cCu*yViQD+l`Hceu z9~tvt@@?7RG#^3vCDk_p;Y@dTU*F7wqm$f7 z3S;pSs7ZMu^r6vG2E94H>|Le_d?2a=)^$jB9g(&odP#aXLnc|CJ%H*G$8LXJo1X-~Pg?{JcO z=jCw9GLsV+)(#(M_`bLcc+Ge}86<*O_6*b0;8K=?=#hVbSfY+5f)Q`D!$5W0BM>(0 z5BTB|gfOuK#YcRR9tz@G4*2*x{YEwf)tn|5|~4uk*D0R7!=nkyqP!KopnS&fNpguG>uc_;zE-TRMIDE)Ab$2;ju@%@W_nFG^l&=|`S zqhyMuFC04^*~Zgo(g3`5inDWsT8HxH@AvZlmeD&JpzAk+!c~#}a*R9{k!Et2i8U=m zMP<*5a!b?^9N*2ZK;+DP&WXOV%&KUA`i9zvC;jt&YOh|!^DUm#ft$bi;&8s*71knG zMbNE^&;E}{u%#eJM=5q@<7XBiGVUJGy@Jqk`81gIaVHOm9J&YKA|oCl3q#~i7DR0Q zWR7pUvK|GB9Bp;2<0eQ*T_Ziv$?{ix;0zbI+Xw!V7k^sHMrMFKR^2o@3f`E>LE$25 z(LPq~k+a4Bq@YFiKpF`U12@)`cLrv0I4AA>0NY)~DT$gXk9W_+16Agk0vX|Yid-yZhq~0|XNkU&jaXa)!jLFISuKk_2}?!V{KSF~vug z!^aaf!;_Q7N6K6$2LM^i1FxP6rE&gP26ME|qd*!^S@Z(8e4qU#ncD1AH~ljI8IdG# zgO}cI6>~aKi+~GwmKQbPglrxjAr|&=kpnBI0VCywT*G{^VCRsCuq+sk5EH<+buI&gcOe8*=GRyoJ!k#I1;(&y#|nz3*M3qQXfLJ`;vHG&Vq#K$IUmAaOzx zxPIf=r+9_K8uIO4w#xnglhO?UsG=|*GrY2DEJ*{U&1*~IKgkH{k;1`qS^ZTLNc#Kt z?*;mQkbwLZOMTHI20{`RyFVYa%Lnc0x<|T34WZUpAmg#+ zp)sX}HXYBeC|hB-hg4fBJeWBY9!cBqcm4T!)X=k5XUgtbrj99Meu|g`y*HZy3onOP zKW*g62oFQcfbqNh;x|9Cf`pMk2?oSR{(o)ekK?FDe|iv2e~6fuO|~5jW1pa7_eB4d z^VZkqL;Ij)GF*1<>mdNQf=xlM%suNT*T!ky>mfexc~L+|bYzk8qTc&#e$IOEHQ<*> zTB%&xuwSt^)Hdr8HgbVPVI%gPk7nSCCG!^260hoWScdQgD^q7S6ceA`UBboKJ*y1M z${vWgpkd^GzIxczGySgh&ou?oCb7sk*-hpppmc2&E*b?p2}1<*RCP+2C%3Fc^$$~} zsp{vQbC8EQv@pkz=(J3#g=azuE1|x~rttT~eYn(5I>jrB4ej zCw;t4KF(nH>_|qaK1!v1_EmmJL*}N`X1#t5}hvlC2;*%mb$>4gqpUF4O?-F_c1;8bI~sC(*D_xn&))Sh{Qj3 z3}jXUz_o=~QA>hwlX>IYjoXw1^S{t4c<(LE1D(>`1j9Zr^;7$H5#V2`^O!FI+;HP- z+#j!espFopJ93Y|<{rAAnGX5gNOL-7XgcHw!J{(}{dxXQkf z`-1i+HKftGfi+uQP>fGVt`gw|$}`xY_~p)FO4FAlakORpqDw**nIu%0eb{4rOt4d< z3W!~M7l5WysnPii`7dET^+JHhe(yh00f2M!1GHtXz!m|$)ruE;GnWEg=P;j&qot;h z#tgpSx)zlC<<RJW_%{UWK0-mlN z->$_+Hjk)V9MGxpS8RtcF}DM!;ss(uO>(8fU)a+4{4B42?#l>NXT*xP+YM07zX z9g_S5+%;gV%93L5{WLaHN1%%L&|K0y=|7R9xun?txk<)6zj3?ILb5xsYse7a=)k?| zd*xDAwLXNv^y}Ry<#8SPM_ss~}A* zM&*ZH|Bmy3qU3fj_coF3?M3jlVX!&cJ{er%?e#zExtkxqoZUua z^1zRhul9Yt8Zx4SWZDbbUT^yFBwhcQ$~(jB82wH8$#v|fJe~fmbswU#F`OYRn}=vi z0{@2rJK)Q~t0oF&=bY+@{(p1`w!s|$=rA@vGP_wrdzz8y`5Hf?mEcUZ-xgG3Tr4U~ zI+iZp{nN$l;)wEfJ~qqRRYho{PQPNnR^v zPV+zGJc9+#knV_-V+QlT91}<+C`oSYu$xU5_pMXc1F(kb1t$I28T8Pwg*fDz?9%7! zqn?B>Zcaq27axarw=XDhB9y%*{WW$eTU4%OL+4WIIL$F?`AyJ`ZdWCRVltaUx<-H~ z0lyr}=4x{K!*o@T(d3~2yJYictXipbP0`TH=wF;8{5B7>>0q0acSSO}{LI=iUuv(| z+zq8ugds0^R1;<;LcGg5l4cUiF23Tj$aGMR>)@FfZfy}yeN8Cc7U+GxOx3Eef#2{2 zXtZ>%&Ba1`7(SIs=k%!DvHHApP#soT4f@#|AN2Q~6N@3o6ArD^-XhrFpBJ|h_@gD& zG_o(d>-0;BC={1Si*55qo&$^vAd0v{Q14bhj}fJ5IGz_50CFV6W^P9V@Qh)=I82v@u40*L15Hy?UAa@ zAP#6HrmN^{46}*hl!&z#enackewvdv{%2Vv)5XuIySXV`YbCRq?$w4}G7V-DxR$5U zfhdG$MybSdx8Rvk$kN|f?r3G$SniY-R4PS_g;t&QH_Em!wP4w-!pgk^i*J-)NK9CS zzq-ayf=jn}feN+woUhW-hWx+FLJiY5(TZ;)i}lsvGgg1~n5`<|Jk=?T{V|7d`ohQFDrrmvO}_dI)(sbt*aNFh zdIxBFppWkij?EwFFSpF~BPg&JYS3-37yu%S@d4D%4p9iTr78MEQzC_^K~0F;SlOH* z?id|UAsL7d#CrrazfP9xJ}Z?vuMqH7JbsObj92na0RS#~pS@@n5?Il}SCi)<>eew- zw-gAQCVZgo2uuK2apxwh$fh#d6#Bem?H9Ynno;ao)L-~OUGl-vUI1(e=UCdX-oU`X z@ZXeK&PkUPNyz$f6+=a&;TO)c=J7+-R$lhL8v4Qa4>ZuzqX5h`atN0ekq~y;n$Pax zuz_paxZuxCA+j12RpSknM>LUdJLOc2wJX3V&fFg8ToN34ZeIfMsb7vgwu-cVsvBIN z>SQz^vHQpTOt0&~dKs#pZ##(&eGD5oci!1wF7Z!U%exCH-*aItAoaxVlNj^-$miYS(07v-JM>8$aCN|?+%oFkFkQFHKXGZIJ!m=cc=WlNf^RhGg46XE(B#`rAK3=|BVDV(AN< z^UhtJtYN6g-PUQgU2qzz1K9)FpFMH|;54U?*iaA6Z@uUq`<>YC>EgndEfRJx>X z1qI-l^%`hOb%87jU&%kc)GE@Fmw!y8tMx!yHF*FKangm{$us5J*G&I6%DLH;!@IU; zA5`NrB&l-I>d08|$iwi!!I9RN2^0L!h)i`;B|o{aDu;m8`ZN?OG)b<`~wZ0@_jYu zeO4a`{WoY#S88}H^gC5-s77#b?q`jJ$+g!yJ*YND5}cYJ1Hjyzi?VZ*fv_q9J8~sK zhZ+rcVCN~?;60smfivBF%(2o@6)J9^3&6eZ>Sog{lPP%ys#?s_rUh{+x%O7taL)SL zQa&?X(5JzOy7`B`RQs9dE?$?!#}FP@XJAWv3y8+}5(!iCyd^Ik`ZAp!h z?nc|<)m+QfyEOD8a4;A;2QZxze9;`Cg21FBDiejP3(Ddx2@c4lNIK#z(W)a3m`7>fpS$PTfb_A<5fL*@l_Fv-to3SHLa7yI19F-ciJp4$onL5zL(t zh176Q41+x~YVbsd8>O?ix8skkqS&Ql_Zu-Zm^qw>W^|zl1!Gf<-uqa?j|MKtRX3ZT zzvTAG>WTCsrem3p;%w6ZpPz^<@pw~T0Arxd*w{yt5~ zhi~pX1U#Q;ZV#mP+S8NYJ$2dkk@uq`uA{5Y*bBpr*bw{0dNt#r+(XVN9T3`Z+fqS` zId8WbJnsJnaW0jp<0+nKr=jStq0stxiAmiA=1430!RRd)9!t;5q?dE5uwa-iJ`|pj z1)MQ6coZd5P%xZc-P;KrMMQd@pLznolXG0uVGYo{Yghm3)vMQJsYjc$PcN@lZRYHn zzw9Y%y2$RZ8EUMEW5rv9{dM(xE|}nu>YNdIQ*CEW+(GpvFDYT)ez48 zbO8Pg)^XZ9_1CHG2$%s@K7g)4Kj!j~JP+MgBHzA;OkkiiYP}=G+~GB;2ytOKiSJO( zqbO}NPEG1(ul(zw?Z%}J?l>WmFqvgp1HD|eNtJ2re)(PXV%IJg3;ZPtzv5j$g zP7s8v#sgS!0VPQKAC+VLqpl6~2iMO(pI?)$*azpf|3~f+iiE8-aG<7?l%OXSEj^Fx zEM9rhHD7+v+;p(l{6On@WzV%NbFAHxDHA^?dI3Q8-D$rt$~`##0sX0F5Fw>;0h=q` zLRFz`>!UL<+ozy^u8*tZ;Xi6T!v=uK_F_Sn_=K?gzHgFEvpl{@V*57l;DK~+0U(C4 zC%0?uk0b|Zhgm4PJFICNK3E3T?X#u=(PaQWck66zf77PztX%b^JDtFXY|>uqi^2n? z3uXa#D765}VL7*_->O+-ngrAoOQM}12g zscu~ZL1e1G{bWq>w{hqrV8N_`5a`^oQV3fE98*@g;C#_cVia`zG3v|WxF+?G003Cz zKJeW?n*F73Ym{WCmulc)+Vkr1!avF~1_1TJ0@1wpO8%}p%>_ICyZ8?BIY_~vA`Zi@ zTXh3qi=Kar*F6eh|JKgLi|oFpCBFoh&_J^L0R@hTXYNSa8alzJ&d5Zze|X?j@TtLR ztJ!o|NB%JYn@m$#dK7Y5eW#C~Xz?fwUU|vZUz-s-466X(9bR|5ZCTRzp8F}^#kd@5 zhYC45h|(LA<x-n9zGDA~F^D3^9{`4bKIJR$#W+uRB9)40gOQk{5Kd0yp!GniNaOYA=DTkBEt3b3 z&j9e1>G9tWX7?Rk%)fQ4A}I*!LD_&lns(eEY=5ghbE!)FY-Yk-z54ne_2bzCfXQOn zSc$3H_6EbJIBgN7U94}M*-ar2)EEc_u4_ytGMY7g!$paD*#w`$O`#PaLgAP?>A$Yii_O&KR#lru{@B{3IHsBtElA?c7GOK{-hxd zv0PATmcf!7R5r0;9KXPt3$2lI60J51>O#WC=H~7g_7WM~;>&m-o^U9zWlfkmA-bkY zs}{_QOf?vb$c`bQYD` z5$LGOkzr!#_oDDaPBysSC-XcIqgY1I+8E!j@ZyBu8n6maPw{%+<}kC0!W>Td0~l5d zf<)-#Ok(px;cXC!Gf3l=-|thtzGa5M*b|{&)Qqna|0qWPqs05=KMj_T`*m9!@2b$$ z$Wu2bvQ>+cMf`w2XaF20|E9>Vd+n0YMBPK6dxnD1Ik8&d*8|D_IFg8##YIJC%#U{;-<7>HgnhjN9-|7=~tf3}y05p%8oOKG20c4lO=@y09P~>?GeAUR!Z_R2;w$ zH;u6qeqm$i^2#!DgO13+Ed;TjQDPcN-Dk#O9<+73hGt(5&I5p&=!cz?X0G;t%ho1% z^IluF^UY!TO>k>}?l3|jAS3biVr8gGgQ-~c1pxHf#1qgiYf8wjgCbo?f$*Oo`qqIv z^!6HeMVhNy<(Y^+X=^FVhY+J1(piK*kOtTfnmL!Jm9lvRR38j9v&J2g1==1*M1v~j zCz%I1n}{DA%xWD*t}1)jra0WO2N<^@4+ z;#b6Z$pY$+%nDIZ^QR;~nOJOzA+%t|O5&Xpo#f*At$!pzbjR`-$^rlf)tZl0szyGP zlU`awiUM>t;U9>Vj2=kQpn?|)w89chzcY-6d9*VW!##VIZJZEBg${Cix%%_+l>6h9 z*Q2AQW*)W;)GfH+dMh{xq~qWPEs8dJPMOJv;kCDDF~SpJjIHMRQJ-wsHq9f^3aNfg zWwHX)URD<5j&gXk&w*(9i|qiX03}}tcPI5+n7JQV|7Q=5{A67;84caB$Y1+>F$N3`OU5l-ITUq$KvCAWB>|3tEMoody6zW1<3$A+ zw0TReJn!z;Fk-aMXJ*h!m%i{aR`oGF3BR6qwEDLy^0H8n5Lk~)b1R(03-yUpeyqU@ z4`zle(Oz6|U{J)(#qiZP2UKX*5sDFC4=&)cZ1!NqTNRZ)j|$D!F}irL3?6%=_dK6H z$kAXX^iU_CaAF8|xmGBfDsQN(0Wxhh7s7oWxehH0C<-c?+&>bdg0o2BC^Jj>6njIUS|R^8L_;&|}Kqvh}Pn#k@k`TRG5{;Zi-n7Jf?r$*=PgFR2 z=S2ctrugsGhwrunDT?`)s)d7ng}YVsr`v|a2x!feC__D@1N}E(g#ffGKtI(#aPwe@ zf%!13S`G5D>g9f)9j0A)k%Gmv#B4P9okx6`Jvi7*1*fR23h#4Uh|3wKN)eG2Wqr2% z6Todl)4-9JLz$>jZTeV_5{Tqmms9>*ZWsSqZ4pB>^}og4AND*r%^-JD^iaOKKHx6Aw&w z8SCwoV5oPV*n7Xmx@v6ogh}3s zw9=FN-)l?1r7{{T{OvN6AKmbKRGd#>h*LHC$8MxjyRW?TBm~kdiK$uUXZ3@yVmfOj z%ZQiU3m+BZQ|SkR6G@=K9GC#dP3i!QnudfTcYwVGbY5o80Y4q#K<2zF@(0CzUe`OP zZKT(PQK$|JuJ1P-AHs8HRCz&rKS4Mq!tk`vvZ)_;=EKM->SchsJDIMZm~{^l=$qICizp} zpcoIa2<7eGwc_NLXZ&GJg@2J~V>azwZJS70>|oNdDOEsENVGO4btYe)C@B1`p<0H0 z;LeXgNgt?Wp-U-#)r>z3Q76_28+43n2hI{$#YOSEmR2hxevmf~#Bg#qbe5)ZH~d&b zEup1p1efpfeZ*75QT$Fe^8Q)nbz9{ap2AZk%dkl+~~BoblJM?1|Nm=975$l17qtTe!J*q>VYXl18AZEWS!+ZtgT zLUCc+8rojy{k_1Qs<gH`!G1{UlNTfJ4xGpBu548S2$NLO<(1F! znnWC}o1Wz*i#iB}w{Uyz+xo@n@{33NKCG-7e2~)qjZLdNVq634C@zKY=A0KHvB7}| zYC;|{Mv2Aing~S)&|yHVhSP@5xzTy=MCOj2e^=8hz9GCB@eR^in~>e5sa_D*so?u? z-Tf9Q#@S*}^^ju9N;z=J&d#~tu#zdd0?qOc8TqDLi@3J9=bMG7uzq6HFJNum@<|f? zm5xD-&x3=`Zef{bGG1U?Npd!F{8$`iH>wHj2SXIG0|Bw!QAndo8)um*gv5a4g1d0) z^N%4_CqcI9PX>lRDjNv?{+T2zW5iU_YofzK8>c+l_TgEX^vgjuzWlsw)jIYuR6D=* zDM@C+;K*`&71MU~_p&zR*9+bHutK*;^hQhmHkE$0GJgx{T*e;?A)WhI_}qYPb+uf@ ziGDgByHErKfrr;Rn_eMnkQleqmWU3SELMjdO{4(6_V;UmPNaV+`{pA=o@qP$eZ z0G)^er!Q;5f9vSOX`fTLatmu1mHzWZs>2Gx2Zu^7Gk&83+z89SNzD3yhV)G^SW$V~ zayAOm;rR-3HY5e1WdQtqe`7#kF%qo$W#nL9LfUH$LONdD$R@453?(y*P&n)AFYPI# zT$Hyk@%etg@B7pF%{lLLp7+__=iQ#) znRA|Nc|X5=vEo8@CG}(r{^@Je>T(G7&WE?;{PF7r^8*jdLw<{V)$Y>tlC!#cYejQz zb{?C-kP>yis3)afBn84L$e~ttGTba1%w6e(=E2uOr21fQ(;w-u^ZQ5 za=NSHRi111kLRzi&Xnw%uA>`zwHq3L3{ILd;biVT%ip$oJ{lfnc|5ObnRQkXx$xRP zw5VRbsw(HgyQxv^2zuM;E%o|`^*gn!+)Vfn{=VlwzVlSwP5el&Ca-CK-?a2R3;mL- zvo(K`^C+_f?oC^a-?*gCZ9lg>3*BVkHhkJ2PQQ$1KR5^GBlv~Ige!m2E2lwwA51uw zcvAWZ-2(O2W7BcS#gIL=(#W0WpE`5CARuS|43INHTif~2@^;z8v1!s9rWb5W8h13* zTJ%_gcQuDai^kuc8*F8?X3-^yRfAKw zQhf8ZOEJjCVV>F7w-pKV>nmpTSt?$Qi(f-z)37D=O@(&sR( z=0zObee_q!^rK@onWnCN9+c4e?9MFbrqhLw%Pu~Fkq@f6ojb(_Qw~fXu{Z)82F)EuJh}e4?a0=Gb(L9P`V) zZ;Uqk&~k|*IBDCNEyNT~%au;UX{Ds4+D}tA?JDGcCt%bhoG^THFsv}BbatMH{K7J~ zjHNchPczcax#}3zevq`ae2DmfZmAU!MTa1)unR|(~ zLqS!>>`q#(;asjs{NAbQ@A9!TsojlD=9j%6Lz7Mj`YNJ(wCl`n-L@GCer4c4#G2{(x}9*gVoN8zNRBZ4JD+m90)*-Bp&bk5vkiB>(l1-GzigyiO8qZy)2y-^p_TZ~ zk=5KCqju@u2-!cJvpRUaN%Yk>>mpV~U%OWGxZ~_OuZP7}wX^*D8eGn1$VQ(^6OZ@j zIazp{ue`5zD_VDt{$6X(8_1??#oUjv`>Cz@@kTCHGsXPfN{Y?+>uT0POP?_)zx@TzNp-n064%v>k_ zS+X*H>=nt2;&pF7)&K5{Wlwz2=d<{7tlrqfQKFrH8sNrR1t2dO{_w|{I$@VH2mN=&nt zFXoc7X;#?Vl;DD9twWuV?BuM)8zbGe#9R}YY6bl?^D#DXU+9+2ML*R9U)T_M^-_hG z_2!yHW^a#!UoD}kO+0zjM~fr#kFGE3x>Z>oaz3cYzR=FRt{Zc@a+JimaBB(F^+r6g z^ItI(NZt`o?@hXM`B9ef=xy^-C&c{fxvTbtNv`8X4?J$-#iN3_t?o#c(r`mDWe|>T-I%ME$5U}C&Ue26< zvfDrD-(M_S&1|6JW(;4-5SpxC;V>uEn#Eh5{bwjWGyyL*ng zQR^d>`(aG(l8|vb+pMde%d2P4;T_DssQ)Q1IpE#x`Nhkuk5)~26gx~5JG{3CWB=O` z_v2SC<}FUblvJI3>7?U7rr^>0wKRGC;@XB(`?w6A{!Z66=X8hG36$6hw>8Pvf9mqR z%#HoA4T5eslgt|*WA-dO$tm{C{lU1s)nPPstwr&hP)hx-i+9i@3)44dUD{&l|ttMiyii@%zUkd!3ecb`0Ar(T+(w zp6q^h^8}v|0N4POwcs=bFyMmz0Oxou zU6dYJ3r$eMpxuy_7Mf-a%`rz(%0cpxkpXN5$`L@9Gk^^NYzg4)>oL$s0FwaBOHyBOeEV;iDW9-9!s*P+L5V5 zd&t`zrCkMsTzhT^0ahKO4?&xUK}c>aqAiiAy;;$;3&2!U01pHBdjKAxgdYP~ORjJW z(i)6>z}4Dnux-A=Elq%k0^sieZ7YE70Sq)k?+|8iDC{LsNfa!JLv4axXP1vmwOQW4a62TMefUn=K~LfD)rX}?rtVp5}6f^ZjHoDCNaW67eV zIQp0Ng&}%TIf!0$4TE(n9PwYO{cKP8l0K!>!Kx%OHnOuQbj@Xj_cxJ_Y;njAHy};v zJ!HolK%zcH`H&{{OB<|1%9BRH|7B}byTcF_Dz7PosVP849@PU}7Q$i)Smo$MvMrfL z_ze9yi%2MuiQyoS7nV*UINGXs)bK-@Jbh(+HY}!-DMSK^NK~@)V?Uz?8(##v>VkBg z5*V4}F1Y?#j-%618$CfzOD;V~EQ9-{p$KKAOu#{wZn`HcN}?j@M=EFnV6I0z%oK9r zK~!pJ1szJ!Z!&t*&o7mUf!mbo17P&F-x#C`=&q#LEEFvB76gJ0;Ynpcr!9p@M4izu zK)rIPM?jqq$i9m*QYf=+9r2F#jznLjGWA+boI*jkf|W#^ZD)tK1HIs(#;U5;z^fb_ zUhZ@<-WE^9s~I~`HI&aQ&@WH~!`uL1vLIZd7{cnS3pxZetSV^74&@#yeNhBY3eRPM zb%X<}ygvx3#-Z8|sa^~Q2pz+CU`k1ltiWs;FN$l!6VM16Y1CvOOFNaxiiGI{kt&Ta zfc=aV45=vkpis7-9Ia8K2P-_4fvmx>J2>e`Txdfi*^nqfB%&fNTuLJhA=1Py6bA`~ zQS>hb$Z9f_ltYAoVa*GRSF?d^L$(jGq65EDi??AS3B2&U_>?mBalcS>}2etoAnfp5P0 ts*6+v-+ZNV#aDrEzWS<*R0Q9ArE7{2M6@LiYdw literal 0 HcmV?d00001 diff --git a/autotests/read/heif/metadata.heif.json b/autotests/read/heif/metadata.heif.json new file mode 100644 index 0000000..8669721 --- /dev/null +++ b/autotests/read/heif/metadata.heif.json @@ -0,0 +1,59 @@ +[ + { + "fileName" : "metadata.png", + "metadata" : [ + { + "key" : "ModificationDate", + "value" : "2025-02-26T16:52:06Z" + }, + { + "key" : "Software" , + "value" : "LIFE Pro 2.18.10 (Linux)" + }, + { + "key" : "Altitude", + "value" : "34" + }, + { + "key" : "Author", + "value" : "KDE Project" + }, + { + "key" : "Copyright", + "value" : "@2025 KDE Project" + }, + { + "key" : "Description", + "value" : "TV broadcast test image." + }, + { + "key" : "Latitude", + "value" : "44.6478" + }, + { + "key" : "LensManufacturer", + "value" : "KDE Glasses" + }, + { + "key" : "LensModel", + "value" : "A1234" + }, + { + "key" : "Longitude", + "value" : "10.9254" + }, + { + "key" : "Manufacturer", + "value" : "KFramework" + }, + { + "key" : "Model", + "value" : "KImageFormats" + } + ], + "resolution" : { + "dotsPerMeterX" : 11811, + "dotsPerMeterY" : 5905 + } + } +] diff --git a/autotests/read/heif/metadata.png b/autotests/read/heif/metadata.png new file mode 100644 index 0000000000000000000000000000000000000000..faa4d492431acf47742a1b252734a5a0af98a721 GIT binary patch literal 14638 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≪<)YB1?SBw)PBSr*qBdqkR@2CYi_bjFd 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 iZPLp{WEH@7#^ft;XOTN?#tt~~Aq^E> @@ -18,6 +19,14 @@ #include #include +#ifndef HEIF_MAX_METADATA_SIZE +/*! + * XMP and EXIF maximum size. + */ +#define HEIF_MAX_METADATA_SIZE (4 * 1024 * 1024) +#endif + + size_t HEIFHandler::m_initialized_count = 0; bool HEIFHandler::m_plugins_queried = false; bool HEIFHandler::m_heif_decoder_available = false; @@ -305,7 +314,25 @@ bool HEIFHandler::write_helper(const QImage &image) } } - err = heif_context_encode_image(context, h_image, encoder, encoder_options, nullptr); + struct heif_image_handle* handle; + err = heif_context_encode_image(context, h_image, encoder, encoder_options, &handle); + + // exif metadata + if (err.code == heif_error_Ok) { + auto exif = MicroExif::fromImage(tmpimage); + if (!exif.isEmpty()) { + auto ba = exif.toByteArray(); + err = heif_context_add_exif_metadata(context, handle, ba.constData(), ba.size()); + } + } + // xmp metadata + if (err.code == heif_error_Ok) { + auto xmp = image.text(META_KEY_XMP_ADOBE); + if (!xmp.isEmpty()) { + auto ba = xmp.toUtf8(); + err = heif_context_add_XMP_metadata2(context, handle, ba.constData(), ba.size(), heif_metadata_compression_off); + } + } if (encoder_options) { heif_encoding_options_free(encoder_options); @@ -904,6 +931,43 @@ bool HEIFHandler::ensureDecoder() m_current_image.setColorSpace(QColorSpace(QColorSpace::SRgb)); } + // read metadata + if (auto numMetadata = heif_image_handle_get_number_of_metadata_blocks(handle, nullptr)) { + QVector ids(numMetadata); + heif_image_handle_get_list_of_metadata_block_IDs(handle, nullptr, ids.data(), numMetadata); + for (int n = 0; n < numMetadata; ++n) { + auto itemtype = heif_image_handle_get_metadata_type(handle, ids[n]); + auto contenttype = heif_image_handle_get_metadata_content_type(handle, ids[n]); + auto isExif = !std::strcmp(itemtype, "Exif"); + auto isXmp = !std::strcmp(contenttype, "application/rdf+xml"); + if (isExif || isXmp) { + auto sz = heif_image_handle_get_metadata_size(handle, ids[n]); + if (sz == 0 || sz >= HEIF_MAX_METADATA_SIZE) + continue; + QByteArray ba(sz, char()); + auto err = heif_image_handle_get_metadata(handle, ids[n], ba.data()); + if (err.code != heif_error_Ok) { + qWarning() << "Error while reading metadata" << err.message; + continue; + } + if (isXmp) { + m_current_image.setText(META_KEY_XMP_ADOBE, QString::fromUtf8(ba)); + } else if (isExif) { + auto exif = MicroExif::fromByteArray(ba.mid(4)); + if (!exif.isEmpty()) { + // set image resolution + if (exif.horizontalResolution() > 0) + m_current_image.setDotsPerMeterX(qRound(exif.horizontalResolution() / 25.4 * 1000)); + if (exif.verticalResolution() > 0) + m_current_image.setDotsPerMeterY(qRound(exif.verticalResolution() / 25.4 * 1000)); + // set image metadata + exif.toImageMetadata(m_current_image); + } + } + } + } + } + heif_image_release(img); heif_image_handle_release(handle); heif_context_free(ctx);