From ec279cdcae9c8cfdf3649a0d8c1df6db156aafcb Mon Sep 17 00:00:00 2001 From: Lucas Cimon <925560+Lucas-C@users.noreply.github.com> Date: Fri, 30 Apr 2021 18:48:19 +0200 Subject: [PATCH] Fixed "fake duplicates" bug when a Pillow Image was passed to FPDF.image - close #139 --- CHANGELOG.md | 4 ++++ fpdf/fpdf.py | 6 +++++- .../image_types/insert_pillow_issue_139.pdf | Bin 0 -> 32656 bytes test/image/image_types/test_insert_images.py | 14 +++++++++++++- 4 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 test/image/image_types/insert_pillow_issue_139.pdf diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b4c641b5..cecf3f7f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/), and [PEP 440](https://www.python.org/dev/peps/pep-0440/). +## [2.3.4] - 2021-04-30 +### Fixed +- a "fake duplicates" bug when a `Pillow.Image.Image` was passed to `FPDF.image` + ## [2.3.3] - 2021-04-21 ### Added - new features: **document outline & table of contents**! Check out the new dedicated [documentation page](https://pyfpdf.github.io/fpdf2/DocumentOutlineAndTableOfContents.html) for more information diff --git a/fpdf/fpdf.py b/fpdf/fpdf.py index 56b87b375..f0fdc6567 100644 --- a/fpdf/fpdf.py +++ b/fpdf/fpdf.py @@ -34,6 +34,8 @@ from pathlib import Path from typing import Callable, NamedTuple, Optional, Union +from PIL import Image + from .errors import FPDFException, FPDFPageFormatException from .fonts import fpdf_charwidths from .image_parsing import get_img_info, load_resource @@ -59,7 +61,7 @@ HERE = Path(__file__).resolve().parent # Global variables -FPDF_VERSION = "2.3.3" +FPDF_VERSION = "2.3.4" FPDF_FONT_DIR = HERE / "font" SYSTEM_TTFONTS = None @@ -1720,6 +1722,8 @@ def image( ) if isinstance(name, str): img = None + elif isinstance(name, Image.Image): + name, img = hashlib.md5(name.tobytes()).hexdigest(), name elif isinstance(name, io.BytesIO): name, img = hashlib.md5(name.getvalue()).hexdigest(), name else: diff --git a/test/image/image_types/insert_pillow_issue_139.pdf b/test/image/image_types/insert_pillow_issue_139.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ba3df0cba295647de7105d7c23792e3d789eba3b GIT binary patch literal 32656 zcmeFabyQr-wl1E80Kq~MEI7e~26qVV5~OL|T^e^ua1Fs7f?ETPy9Wp!+}+*XUXy#? zdpBqA`#XETd&aoqx5xgcYIU!w>Z)0_zPW0Cb5@hd35n1$&@mx05xpY<>6#*PbJHt2 zTNx11%jp;yAVO0c14}z12IyURM0$AxTadkto`Ee9<9~c12(q+;-nS)Ue)!DGi)dh} z|Io_A$A7dYVq$J*U_(SNVy7Cv-{P!-)e{=@?)h0^wt)rnkjU|Ipp?Xt?6B`5_S_0}+p3%#il#rs3tUt0BWI5Y zB5dGWF%(Nj_7nse)atv={E4^5bK^58iBC1oD@H!E#E8is^#Nw(wwh~uQ|#3Y2c}{s z%jN)+0w`*P)%0aX(gu_GPNiA?@F^i2-IGtR_ftvrTwE5q5>g19N^^4HQ;<1_@&Ni; z0TKK>JO}z8WKp>%M~0318#i$u%QP83jQJl!_{ZoUr1cwF+9J|Rn&{gSsXa(qUIUR{ z5M=)#Swwni1AP-60gw}s+B@hi77i9VMs^~0W(GQT4h_WrD^r$#ZWSo2Yigiphe)qr zuWR>n&crQ#PMWfb{)2Gey+foIGcYkShW^UKwIIkGWTRlEqX(S;Ap-{!Jp*}B0YrKM z6FXZu0~3?U^5TSJ*CJ(wIENqFO%S6rw+HXBOkPQ(73(RY4!Q!LerpO-)#}?Ut_!de@S#*QoMR`IIP^$!vb?OYQmV4^?QLY@xnwA*7eq;+F zzE?`nklbE|+wI8D@p4sfEuLw;Hz^#ai8gaUtTpVT+(%d%Z3I*ZG+TU(3HeCI-TVX- z;sXzCeiC!=2npEyia`4@60jA9M*Fd(6SNc#un8=nK*&{u6IrS&VJcsF)O~?qacf8BlQOd(Qnxq zrkhy|=c7rt=9q-rb1jUDAGQi$Hs8aUnZ8*|>a9dlW&4)T;vsK~=%5jbn*LA`l{%&r zl$z#_n3(1|26;JHG+5Q6!7|A8rKNj*IN2tKZ*LXqaGNG~yd;m*ffUN%fh3e2P`J_@gLFDeyL2 z8J-b1iki(7CZ!$(izTaR9m{&6YswrWIOg|{*<9iEJy%9QA!ACW>o-k?5&*oZMW0Va2bQ*0L7O|l zzBVlo=U8wrJnJhnvH~nmKl~&cl{Sag`N8DL?7&qWw7m(~an|YUq%Q2Nb;Y5n^%=8y z{u0IWgFtBiFnhiUJBCXn57jz`j_-dxS3gR3B=S~LE9nJaW0+N^L8@jZ>B*5?y|IgG z<_#y*`#T1SIKQ;$=G8MTZ9yLWVBn=%w(Fe z7@NzWvX|N~bN@@{=RET_+vm$lC(usaZU5ea{8Ov<*TSBUZUX_mzeTTy$MP5S`tRe6 zsEv;EzZqy4{t(doL(i}>{AV?@+xHmZ(IaG-uc!1473_HBA2&aVk-iEPA`btrvm-ui zhKX(J-%5+^-!HBISyX2K1(i7%nSK%7q_i0t|7-Yz6>41@^yi}p)&8K4F4dj_RpePu0eO}KPpZ(o0+S5#!4WcT) zii*L!!g4gq=$ho(?X7fU(rHtlGbU|3X|%TCXtoj@?X2xIZPE8tRXuk*#n+jOp{NF{ z+k2D;+gfzgTD3S+9ioQ1ZOK2-ZoGhk;IgYpM}`VGjFl#_#xe4juyq^7*~+sCEeTgD zv}QVKIXcTz1m0GmIEuNCha?y{I;otQ?3O0_Nfsv{(q_x+R1n%W>gK1RubIXS)@Qfl zfk(Q!i>b)&=hC}ASII}LrX*U3+UG%b%8v(f0%w{^ovZY8jPeyL@m7v;q=9XzlH1ve zKxXWctgd9$-ljO5e06a(idqO2fVsU=eUd!f%Thjw zBAztYX^OxatZc5kImySaUUNMks^TiwPG_{JXr^qBvaIsgaFk`{Q8bgB@#JXU0Pbmd z?@k&%9_H-31m(2(k2=l{(}X?gNOk@mY{G}Z3w|qGHUr8m^O}+qpxIBtn4p>CD6nhA zUx8HuW6J?>PvD7@ey=NNih=K3IoCw5iv>p`?MVMO|_d;^OZ(ow>pD+&I5 zUJ>^J5PJgU!}1Su((M!9BCeTL5pT6TeP2m#{hML@{*nH{B+_qz>ESv4 z8^-?$)c;Eu=lJ(a>wgx;86Nf$|M%^hfsvWz7a)(9G)K3`>s+rnHm}_C>)w|bn=?E0MJ}{=tiwiBU1)jMa5Wj?V>wJoX%KgL#&F5*w zi{*BokAnwaL{FYv*nd;EI~Oar)h0HOvV zc^o{MPvv-Y8j~*uSZ(bK6{pE8pZ1K^)Ss;Tu#t5|K^V7C<79&7`eV)LQCI^d zK1#}vuZnt}`15{@$KYO_zDd&oBQno}-j{|k$q9NQ?fv4Wjr?1=maUbFIPJhz(^+%> z*U^_BM}x{}ptCgSkAiyTYe)AN2?-%73Yd|gB5rxSNQ zYUQ!j?{{PKx=I#=QLB{a!~?(dey&)(LzMa> zi=Adp+Ekb0!sWVjZDFjZo zHh+-X2?pllNv99Oj`R=o>9Oa5(Pciez&BBOK2K?+s`yuj7 z3w*+Bpx6C1Pk2V?I zH0REM_k!^({}|R_(l#e!}E(idK3Y>5fO1dr4tViaGp%-O>6H5u2Uet3H&0P0;r>8Ulr=}|cs6Hi!Mxk-f! zG$e9#`@nLbdBgKAl)&)ET}(pqPbpf!Unm*zA^ox6%)(G^K=T-@H#E@P2T2E-lc_&@ z$QK2G&>R5^TJ)J@HMA%q9N0``{&As6L3%MMV{{ZHgUf16-N+q@s!nz~c85nAzO0Y# z_NpAxo3th5aQ>QI9s3QWTR*Sp2C)ndm7~`^tW+6%@^i>cB1iEMu&XptdsSYIEV*C9r^w3GBgZ-rhX6?Zg;W^Ik_aE^YrSCcYlix3QXm7q5X`$#2XUdI&!xQx@aU zIx>yh?ICbI>A3$Yk$kCK5svJ+DkY0HEHZ4^o{)BJzmELr6AOcZ&(azk7&qokXI;m~ zoHgC@!~hcVn#9TcYZk{B+6-1R>b<2X5^_4HjX5fkyUq&7$gZirSz$50?UoE0Fh5#^ zG?|#q8QYru_aH6k!kt}DdOc@GDpa3zSqbsSmNji1mG><_~WQ3 zdG3jKUm&IPa@1)24eRj5ZV4FDPLTX6;GHiIyPb#>Taz3RrcL}+1GhE z&0FrVg-!ckP-!;WRSq6&9{h-<6aD5l9X%q-TMQh6xXhKtw}Z&?P*tq-{W~kT+vO82WR66kAg|ltmLm+1 zuE>xf)nNliU?CgHVlQ`-J?|mhTHFh=Q2i#>yn7ic$5p*J{FH+n(5S_jlu=({%PFEkD1z zN}s%ZGOhlozk+}NUZ`wuQwQ0NZeb~n6>=1dGS$wxbLEA+zH-R-_F4b?FJWLlewIfR zoJQ4#%_IP++;~#QK9AXWMs2?n1|HtLS7!|Zs)xCVRIfuWWyEf&Yis;b3C@W#c)iW;U!1wIJ4uPvMzX z<#COsOUQTiqxzRGg%4n!2~q?t zBnL6ZapuUH#IR9YL~`s*linXS;m9VeRvGQT9hx9SJA5sE0b0oTvt}0Fc2h2}L^gDFcPiSwU-szS^BJC`gXN`(nYKS$%Re`#*5`-&gv`x z3w$FRi3skPBp-gQRq5xF56mbuGB9)Vi>^utk};7l!TA?*5cCd#m4tM#kQusrE(vWm<)=bapC2&z!hsiM zeK~qaV&Y42zQ7%AIhxFv-1796OJ<=$(h({*5eeNJvFki|;vQ~KI<<6jkMFMUH*A!WZ#1A+1e>_N z;G|KtJ<78hGWfh**B?9_X3Fy>s8eEYWgxY7`{*W*>+@3HfzGLhEpv}x?7A%9LVI~O z65&{8hRPmoPT9=VyN|$rhMo$QBt5{Q54AZEh90kMan+#LPfgPo#M;|`U=KL=ndaQa z(=tMFe>Traecz)W%$4;`yqMZ)N_faOtu6iARbhk9aJBp`60RdKx+Em^+>g4&l+Q5w ztu?@)Gd9sSi4*VqIIm3tlC-X(g!xo5rkF)5d<+S*BBXYVlQ9If#{fQ~ReTfR5e2*^ z@poxSw@X0NwkTsQ67_7pei`HX9uXET+PwDN;Fk#791x!9uwQH4_KGwrpKJ4uGG7g%x%ZmeE8 zEl=+IcJY)BEX}{5EdP^<{9p5%+6V($*Z99@PGtB`l>UD>2>kbP>Mu+SK`HTnyB7Q( z-b4LL*E6xR{{rhH3=-e8(S;Y!jUwVnS*avm;3B=u#>T}E1%rK5yh0Z+)qS=hju@_giyda7&(DEUM?pQ2Xfn}D;nx@?!(jc7QS~)L0JFH$8@RDM!Faf}_^qZFFxwYdRF07< z_jz|n3=o;Q?a{JN?tDDiSM=YS6B+?#>wH|UQm0x0pX@Ib3#Ay<+&HBlKCv|7RunX@ z8DxzvgSQp$eIEhg!$z-m#_0`7r1yH(sI)xt?*(3i`-0sX%Wh}!c$9a0WE5_(ymU~i zhURvy?n>cf)}i-zw{_RE;~Ht}cbG>#-yn~rUgmf~`wi{!Zxi9pE2G~G>JN_nKNmYk z(DhMM`JFehznR?MA$0#s3V`7+N98j7%H^{E^P8BoF&aNQ{K4eFPLYMYS;CYlAH>4A zL~DdOd;05w_zP5FbRprE;IA9)-T^Ly-fXDEOTzrch??B_@GphGMW&!Dz7TqW6r}V6 zpe0s|MkOx#%)PG5^OBIlWIdMc*zi^O{qmcjmpk|TK2MF$ifZD)mF8bv3Zoa? zetGKynPO=_RM47jq&`c)ZrdCUAy4b{nav}s+?ZVl_o`K;lyszUCcGIbxhkGC6hOlu z=tIZvl)5+K(Oosv$Z2A>#Q=ZKFeJ-9qS)KMJHKj8A80a2eA#QI0&eW71QV&*5wLZp za+H(aa)6eihi&JmimO)$GCUy05d~GatE+PO)aR2dY7&?tWvo{dmyS|vp}5;Inr-KL zryp4^=QLRI=~cK!OIXz-3|OpYiY%3Oay-j=C%INnv}>Kw`=*>4wU9 zBB7uw$BOf?bxD#wz~~u{2+h`ZAy+qRUMB0+cN0GIeC@#@>gQ(DMu2Q zA&_}M8>d{yfDf}@hzh7M&&{dCVq{NMP*fJfiP`XO3h3Y;)A*JRzr9;tR@ck~8|RRc zzRjMZa4vW(Lbk3FSUyzI4kZMzZ&5tNO@pJS=*P9M0PWcbV1ZPW%-k*jC;=su<*qeN z(*7{5XYD(TADRg>gj|!;?gc_O)H1?|UuIp>k;(-~jFP~AcZ|d>uhW^1q-~{1i>Gpq zGu$+hDGl=|y(+V9D0c*Q7tR`u^qegck68EH1d|{X3BRH|zSRAonjvyE6Vt zyK*pc{PLDGC2kCLYJ@*HH|**C#)>nYZIU(RUObzaSwcs_e=_3zRl6k^_ySe4-bwyo z!E1q^|3#Je*RNhqKfKf7Q3=!!wE4511qDcAl+anYvu;Wykneu9Xq3A0ypcU+VCHLb z-gl)p7(_s`el2o`TTS@@xZi&Q?oYqQe{mTjS@Hx1QBMlR%KzAP4wo7=zp)}h^;=E% z3iqBxw8R;eh3pAlr|PZTI-_k6i)9SqFlllY?x$o4r*Ge-!9R=yip^`Nn(?8rQ-K5#%W=J;&At4CoURQ7e=L%R=_Ruod}hXM-zmK`=((j7Ks zpk&L-;zP;s!McPa-O%=N!Ck&+^*7!KV1A!V7eWju*<2b;ILb1?Q_?MgQqWP)zLE7N z@fBv?lQ|nLtm{}ba1fg6po8#;-r#eC7?Tn@{iFL&!ksfAO4WUHJ>R@WZ};X?R$uh! zfS;U1^|cLel#~<6s@tu-ELiq!$w5?(N~6i|G0Z!{B zSbFFvci*?X>Weado3Ovt!cSIGh=q?GsCcG}K+dWcFs!>P%$T>+Zt9w_6tFQ*!!~#H zh?*mmjfbg3x2=k|ar6l_!C*xN?@$|w$cq148NQ|5+>4r3GECQqZGW2fg!m#h1YBZ0 zGS_Fd@Z;Knc8!c+iw|d|nXIrt6GBRn;bbZLGrG2XUbA^w#ndi4+(kxkE%h0lioMIB zjy*E=5;&GHyj)k)(fKo5!BVw`3d%Uvyx9bcIomeut?kT~3KnWe*GS55IE&y z5BOGPO3>z(nt%$V}j(lP5L&x=Xt+?cVjK6rrS8X-HR#iVLn!~$(uA`Hp>o2&`a`BKuQ}F`d^|ip(`QcKXU;YIxS79(HBivX=HNxE@j!@_jMv7 z;Y;%4Ec-gvn@|oWWkHC`JX5)d3f1BFgs7>48b>d~@9O1f3KDtP31bD3O~NFas}Olv zvnsA*{5`U znWX0Jw?yJ{64-J#mus*~m3PzH$U#+C2nJW0<~jz&6RMG&Uh=))5enY`r^&&yxSzp3!4nPScJk}6-*U@jLVu+a3h9<#Rz(e(YOZ`kM&kUYCbHejh)A$c zv^!r2#takF{@}=~B!SQXf!DU>Y$o$q@%NOiXRs+gR_E9hlNx=+x7cgLtbZ#g3Vc^nk*ytiYraVv zqPV@Ry2yfL!DARx++z)hLs@=~*z(RBPB+_Bt)Af4j7LnT4*Ii@|-_3Xs3;>?v*QHuC_hX%&fU$-53WblW+3@Sa z>>-Mj8%aqGmXRCC-}bHZ;acbk3$QRffp53Fl6u${zG3$mqq>6PA}IPh&Kh*K`^EMF z8O_~?oVX_W(+&H1kO1pEV{meX*m+l&-}^(lfg2xsU1ka(UQi)^_B{O{yPvpat=IFed#B z#`=TIM&UDXV6o*nhHGEcqMeBd%&=as%;4@ERNlGh85f+Y7CT2I7TCd&JsHIg9!_R7pyqiI4!XpbjUCJaxYHlzhj?{mG1 zYtoI;>6$2RATHfu=~jcKvKi~mH=SekuGxwpvz>-Istn~`Epdo(8TDs>*2b>+3e}F| ztQbSv(Qwq6z;MZu_`P?a_pyk<*_zhewAZ~;w9_&N(%OrRvPQvc_y)m>@;%%(L;ljv z5b{Q6yL?l;@jURSW!M2R523BEEkODe&Me0ClqnZ+1Ur=sqL*<=fxxEAi&Aor@O#8lL`T40jifg7k z5;fZ{+&%`PV**^|p{9?5mjJMa-m;CHPFR_nQ}fof>Xq)`PVlvQ_wI1V+~}p&=Nq6| z*nw**TQ2CXoLl~tF3Qa6Id6jdGGUCg1SeQ!V0Rr2avQ>O@(z>yF2n^Ij^V5#>>{G& zPxU?zA`dTkTZIS~@M3Fk7I+92yw&=%aVh^L>2{2D#PoYMq@NGk-$?t1k@hdgv@!n5 zw6U@M>Z~}~WQL~mU_-OmuAz+<;k4ud}jI~^?R2P zqI;Cru+SJ-Oy`FsAN~*y`>!r_KUG{zrdF>N%^NuVDpoGu;eR;54+ytbZMi(sy8{ioy*cFRIN&6Ax@*)iQeKA2*u@HInX(b)L04d# zm8r7uTnenvIfe)8<4$OI73On%oT-fQaHwONHl8&Jd;L&20x5^1c|)h}IysAJ3uEps zVhpqZ9RS%Eqx3~s1zz-3B$@q;ZbGU2PbdKJ%2_#Pc=WFA%T2a}=7@EW-fqe3$?1V@ zl_u!j#Q;_Q;VLdm=RDSf=KPsHAzL_%vg?>wc^FjimaVJ@simeL*&0Cyuk04Ic7o?3 zhqL_=LDNmxEnO%a0dUkPg(-iH2Co9Qz}s@+6B%Ela84f|e81q>P#FJ1h1yjd8RqN> zs~Jl$a_uLWF;h9-an`ICiTxdJJsWIL4zvmO@)p3HIa5Pk+{yLgp^N#RM;Rd46*9K# z!t>?b!z-v{w+L_3@J(f^jK8-He#CXs?y87H8BMw?FFCfTzyAhpr)A1Xz}*zduuo%O zZy;|TIyW}5?xvAuMvEFd9H+Q(+J#T=LR5KIkNambr05Z1Bh41PSZqak&`XM@sQL2X zSb@HJJhw*WJ-JsX=8*J#=W7BbsCdRaG5)Pqn)!(%$NJx~()>+y{u!$~<6n;Ggr1l1 zYp@gJ!!ZN@=UjkiAYcQgo1tOJD-4r@~wq1<$d12+^#If6n z1s5 zmb1{=Gb=simbwxWG>@c5dp^c-WLshtr1oOWs1w3nU4E&Xg?TwrfwqK$-zfrnz^#>1#3=D4mzvzw!IGG zRPKcgY=ox7_Am)tw(3zH8tfW-EM1-50t7=*>U>GUK)XjLH&mf#1t*+)+;WjxmpH`N z=io*c?Nc5@YlSfx!<-Vg0gVeOCyNiDOZrNO)s_TDF3_>Hu6Y}6+F9N^;tkD-MdggS zokZl|%D54OBRXFft-UluR#yoiz0*9&hv@*rR$|+gS!#%H-D6YJzT0Y;fo{6^X)HBh zyPj^J52=9x$7I1fG>Xs97|#PE3=7v`2A(#b&L^WZycl52+{zer>3MPMb`%ULbU%_b z8B>^k(jPL{4zp~&m6$s#XsdlW&r;nsbu!oyv*`R}YPkb-thcje-2jEW%J^lZ>2sQU zoZPGIM#~GN0Uny*;ASP3jke;6x%j}24K+kMf*6$TC~7$U#}0FrpX)9CKWyp?zwk67 z8lJZuZ=Fu&n^}_8U6H0JYg;JoEJdke?F$w{?3qu&!SM~F9?H4!HtsTO8GhZfhv;gk zY7H5h7Hm*M@e!s#@85Cm`3ZS{?-Ks-F5xf7G&B9mG&3+U{kly^P&39e zK<`{njGwJBXQeiY=*v#9nJK4+rq?PMaxAmlb zsjMvoG*kJAgC-(@{|9qq&{ME)YDi1st9T8Y^w<)g%uE$iiM=L3@|_rHtjlw4;&I{i z6XE$*{fxC1n(qx*1!%=4qpK6ms;tM3qy`#CuBEP{M=wbxx^|RBYH6;W*;maC?yg^; z4t^YU^xf*oyW0>nUo@JZ?f1|jy;gz1GrssT_O~hw+PeP$M*TtZPsPyuLx=c&z+qD;J`P#++Y!c!#OzEXTnL* zF8%T|G@s)G!4*>sBnqEFC+}I&6$)6VOnQgOpFkLmfFA^Lvx$zFwmAnFGv3+JVx$b4 z&t%9Ndk`QF*p@9NHX7pMjE&VrC{DdyKGEFb<&`lw9~lUzsaZZj&|D^(E%!IZR)|C@E;wcBEpoDCR0xo#Mj-(9 zI_;xs1u5u67g?vz!(^gF(8%gaaJItKh$sYA=!e* zUZ1X~%kkpq0Ok!(%Yk?O(VkQBCiRGjpKx5JpTA}BG~ux}KMw`HudM$_^dTh~mg-LAm=MDz)@br=^y< zUan{_q4fC~-@j|(0}s^to~zi-cVrD5p~F5$O}{QAO0Q!pVCvPFHHVk2`ufyz)rLtm!qqXN5$uXUP6!ZK$Jrcb;=tLC~$dM3$EH7whM zBMcw2HFnQ`&TET)nZ()a-o_+zz6Yt!9Y7`}@4Ihi`fQtm@#6*9L~D93yz&uXltEi3 zi1|1WNo9T(w821_PjOj`Sbp( zLq?oRfeYi293uC~0%8@&0DCg#Tm&1DFRrPHlV_cRICf879td+b5LJ0DRM9~I!pa+; za9<_o9N%w$1?ll%QIVihB=T_eR4h%{hD*@PXS`=4wfJbCS}X^pJTA@fb=uWF!U8{% zssDS^dzeD2--~4WiLigG*gvXbnf`L*Khv+|KgU1qDyO)N(fRS<4&vQs`%}6$<5z3~ zN!M;aJFoBAbcm7#0Ny@@g<;iwPh)NlMyGKj0#ZI(DtG~Pnnj{Tr=_8B)7E)U26g5N zqttaHweHn$ppUKV(M)(#Hh-XG?fCtUk?S~BMci#lK;7@zJxa`J8-`PZVS- z7*CB;>_kWmNO2dJtYyj5(_ZB$yga&mTlngP`Jj^u$A+NpF1S(H2oUsZ0I9$wX*OqTd zi&lDkM>EBImE4CYC({l~GHDRnk=Kt+Yhx34=56sE#sEbw&mOoUYkTvdy_27sC>M7 zeL5<7vT@GAck&dIKHEur&|v^M%s9`0r}+EPmZ%3!zt9>>qndejRB99jgfkT?7`Uoj z+A8;EC^t?!?*ZIcLKIad_d&LrIiW8+T>Jl6}KCP-m>0JkKt-HwteX6E0*rJaH;n&b82`&L*G#`M*9?pdzdGeYcS`EQuRD$UEe4X9>&Rwz9P}cY`^cq- zNG&7!EYK8AHTc2lx#d5wO451rjkV0@>xrmTU$jp{y>*d>{9Sy5h=?@_!Ld|9@*~F4 zW3DGmlgS($9Ihr4hAw0G2cF&W$0f(h*NvA0NsviT?pzUu-T%E!+Wom%`lBgyo79Dt zZkw7sVL9=(-@=gfI6G<30ZO)}sOkA^rV5`6_WSinIWn=0Gmvy7v8Kc^ah^?GE~kIc zrghRd=k)984n46nyV8#yHAH0xc*O=c)5g>cQr%#>196M1x^1XX*m@|MsC%f(a$KI` z9D03V$1niSqH@|WD7qwH@0RH4t~r8CHIeaxSY&aI-eQdOYU#Wrkb4QW+*p>{fNB&Y ze23>YL@n1fD*2WploLMqvYcjoT`OeQD0$v)cCZR0)v=$=h)6&0A_^e>?97iIvj%QrkHb>iQ+Vk@fE4zg^IkeO+KR0B z#}{?`kI~hTI2MNlg;&vuV>Tw%I9WRHTGdNrOqP*oZe_Mq3rr@& zcFU=xB=@OKLEe3L4LjjdwPR*f!bBCbVAf9+pkp&534%1w7K_PJg?1HW>sh1-t}9zNCuADh%@85 z<>typX1#XlBP-afI$ik=z>kzK^|}wBqG|mGK<1>ibay$W-tpum7j(W|>}QRDh|HmK z5X&!`bJa^w#JhGzH^#cm|DeXf+nn^O*lnMX07{ZrhjSe6#%mCScx+6Gug-FvD@`(x zzy)(!?^!rrWm4YMI+ad?BK;MGnY9%gJier}I~2IE*(bBqef1xKwj#f*b;&ApHqTKL zQ?>Dk@|G%ete_8(!l&btaJMJjN~JNYQdJaB7}pHoG;z)X*3FZojd;*&bqQXJYCaRI z{%qPk>GiZ-K_zb%3MN^wy5~T~BCFSw`jL%&s-UaZnGQ;f1RuC@eS|Ka=Y`itoUC=miDMHQ`IR?B(wI+2nOP&505(dliii;c1!p4N!v^FqGgUDPpR?-kWy zHSOIjO5c+DX*v$q(G;DrRc^9!9n@|p6j#mbpf=zX2>T9y@DXmfgddDjKq`92=<2nO zagXUNLUP}wN})Xq7F>*qtY4RSO_*0Mi6PiB+3RhUy{=a7&{E2vftGqv~^8Ruz1WdoW5U{iU zdIrN3hcWsG=+4F2cDG(7GCEE_k`kdtkIu%ZOl5h{EV@%z*;}ZstyqZX?rWVkEEibtYZ=Q zB@mf5W)7&-^*w8VGX3U~YfM#30@9z%b1-(lCuNg=*nm>qrZN**b-l)QnzhsFE9Dp8 zdvDdo zh(h5ddiuoXa3-`X zW&(N%O|JqhSgz()=4N1_9UnawaF}s~BiBDFC^(}t%`n150F`e6l8;yU51<77@$j|j z*s|0x)fw&eBw_t0C~6PbZt{$Tf%aPwY2~p+19`n2y1HqtpD-_ zv@l>8;~rbt(S=M9W$u08C=cDJOyRq{X@m4lo6pFJIwclZTCB|f_i6+CLhtGuqsFgzT*PgRVR_`4w=fbEku1{2 z!F5S13mxU%{=+#T#6ORKKl<-q-oO$1d_McFhr-Y2@ozx>!+`vk^H5;=Cl7^p%)cTs zG>!!A1G?XOw3J~4bJkgSenm9v7k`rq>FM%3)RE-c5#g6?>ABT5Z;Q}B*zF4pT4HQx zG+HaDQ+lcKQ>qF*#o~SWl(52ONXjVNgpsW!VOspYrzs(&X7hG!#iQzNc!a7GHegORm5<=+_r5a{e#eH8X&>;vF^IQk&7 z8S08Y{B_x@Dqq{4=QPm9K_|V{PndVZgppPIt6KVNtsj1FR7M$<0k9V82xbR~MZzKN zRd{;v7ZWJd5Mla)_UzEv^4^GL;XZY^g3B+9GA!F!C!(PU)b#_99P{^IgQX>{rO$8` z24xjtXs7~wu#3}uKX^%c8nz8Bcig4F-{W>Rj!Y^WK|_|rY9?mhlF);xOg&ypVQ)*< zChgx-v|(7kluph1C`Mn43uuFs#7!026fGFGN;H%rtI9Iwk5vu>o@QccAXB@HK5Lc` z+i}+e`ydn?mkclmsOyhB4VTm$j(b(42DMfVM;Ua$g@gdj3|rF^hM5CCGuk9w@)(m6 zD004`dkwDL71=19elwlQq|;ucwjDNa2jB2k8n$ns^Ft1Acs^Jk5rJYhvPR?BeMl37OUDbWbWpmLac<;SVF=!&Ig5+lwW>ji znJh|g)3_4+q~7l{dipH}MYQ|7pIK@R74FouQhO_HU4Mdp?8R6Whry_dq5aZxU?Ig( z;=3$VPVRN`uA8C0exc(otmJ zxOaM6An2g3aNFvKg@*s!xT=l1JtmnGn%u=lUEY09kT9MrUr!oQoI)d@p7>T7n3Wra ziBc2dtcZ9f4(lD>kRcmibwumm{v>$BWoBwn+BLeq$XXM%G4r~U%Fke5XgC);0veTZ zmma=>tjJ_MyC=sA4dxtzi1E<7&Ar>6gQ)Dp=XSWZ+2|NJOS8|4!Cz-}v)y3QgTdKl zT_rle!-`-ex`Q#65Kc?fqH@$_O+_dWW9WC;Aborn0b7T6; zasJG|a{jCgzbcW52D1@uyyim+P%O7e$?230CN01`OW9PoX4tIo`4UlXMlc;LmbJqx zHmt$fmaHFnM8r#LOAAYc3zUtt&#AnK0~REW32bZ3zO2L$y5IQipQziY^R77CaGS0= zN|7lnHEH8MoMRLCa465ePNp%oji50IN{O9~TrH30e*jM-&Ak2e_{L6l-{11UHFKVD z+i;(1Y2!P;tVzRpU2v=-$|U1bxC-p_{MP2Lkp=fn^^PDc<*3w*wlkrYAa^c* zzRSMoz`Gd%EF7=(V674hNYb|MW>bbed^ zhauR9d`6Fa@UE`HF7p+@Vu%Bx*#l?Mkx*^CXK_+qbwpj{Q*o{O&Yc=~HN|91J2vBf z3_n6>J+*Jg2_z_Z$5j$R)(O8TeQUkph8=j@H&YOgz`m9VVt@ph zH4M!`7UQO$UGu_HD_ho?-gs4=K84g8Oe=Nu+3{`_QhYS%1}XRPZKZzHJ}o~tyeF5s z%(#TS#)6)Yl&^Rl%6q|l<9Hlamv~TDbTN5Rf(i?QNi6C9_5}4GXAZIciAnqanAdZ7 zez{}V-@?+*Rr&YJ?H_%)W&X?Yq|E=slQRF)KY2-;BR>QzT+YQ0S|&PFRY>#w2-^Wj zj#kcE1_zVCzkH=-ZS~TpK&)mY(A%2`kG)##g^)TaJHkurC7~DL0T&VhugbZ1>Kg%#*+`R%+T?)y>dk_3`34S1cvMFnZS`r$?hKo0z zj|bc96XiKf;{Z;;uo**m^$ak;ll*)%o_|;E+}`i=|7!2rqnbFgxaY9wA=q^-;G-UJ zs-lQOGBcS;LKVs*6rzAAffVF@Vj!?dg#em@Zfym5R99EXQm_d4C>n)`i&lY(3-a)R zLI6P!U0iVi0YMOv$9~@k)+D=o+JE=-J2@xc+}!)U?%X?>?{R-jhO)%S+sCzvYrbgx zB2z}wfyS$s`sgynqe`AF*;j35hfiiMKF}2HLl(>_>TBVP%Urr2&ryXb{@}mn#kdu1;}Yir2UUCFSsS`AP&Pd`B4m77 z>Wz-bUaug5ReodO^|9s2hOIjrb8gj$Tg%f%%S%G%Tk#EoJeRf&n1tOeN2h5XiY=#xpUrV zRYuO(_D8k%%5U`@nH#X^n3pQZ+}ft;v*N<(-6+pwUi0Pf%3}uinR#;e=bIZsrZPPvsmyIh2W@(W=L80Z|?mU zyZ8UQ^;4$S`YD5@83UuuFU;5n`1k0i7jRKt>z`M*t_lb_;?}? z`A@hj4iu)0<(1!0HRcs;wJ5Xa=CV?P4F8zBz;^7>NX7AHLxEHN2i(YWmkxEbX5PM% zgNs1_Y3k5 zo#U4AhECr3x@p4m8YfLsmiV=N`r?ww`jm%@pW7`-O==&$>$Y*cGEQ)F^jTzo%{L|q zh?+Z!wk<0i*xK`wIsOx$IB(M(K8ZbAr{te@GrMYYURW)T@3cDGOmA@9lI&Skb*Mm4 zI6g1pNv^qXpP^p~>&@?$Z;$Z#*6bf%PMPk0uS*h^r04D}>N(XHWf_?7By#dro?4(s z`2FpIm14*&H7xDq z=m+;Fb|O#5^&E%P_i&yts7F_Z5j^Jb_+Idlm0VmRf3Sr~Jx}Tfa1Vmv`ER3t=OUo4DtWeA1m;8&EguSRrtIz~^T* zDjiD2rgNp{lL+Sh(>8}!TP!k){kiMXpOrB?OOo8yrWXwtyO<6P+L`Z9FZFMlN*FI_ zaa_*}Yw%aZO>OO~Ek~4zlLc9f9}ksChkx`E^Rn@a@xFazUS-jWHSK}5gNIudoZaht z*S9d<$v{0+qgubuEvcifPS!==qO9o6>-7npx;Xu;+2MKY?cE)%yyc~j-NpQ_&tpfj zznyoZwdX-qzgfU*YhP=l(ng~%(ntJjF1twH+=)58=VZ-RL;ZCV$zMh<+}<{~Y*_U7 z@Pu&L^vA(n!S+F(B0t-wWVW1;#?wb--71qwKiQ-taW%8wwlHW@+~T%vuQHz!GCytfbQkD=gTjBzWf|sAD}ZwNkg{@ zWr!agz&ImxFX1j3LZ?809cI2AXTDtl;IK0QYX-o*5K@>v6TBH-(p^ymE`S2CFjowL zGw(2mBXITv=9mZt2m`YOg2Ja8%#slG_idJiptDkJ1f3P*AXGFc$P4gyuvs}!7B(x0 zVhD8>k>bG-Y*rM+nx;0BQgi~r-^r2){!W&K;Ip-YIH%NH55>%E|oX|bZW%H$p+<+92CP*l*0gN?fYUspE9M*U}QT6%Yq}N zA_$W$0-)IN#SYZ#@r6)g9|{Yd0ec4E*Wof3L=qDj3Df|2HwW*Q#sFP;NQ3~D89*by zSI@2};SL&TIg18c@HQbNL4dCBKxSzG!3LpzLL@UZ&}0Hw5=`%C@B$1fOz+d!VBoZ9 zOsEJ=8cGmgptNXgLWd7$!0iT_d^iqQyfkS{HdL4e#fhLV)!Nn3y8jGRRUj`e4 zH-;u3o6xP7gR*t%;DE+x$)XH`rQKhY!DeZ<1;rSojx2_g+WkdwHmOq{6D4)ZBQQc+ zmvHE{#}p+AwhkZ3X6x{QFuyu{U;}_QAI884;7c^d4`b-+979>q7&ZAYU7ce%0dcl8 z`EWLL7@9OD2O6;^jlgttj**0p&M}e=|BPzNg7^s9V~?>J&<|C*B8+Igk`~Uy| literal 0 HcmV?d00001 diff --git a/test/image/image_types/test_insert_images.py b/test/image/image_types/test_insert_images.py index b9a47e992..54872c26e 100644 --- a/test/image/image_types/test_insert_images.py +++ b/test/image/image_types/test_insert_images.py @@ -2,7 +2,7 @@ import sys from pathlib import Path -from PIL import Image +from PIL import Image, ImageDraw, ImageFont import fpdf from test.conftest import assert_pdf_equal @@ -60,6 +60,18 @@ def test_insert_pillow(tmp_path): assert_pdf_equal(pdf, HERE / "image_types_insert_png.pdf", tmp_path) +def test_insert_pillow_issue_139(tmp_path): + pdf = fpdf.FPDF() + pdf.add_page() + font = ImageFont.truetype("arial.ttf", 40) + for y in range(5): + for x in range(4): + img = Image.new(mode="RGB", size=(100, 100), color=(60, 255, 10)) + ImageDraw.Draw(img).text((20, 20), f"{y}{x}", fill="black", font=font) + pdf.image(img, x=x * 50 + 5, y=y * 50 + 5, w=45) + assert_pdf_equal(pdf, HERE / "insert_pillow_issue_139.pdf", tmp_path) + + def test_insert_bytesio(tmp_path): pdf = fpdf.FPDF() pdf.add_page()