From 8c6427515672f1378de39ce5b618c12129ac681c Mon Sep 17 00:00:00 2001 From: Alexander Date: Mon, 21 Aug 2017 16:28:29 +0300 Subject: [PATCH 1/6] Load 16-bit RGB and RGBA TIFF image --- PIL/TiffImagePlugin.py | 11 ++++++ libImaging/Unpack.c | 82 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) diff --git a/PIL/TiffImagePlugin.py b/PIL/TiffImagePlugin.py index 333104966..f2edf137b 100644 --- a/PIL/TiffImagePlugin.py +++ b/PIL/TiffImagePlugin.py @@ -201,6 +201,17 @@ OPEN_INFO = { (II, 2, (1,), 1, (8, 8, 8, 8), (999,)): ("RGBA", "RGBA"), # Corel Draw 10 (MM, 2, (1,), 1, (8, 8, 8, 8), (999,)): ("RGBA", "RGBA"), # Corel Draw 10 + (II, 2, (1,), 1, (16, 16, 16), ()): ("RGB", "RGB;16L"), + (MM, 2, (1,), 1, (16, 16, 16), ()): ("RGB", "RGB;16B"), + (II, 2, (1,), 1, (16, 16, 16, 16), ()): ("RGBA", "RGBA;16L"), + (MM, 2, (1,), 1, (16, 16, 16, 16), ()): ("RGBA", "RGBA;16B"), + (II, 2, (1,), 1, (16, 16, 16, 16), (0,)): ("RGBX", "RGBX;16L"), + (MM, 2, (1,), 1, (16, 16, 16, 16), (0,)): ("RGBX", "RGBX;16B"), + (II, 2, (1,), 1, (16, 16, 16, 16), (1,)): ("RGBA", "RGBa;16L"), + (MM, 2, (1,), 1, (16, 16, 16, 16), (1,)): ("RGBA", "RGBa;16B"), + (II, 2, (1,), 1, (16, 16, 16, 16), (2,)): ("RGBA", "RGBA;16L"), + (MM, 2, (1,), 1, (16, 16, 16, 16), (2,)): ("RGBA", "RGBA;16B"), + (II, 3, (1,), 1, (1,), ()): ("P", "P;1"), (MM, 3, (1,), 1, (1,), ()): ("P", "P;1"), (II, 3, (1,), 2, (1,), ()): ("P", "P;1R"), diff --git a/libImaging/Unpack.c b/libImaging/Unpack.c index dfc8a4d7e..bdee4c472 100644 --- a/libImaging/Unpack.c +++ b/libImaging/Unpack.c @@ -479,6 +479,20 @@ ImagingUnpackRGB(UINT8* out, const UINT8* in, int pixels) } } +void +unpackRGB16L(UINT8* out, const UINT8* in, int pixels) +{ + int i; + /* 16-bit RGB triplets, little-endian order */ + for (i = 0; i < pixels; i++) { + out[R] = in[1]; + out[G] = in[3]; + out[B] = in[5]; + out[A] = 255; + out += 4; in += 6; + } +} + void unpackRGB16B(UINT8* out, const UINT8* in, int pixels) { @@ -723,6 +737,54 @@ unpackRGBALA16B(UINT8* out, const UINT8* in, int pixels) } } +static void +unpackRGBa16L(UINT8* out, const UINT8* in, int pixels) +{ + int i; + /* premultiplied 16-bit RGBA, little-endian */ + for (i = 0; i < pixels; i++) { + int a = in[7]; + if (!a) + out[R] = out[G] = out[B] = out[A] = 0; + else if (a == 255) { + out[R] = in[1]; + out[G] = in[3]; + out[B] = in[5]; + out[A] = a; + } else { + out[R] = CLIP(in[1] * 255 / a); + out[G] = CLIP(in[3] * 255 / a); + out[B] = CLIP(in[5] * 255 / a); + out[A] = a; + } + out += 4; in += 8; + } +} + +static void +unpackRGBa16B(UINT8* out, const UINT8* in, int pixels) +{ + int i; + /* premultiplied 16-bit RGBA, big-endian */ + for (i = 0; i < pixels; i++) { + int a = in[6]; + if (!a) + out[R] = out[G] = out[B] = out[A] = 0; + else if (a == 255) { + out[R] = in[0]; + out[G] = in[2]; + out[B] = in[4]; + out[A] = a; + } else { + out[R] = CLIP(in[0] * 255 / a); + out[G] = CLIP(in[2] * 255 / a); + out[B] = CLIP(in[4] * 255 / a); + out[A] = a; + } + out += 4; in += 8; + } +} + static void unpackRGBa(UINT8* out, const UINT8* in, int pixels) { @@ -800,6 +862,20 @@ unpackRGBAL(UINT8* out, const UINT8* in, int pixels) } } +void +unpackRGBA16L(UINT8* out, const UINT8* in, int pixels) +{ + int i; + /* 16-bit RGBA, little-endian order */ + for (i = 0; i < pixels; i++) { + out[R] = in[1]; + out[G] = in[3]; + out[B] = in[5]; + out[A] = in[7]; + out += 4; in += 8; + } +} + void unpackRGBA16B(UINT8* out, const UINT8* in, int pixels) { @@ -1207,6 +1283,7 @@ static struct { {"RGB", "RGB", 24, ImagingUnpackRGB}, {"RGB", "RGB;L", 24, unpackRGBL}, {"RGB", "RGB;R", 24, unpackRGBR}, + {"RGB", "RGB;16L", 48, unpackRGB16L}, {"RGB", "RGB;16B", 48, unpackRGB16B}, {"RGB", "BGR", 24, ImagingUnpackBGR}, {"RGB", "RGB;15", 16, ImagingUnpackRGB15}, @@ -1229,6 +1306,8 @@ static struct { {"RGBA", "LA", 16, unpackRGBALA}, {"RGBA", "LA;16B", 32, unpackRGBALA16B}, {"RGBA", "RGBA", 32, copy4}, + {"RGBA", "RGBa;16L", 64, unpackRGBa16L}, + {"RGBA", "RGBa;16B", 64, unpackRGBa16B}, {"RGBA", "RGBa", 32, unpackRGBa}, {"RGBA", "BGRa", 32, unpackBGRa}, {"RGBA", "RGBA;I", 32, unpackRGBAI}, @@ -1236,6 +1315,7 @@ static struct { {"RGBA", "RGBA;15", 16, ImagingUnpackRGBA15}, {"RGBA", "BGRA;15", 16, ImagingUnpackBGRA15}, {"RGBA", "RGBA;4B", 16, ImagingUnpackRGBA4B}, + {"RGBA", "RGBA;16L", 64, unpackRGBA16L}, {"RGBA", "RGBA;16B", 64, unpackRGBA16B}, {"RGBA", "BGRA", 32, unpackBGRA}, {"RGBA", "ARGB", 32, unpackARGB}, @@ -1262,6 +1342,8 @@ static struct { {"RGBX", "RGB;4B", 16, ImagingUnpackRGB4B}, {"RGBX", "BGR;5", 16, ImagingUnpackBGR15}, /* compat */ {"RGBX", "RGBX", 32, copy4}, + {"RGBX", "RGBX;16L", 64, unpackRGBA16L}, + {"RGBX", "RGBX;16B", 64, unpackRGBA16B}, {"RGBX", "RGBX;L", 32, unpackRGBAL}, {"RGBX", "BGRX", 32, ImagingUnpackBGRX}, {"RGBX", "XRGB", 24, ImagingUnpackXRGB}, From 64225921966fb8bd0e02fab09e3f6b04a0df35c1 Mon Sep 17 00:00:00 2001 From: Alexander Date: Mon, 21 Aug 2017 17:09:35 +0300 Subject: [PATCH 2/6] Support invalid TIFF headers --- PIL/TiffImagePlugin.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/PIL/TiffImagePlugin.py b/PIL/TiffImagePlugin.py index f2edf137b..04459748b 100644 --- a/PIL/TiffImagePlugin.py +++ b/PIL/TiffImagePlugin.py @@ -241,7 +241,12 @@ OPEN_INFO = { (MM, 8, (1,), 1, (8, 8, 8), ()): ("LAB", "LAB"), } -PREFIXES = [b"MM\000\052", b"II\052\000", b"II\xBC\000"] +PREFIXES = [ + b"MM\x00\x2A", # Valid TIFF header with big-endian byte order + b"II\x2A\x00", # Valid TIFF header with little-endian byte order + b"MM\x2A\x00", # Invalid TIFF header, probably big-endian + b"II\x00\x2A", # Invalid TIFF header, probably little-endian +] def _accept(prefix): From 846f986bc8ecb8347b8cab69c1283a2655db5db4 Mon Sep 17 00:00:00 2001 From: Alexander Date: Mon, 21 Aug 2017 17:10:05 +0300 Subject: [PATCH 3/6] Tests for 16bit tiff --- Tests/images/tiff_16bit_RGBa.tiff | Bin 0 -> 42224 bytes Tests/test_file_tiff.py | 8 ++++++++ 2 files changed, 8 insertions(+) create mode 100644 Tests/images/tiff_16bit_RGBa.tiff diff --git a/Tests/images/tiff_16bit_RGBa.tiff b/Tests/images/tiff_16bit_RGBa.tiff new file mode 100644 index 0000000000000000000000000000000000000000..0fa209c5cb1fd03603a44fc5d4c0dfeb997e2c16 GIT binary patch literal 42224 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
  • k@N+XE@S(Zs@d__ZIgM`Z`A?Ig&xIZ@>Q>vKF#Ma_go6Vn~#9 zdUdE{P~m>1)Gsw8;1P{URQzW8$k0z3(6K? z5?~DDUifYzIcJ=fABlaZ_sHiQJBqUU_I{P+y5;_~V0UQXXItw^@6X=DgXBUIzBT3N z;^bIVO*&FJdz$wZ6l_j3-U{w0Z0;2bP5W1dc6jGjc)YcH`$pAF=KtmB-2=Z~!aaiE98A%{af;9vS#l3E# zRIygTeDScCIF_;Ah9&9=k$4UiIUz!rY}aOruESp8r2#TeExHKzqDv}OAUZD)viN$I zqQyx((JKtONIVFwgE5fu;r++4ikNsigCCZsqui`uh&PT$FNj=M@C5-USI=fSFZqsY zX#uyhdO8G9DT&bu^RiI6YMcbFrL~hobCGd9xEj^Yq}CzJcyMP_Uqtl^mgXl^r!S8N z-T*}llWOx0fyID~s@30HS_yCIDoM810MI@`0&kEkKVAzQ4+Fm)&VLCvl=W1fVwl8v zbL^mUD?qG&1PZlnH$05hvd$i2n_nT*svQe&*_6zVXgY4dtq=znd-Beas_86Qf@C%qjR8~rkx;0$=MuQaXfY`Q92WOX;|KQNy>b~1QYqj8yBp7 z1tOQ6^f-McZRzEkjSJJY8vbP7r8Sfm36*BWKRq6ESAfyW#I+xXq{JIci?4wEVy)rj zQlt8lU;O8v7@_oo2OXKA>*+j9S69t8~=CqUch1`|E#7IIxlQ z8@S#dIjvwX2EIQD8KE8xZzqElxkNXPm8N)T9Lz01&P^zp=~exU@rFwu`mTc}Jw_wn zu;lcp4ci;G!ZW`uM*ZIr^EsV0`Xj526)l*zWIp~$u+c=R1F0e-^oB>h!SFtG((fE`0CPabbV^WMOFXqT%`m+2dot?Ou&& zF>7N^ZD*j3RQ5N*p4~58b$>vY*XBgVHkz(^$LArx@4O%XkN*u)ef6PG*GGElO8v57 zJ~wDu!BO3BbEmHtkoR_6x+?yGA%8UF%sXWb4J`sndgm+tbGfpym{~J+Yw(iHy_+b` zAAhop$#{5>Eq^#Ox>;U)nVnnnca|J51(9oP;b=nvuhhuEos>pz(@h!U-f1`r?WxOG zm@t4*~Mqe;t*0Z`P+%<0rEv_zDo^H+I zzg}9<(}8x{W^CKY2+z z&uu{Et)HrV1(>TsZRC4MW=Sf;J?3)aFVuJoG~c*^x>i78l+tyy(|i56edua?Tr{cd zX8c>vP+CzBQ8^BHIRXHA;r^%B!g(Hw6ZJcPgM+zzQXqW?V7y3;8k7)A;GX!2m zpnfArNRvdNn8RZOSl%M2!owgrW{NRk&9X;zNzaf||Z*Pl6s&TC1bGcQCE7{9@EH$Ko_LAjhVScPI2CWeEZMAB36Z|3K)= zLJDb1d4A_{rwyvYOmIznRr18Brhq|r_hw-v(OE5VZ%-88tRa-6TbJ6zhby1f6rC7@22+5c~;dWHguec`~5wBBzVgFGL(Gnnj7 zen)yZo{+xg2!E;ZqrtpVfHOe}z72gQRL@P`E*nZcjI z%xU_1#ZyesW0X`UyyYsE9VRlNhspU;YM$iCM?WISsS*8h6a zqjGExR9T4!1=(sUTTY~lz{baMF9rHapzuIppb!ieLSTvXKOsf8HfIaio~K}9ffU~g zeJicbVm5`@f&zB97pguO-2=t>7jg4$z##daif77!+fMM-@ZKYYqe)8DO0m2mv65*1 zmlQ2O5ibo3HrZV$efXRt8liWoBs`jM6foI*d5Mu4Eko76Au)-#_a)?*jjR~(Z%hoW z#63)4rJuD@vXPX$L{Rf8a#)eI{nCf8qw41g4wA{=B3BvWaa4e{Tgm4FGmzD4_maH{ z9I=5((Eu7&;;LTS`8y=Kkehc+89!Yid;KIV|3fRzwM*)AF`DE_pc1h9&%o0SoE0zL zAI889a&{qp!Knuka5N+9f>SY87HKd*O85T<#1{i(!19>qjWqdk`=m?XAzwY3c`|Iu zqFq0LORqgY#D)Y)PLbe!fF~xvy%sr36@dc-6q)=luJ|XAcuvlSQM?8}Yms*v7iSp{ zo+=SKz7r^Tdg(!~9F0{Ij?wsov;JdfU@Q>l0@vev7@{c=A(D2;xzaV`7{CoHE3>- z82lRe8&CQun*U!E%>lkbJSM0bm<-Tt5a>7*;8=x;yk2!^P#ZRCpqFF#ed(yb|QZuHmGI2915`EuX52q8;EWJsNUq#&<+kLto(Z6vtEvfvcdbs zC=o#M2T}B)!~eJekQE`@5f>G9kr*kamXAY$1wfpM#3zmna-n}P$X|aXt0h&AjC1tz zDU!bpx_>4)D&Jn^ghD>pmzC0a>_Bd$YmPMfBn+&CR>tD02*$0U5tH0BU&<^zYR!Q= z7fPd(A%3n8Ewp6IdOa4*9x)$2D2?JWekM>KI~FJlB0NIY2g_GViIvc}0I8+Nvc=GE zinwwJ%^I1rLeFwET2>G!k&I?JrteKYDrHFMnu9V`$Fo(D0jr$IMViOu^aMCMPI49% z2J9hFNO5NLk0;PbHBy^!_qcF0uh(bwg|ig`vGG;sfJ;Ke7pn z(X1HLd@81UrJ&IPNb&uiU2SP67o%nn-2MuT*R(@VKWcU#O*u-5tz?iQV z4KTs?DUcNw1Xv<1oj2+Xo>I=6D;afCjO`uTi$)#1zqDBH4ssDQ%d*vLaUoH;y{8&qOvv-5#choZSTQI3qU z05C!D=>Zp`I5rzNmU1zqgMscl3uZO9^CQ6Low{buL6w%RWN(%tg#SfeGjh*Do(Z`w zn!%KSho+)<>}vz=DȇpsR}Qc))2`8OJDL`nmSZ8o|z2yljh(l^zo(5_v*d?uGRXw|^kn%PPbh(0HuC`R#}Xx~Y>s|+ctQ0yTT-Em|lUc!GH zpD+S(73zEi4v$B8ymIU>)T954dlqA@v-4c}z1CcMLsUS{NVvsS|g>Z;iL{??*?gPmn78N`yZ9iM3BX9 zE&h16s5f9Dt@XQdaX)pj?j5RZ! z!E7z#x6^zc)AgL3sDgt#B-ebWqe9BsaGe-@6F-`kL!|+_cYLgrYd#{wZjYR$!dWtM z^Px{n9}saO@`tl*fMU}m_1hOw-Cf}9cs9*on43go_<@UL$ps)RwR>4${0~?^pJUk( zX2G+6hYI`Bsk!98UXOU0$SBqO-X8$kh5Y%*Gj$bM2K*h!v-G)J30s^YG{fNVOEAHJ z#dqCl&S9N*DyF4PPo=aG9L;_I#KWFd?J<@*@f~^tga%pi<19**fhT#%TK_P-;e9M+)={$1DRC;@5}icRLchHzXT5jCM#zoDXfT*gY)0}>EX z`Z1u?Yf8G%$ZRyQOyf0@qdDQYmJv=!+|NINzulWQVU&OMXsgz~6J<96b!?y4Ol6GJ zl7-rM9^UPO+Y9>A`A{^=_<88NB)QCzapisQtCC=b)`wA=+!wdVPBWFtk<-7GJToQ7 zlbHJ-GtvVcfj;+j$+;AAJ5g%AK5A)rU_BkUDfxV5o?KZ?Nn$m0>_8(+4!8}>pq^H= zR3eRHW9|zK&3%e~;R>0?890vSSbB&hf0{{nY1v6j(GlRU0%8Xeiw|Nh-@`C&25kP< z!~P|}yY|lVt2o0W1^$jam@-)f-2U7_IvArOep+_@8+n!?cMb5Y9JlWe^p*o}s@w7Y z2)qv)2Q?|xiTuu3Rzp2pg#r@?eB^KNn*CiV!Ew}B`+85#BR&rFl%e#`@t1<)bw^yr zU?7LcXvu$!lN>WZIsgV{nFk9bpNUN6faFAJXesoxqLE#Bt_t8UAn>zy?{pbyVP+@v zS@Q-bpuusF=jpHJ$c~3$>aEF z?aq@2a+rB**=Szal_THZDyb~w=b%*C)2>oEp7#R=!~^BM8B5TZ6Y6?G9<)lB{^wc> zzsD!}^-|Pmb(YiFBIe-LxW6JYSVV~C;LbidHW%V_fpyAe*TW|>COUb97|=*@G^SAkC*?aG#qX_`p?~0 zJ}!NMZhKX;`?dbki(xUGw_7_O4hW0*XH@NCctPm$p8?u^@C|jX^JS0rCP4{nM}LJ3 z!^9PJulSo$qnUUc90Wst{kz0iu-TbP8Lkq01iMsf;^yJXqu6+(bQz{L3y*v?_+2WXV+Z*7p>zn}Bpn^IHIbNP~SaB27GZmM3TH+TdwDqbguqRR1cZ~J+ zdx(1;`Tb0sNFzF=xNWqydsv~4s;(cYL%4%XNf~E^d>(g@@h01Jg|?s3@Y*7wE5Wj3 za0mGiAD_vUeO@ja_VR;*CVU2eSrH+N>592CG6l!`jh*_UF$;j59jl<4;!w5)2*C3;=_k2aJ;IQPc2!STZxW59>Id0<+)u*+0?tNT;-?4CI|r0d*e?8=6gg!#<0mBvW+nYod*UiVVt zwd~Oi%!?k+j@Xyk$b;e2jz+(!GJC`tA*{`d4|ipsDP}^hwq2%h_OvE)-Pi6hUCmx* zdV^NaR@0Z+RKs56+&tS{nLWRYRd{bM6))2&imfl!+HhTYTLB!N%hJ5E}&{tDOI{Q;bN;#Fcv`~kE$uvLgpS*}`v-Q&my zZu!vsdM)iY&rqFD%v3xJ(c#T7wD`}&nf)}A(7SRS1y-@P6#2h@LcpC3Q6WQT?lCxf zWy{!?J)f$Zs){TG%LyswCP^!<#p-h?qb(NxD4!IzGa(%NWI$1#Q2!u`MfM7b3s4!M z_O4yQT)S5W$NbDDje5ze9!<&6cSgoo+8}t!-3r1%&yz$@et?3XviqFo8Ak@nNl_>R ziu`mFeu)Zv_&EDM_in&sQ)?%jOSMb_(JWkZcqU=`h!UbYWA)bteag-NchDoQDu7N4 zHE+c}Qq3A@esY5)K7qqEExa^(E*WsqggsX`wUt$sqLRsfTPjVG$s69BoJ}`%2b5Zk z8h_~_v0)|}wUNEVHJH4`Frzk2fmdImI9pKa$Q2}Bf!#Pz9=<}dMqR$(Y`s|7PR(MEXsI-_SS92zJl6fu7izlwy$Kat%h z4v^(vyVZfyYlV^N1YZ2%Gc~O2#0};KetB$;A(L=O$=5!RjenuLF;lf8WM)!R%;;!N zy|TYbN*$rs%y@}{gud5X#r7orC?m-{{8NexEf%to#3928%yn~jMOsuTbB>E;3+?-wI z{PLjqmiC>OKh`#iXq9)&0d(rjA8=%_=ue8{k zk3Mzr>bKxp&r-N1K=h`V>i0+V$If5_@R9e)x!Bl@4Nb?f2NqiefaG`sjap%EiZapP zv4_qafwU=1fP3wz>Eaq8S^z#52t<_dA1Du{8)nQc$)xfsby^^!Q3kMOOuqJ_rlh zKf-I@QN5O#9L?t%GnJ2=_B7iCG!+W37Rda5icq!8$SuGC(V2B*#VU+L;Hwf$ktp(shdpD2(0ejqUos&(8~=_O)kiO^xlG?%_Gja6nc;vl8A zbc&sJ&}QNra>C0<(MG822_d^otjQBAs24gO5^HRNgHS8s-3Y;d4~GX9-8~MIw;@^! zrG^!P#U>azV5aCRuxTdbz4*$2HOwF4Gs__cKwzsBi4#_iNNWWy%iy{L_pQVU!cbFE4ZA5@vW6 z!~1tnXzNwm?O%SRK|_pKPj#K$!=EeU{kC^Mdx}>Iz$QCt%XJVsgfs9hlzLX;FXR48 zvC^%JRKjJzT!-4j@+gL z*BJ>9B=(F|F6W6`fY3%nLpG&5C(~*;y^Bo(+|Hv>TOa5vRuQReF8iMmPOWE^D@@lL zmdsBOVaH(y=xQ6U*#3b5)~-)7!-^Q9Dp@ErCjjtFVU4`DCOSNup5uh)FO z3k&eh2zsvWJg!zaMgOKUO5!|j(;!Ih`TEfooob*i-ZCJJ#~I9q+jzs*iU#YNPe}1B zJY*#6e#EpZM*56r{y9mo74gRWUl#o9gTId%9wq;}*_1I8cWNkLhna3z&dpVtIkAlE zTHS&L*gRhZEbQ-BSOngPUzgfMNv#C$!n3XUN*f_od|xhPF>}1&ieX}`_|9oethOm0 z8dYM^WAWKHXn34Z?_iN<`|0&0zQKTxKcIL?wdT3Z#SY}nL$$PM(^q~^D+H0uZ(hgH zXfx4u9Co=Ei|ty`VMnFf7pf>=Av150$>s+|QLA=h0@bc&!= z>kHQ5m$*ep48ec#kmxukjzU%Silx>}Da1}+-DE~AUPpmO?Qp*0WH15lN>?hc)KixLHFf_y~SVir5L_6I~^hm~KFGf~?mY%dd* zXw{keNF}2TQsoMftXd;%rZbJXs)JtN!m5LG*B2DrzD|gllx;@dORZn4g%`N4TZ|-b z5Y81UM@-^2dsRrwcXGo!*mD0y;cOl{$SPaF7iYE5#|d{BaPd+8bdI{m1Xi%jRc-%i z>>XsJ^N&s1t=)3eSan-3wdkY^8uZClUL`Y^b>eZ%l;ntS=(}!)#+h@v`t->mo#5NX zU$yYB8PF-XVX{tj>6)f#!O`tJM!PTs`HXSg60Pu)hHvHIsvUeEiTuU9n73gYgUpl^ zA^U9szPnpJO-L7ZR#lOF3mmT5g%_8)qyV(C^Dna(>a@$I?dEso@LPbmo?$=IHu+fe z5uLofhrdFrdkkO|`Q^8|rn4N_PiH10{w%F*<}z&sLuOr5Ba1@R@Ku>tOVwzpvZ6%R zYWVXEeg>)s%P|e9cH704{Gkr0thWd)w%aqc=rq&Cj_+>Msz(_$Kq;HYDi`!<6Om~( z5u3Eh+0#L5KCvsUY|BGS3`2^Jzr_w;q?4J?&>;Eq^|TtEjILOfUAgMALTL$^v1#wG z#-i}r^S_*m)dmK;P1KiS?cz5zI>o@uEtshAT3|Q~PdYCy0mEsaXz#*v5Ud4?cz0Na z(2YmgQt4bGNW1DR?N* zxklKe;hU|fE_VlESC>F>S|QWPNv#ZAMu{J+$IDsRT!cD_$aZb{Jq|uw%Y?Mat(V1Z z^dH?O^{6olHVGGs(UCHB8~w#)UDtL^e;?cB+{|Ch<&QvdbN&|}>ALWv;5s|J&nkSa z?Z3$l*Kg(DDg#%DOuTrKLV`E!!s%kxtV^bK(owB=ej9($qMkDfar2jxx#5r4jJUqH znUma%0%-BupYeVJ--e?C^t;`3W+vJ6JNJv*nBi7(cnD`30(>8*uF@&Z;Oh~y=quto ztn6u8aZsR*$k?86l#=})5t&oFXST6TDJJQBk`Fh(edhxan{Gj1KVuwqg;@@O4 zvOOcRlXsLM*_c_ajheMxZ`P~rr9%~3be;uws9_iX>u$FE0wr3@m5WBO&5~(jx@)xk z9HXqKBzcT-Ay-^ms0gJMZCZ4TL7kL1XAkONr1zex*rffjEoXaRoN~D^v)zC^c@9OV zHn5ovy6fO)=rx_N-GI%*Hd>|-Zwu##{6P5g?Mwr|Ml5YZZ61$8U!2rC= zZufr+h6x}&6=|v*|JC$fT(^Qx9iQ6>0h_A5K>7CW@P8l4Xw7405;(!ae*pS_-B)=l zZ|?Mc@EIsH0QLAZr8ZZz;9}Z*@l+9?A52k(O*l5ov;gcc{~QeQIP6+wktuL`SeEw=%yMXvBmz6RAHv3K(H~_Ke;8;79v~j zKkiwDTJzE3=cR9mVI%DS&LfIOW`geVoSe6|5?U zohyX3C8*VcYD@24VTBA z{~8UVWY;ZGz~q3KtF#tJaA{k?BmrH1y;}%rGk#5G8TUm!$14n`9##8V!B?QVdD8P= z`VU5nF19qq)U_X>3ichor+C#L`SF()HhcGvf|{{yM1=spjg39d zz0fqe`Fm%%vvr`U+nLRj+20v6$$j%jKjuo$byZ9SpycB94Z^Sfhj_j;di{Lj{g0VB zWtVTvkKHfg{!(@@>;|J7^-qnfX1-Y5wAb)&XZ3s4hu??h=f^2*r0MaG3+Cio=l&85 zn5=IbpS}8ZOxkFFq*!0%KvWgyG*{K)!pXyE$kLtnE z7qdeF?Kyv6z2)=l2bz8B2cMao&u8B^?URO1t;ui6eztD^u=VovV<=m?0)39S)nt>x zFF>ECxQBw>INBirK}!Tfe8pNw$Fy_E7lg_V$YiwhFtk|Zh7}2|4?~NN9BHgmZ=}lA z8d9p__4(9XRPz*UGU{unb*Q#YYVqpbRIgCiA+;*{)uE)|d;qRh3WNyQ4BXtLA~dYsxQ=(@!N=-sc4 z1K$ch2D^avDDQKWmqPzhot@uktI)&1YF*jiL7$%?hUy-a)c8RMQ<-(HmTo99Khp~8 z%cQ%?Q75w|R=-^a=;@0llvv9|Zu^qIAkVn#XKCI=?FFIhzP8O;9Fdt$H(MJPX~&^0 z<)J&N+NQp>U=H@?_|ax4uAEg{@^ql%gg? zVcKTR?bn>gveK_k+06aUT@ww2CQ>91^P>|_!TUR`RDY2R%St(}*wVjz+oT}aZ%GcF zq1U)4>+t<$O+(}9HT6?yu$xQzN2so-EN47yD{m=lske?xd_!HIl+WJw6iB1ZU})q) zMyf0!FS!>q$Cqf3vn==W3X3Xqa9#Qtd7iWRSN)%GXU?7qn|{g*3iC?uTE_Kyj*Pj= z{k*#0{t%g=a*$~$+uvE(i`pCeMrP=RxD%>JmNyN(Mxmp6`SvGz=(p4?azP4b3uF6 z_yQwwe+*sfHnc>?YpQOQN#|~Ah~>YfyRx}DwJ!Id1D8i@t0m**$D5r|_Vj*iazCFJ zj<#urjVqo@9VwB)%WPA_x8d?q!~D_lmibp4hQy|^NynFs{VfKv=W8ut`j__1Xh~G< zoD*|Ak|%-3W%YKjdFUaQs5I$r)mY}I=Z$H4&JbB#V{78pkf$ zc3DH0r)tPMV{^qLlNV_nD zDjTh=v){h*hyGTT}>Xr+4ysCQvyCEdJsQ zP*y@ALo!nxxGAqS2-bNosWlUTrvqG_v;_KnMAFOH+Y-71J368I%oUQ{P46`ta+hX` zaH75d^tdkp?2D2EetIAMjNje$eh~W@Rd~r(;64pY#LH}#MyQX9`Hz#MLXuqf4 zAq4LEh17H@v5KPjg*I?=p>(*7ygubHef5eC_nf&;)v?-4U>i)DN1*Ft>bBi{=;xk$ zl4pcG-IFGJE^jw=v zv|3)IdKU_#>x+dfO{`ff2fNO3@1P1q7Cmk z7TaL`O3H6p*c`BGn$zWnDmIzIYGdJY-t2d)=gkvTtLz~jYzDjOxz1cboX=$( zRUGn-$xrPmZ4%xjrS{9g)MU+#RI!P^QmJu@W16_(x_;wsd~E}Ft@=skcF&*WuBxu4 z#Q)LIX~_M*;;BvUMiN!NAMA-}B2HVu`t6peT0afNKCV|j-6i+WJKjqHZFgGzxqHbI<0Bw&4Hw`3y;@yq3AEkOp6Yn zZ(&p4c4AC|ViH>NeCAh>bQ5yLrI145KX~ZstI$RDiX<=(B93}{)c>;j1aj|2 z0RCM_crY$v_W~>7cU|5Gtq=upBIv1KIy*p=1@0w9yqS)12usm=jzh;hgq{TMh5H8c zf;<;VQ@uz2jgW?M(bP_iM(qZ1W@7mZl6x6AnR^Hb(DNXQuL0h?XVL`_>jX^4ime4G zp$%r}-uGUGzDLo(qez_cY^*To*O5-9_`O#nBRU#?s0EmddIAhSiF|YHo+9MXGl&I; zhotBlG^j_S|D>8vr?nC6Tx?1~2QP6=5@1S%LJX{6IcVg=G>kndxlLfS;yJa5a2WBM z4E1E7_aT(&Kyl3}AwMMK$Q}(SAAz0)C}TkJ+EatJlj&(7weCuklsp^2=(u{-1kq&3 z&3QghOgQm_KZor4=l@Rujt7IeWj{O*MI#su;P9c8XqLRK3Wfy-iim(En382-3(Pjc z#2U_5Ek&y$zA+%sCr9TKz6FGHDK}CX@>R&*GAeyU=KRu#ASIS*e8qTT3OP%de@4PB z7-1_KUB7pvlu)pGEhlI_E%Q3b=LFeBT3;3Evqh#%?Hd?}mIDc&W=6*KCQ6_`pB=d@ z`&y*IM(CpV`6?KvHOQMOE-8;lj@A1{97MV#{N{@N4xYlZO@BT!@{TkzQS$mx zrcFP<1EoNY=aQZeq=DSIik{AXBt=b-8wb>-2Yf}5fjrup3)N3vNLk@f9t?aY`PYN2 z6AUgfIEtXdM6IXuu`*u_B|~uJ zF?qB`Hm)=|TtVOXpr@QZTp+ugl4_7d(lk(s)Dj95$O}pdw?RrRl>E&{_%YCD9~xP8 zM07+3D+tlXbkz{<0+?PU1%77Ej1Bur!>TpZeTMKoBxT1)v2|~Ym6TWt2MT-R-Wr!3 zwC6;c8UcC|xwl}r`6#aeUYf)c)%RLKtQ>h30@sG4nBVo%NTi6x9U$Hgyi<@cJHO&p zBtjrOdQ8+ZX=XxdcfO(x;d7-zNy}G*#0(740k^M!*U3W+W{U~D(g)|GZTBMYZ2~HG z$oY}Cv>>Ao4zQ5~(;)`H&;uZ_0f==^i~3-UjaV6?8pDM?fG{Kb$kQ1EaB{tXg(qZ? z$p_JG$UoMK^Qmr3F|y?0J}^2S#C<5RE}qFn*ib&m5hsp7uo?|K38Kr3L}L)IM307w z{zl>^fkYKJ{2W9k%B2TRO>eSaGLA)qi$MG#o7aRR46IR0HN7M`NHDY=4Ak2`{sl-E zqf3{t45=3xMuM zbUqH!bSbb&ZVTlyfJ=8ES|%BHqQS>YQ6Uj9(29mG|Er`}Bp#~=vD~HzV7_ovC%^uG z(%^W>X+=ZjWq~pxP{a_m0>Z-u&mlmOjTAHfy6s%%OpEa&!h9X_I{G`UV`7v7|R^3HvX~ z@s%*U4*FK?b2zAIDe2BXgZu<&hvGwEv~}Nwf59ONdIjCc*igC{W6jdgRY`qZ@-Br& zt=?y6)PmkX9^-vqN=%gaE~IwqM@l1!{QbxNt2b-IFr4Jdk(_^&5_=%-T%|e>3>1ej zNSDr`2R=LKG6$*BgA-<9v>m042A`GUjBHv@$L>k~ry!UG)NuyNUS^@vrFzDWZy!F1!uk}OCEIu z10|v7N+Q0x-V2vZjwaSOi9lm|4;KVSyNS`o1V6(xFrJ+~77jgeIOD*sBzB-!?y4YE zGvR&=rb~{9pJ)`)@=D?MgCiOFiiQ$3Qd$$lz3(H=+8n%Buh>tV7 zG$G9?%Cy(mX>rPO*H zbJA6R3bQ*Uv0|UE3MER&tVOoIA;q7N_-RO8xNoGCO5{fZM#^|qN_RoeE|l%W%Q-ku z5W4fk{sDW?S0Im?gVqluWf?S1L~s6;&6ZG33yW|09Q~s-SR^?EC1(LPn%HU_x zP&0HsiADh4yL&k^;B%yrFQhGBgh%y^dhZ}6WwC*8@Eh5I?>1$jqvVjo8stn!$stF+ zmwZ41b~Ly)cc7?O%nO5D!uyl#CuL8*Z2eix;rJp832$BupI8(;Z7uI@(gv}k)LJC% z3NqOll&hMtmXgcOAuuh7edF%ACSNl-G+9!sh#9t!*BSKwOpbaFXQqVWHNa6GS~`(5 z+Ji~~HK~eld8E{MxNa(y9mhCv60ryl*Ac%BZb}orm`8TbmIjw}0zpde#G}VsuBylg z&tgAH<1ggcG#P7yhiby{MJS$A2N-f^D~PWLfdU}%7DdZs*xoe5Ug`h|2++g8=Q+mf zSO*tMu;7zxtg0d0EJeJ-syM^Ik@9=e&6SvduT6D;U(JPZJ;?kFB$lG+{NqY4Oz5Iu zcg5EQHRK(Xv{zN)SUpbNXRB`ESbc@?9#xgG){yUtzwuU;Sl=SMQ!lqy_7xo`KhLP` zRf}+}zAurEI(Fh%y~guH#@T~o^<&e4uBdCf_Sk7-X6=QUl{)(Bm{H$PvsP)JK3(lR zxyzY<{`y{Z=99WV%bw(f%m`KIeg}#}CiT%pH5+ zR?(_z)68oVoBtnJwaz$5+;zOh<0(kzV`RU7(8q{;n-0@=Z@O4HvD!fn``-FE)YX&8 zeHt^7B}8)LX5*1HR?pi_}f3VqvZFzH5F#g%w)^`dcL7b{*n}(+rU?%e1 zBK95Qsu`GxJl)W{!PB_`Gm*!;BcCfB%VPlSe}HLLn**4MJgSW#u2qP2Wp~UB^Uj&$ zVv+2Q9Hwe?nFceF{&93mqFFG0nO)yV&Gk&qIb50D;t3aY`RDZxXNL;js+wVaB$9Er zcLvWD*(XMBd)l`Ild$xu$T_~PnN&WmSQMe$Ei^f=sVXqEvPtBb1HF8_j=6fjW$U4}{wu}N){X8thu8V;jMJ?zZ+q$& z^EXDv zrcvu6Qo5yu&Q5>}Nb)Ms5wT@h|397_KB+zUtyU8@mReA!HJ0*}HQ@weCfz6ZC%CIt zYjNfF0!D3}h14f1m7@lzen+WI6G$baJ(wx2+B;B6DV-b8Ft?~l_=3FV)#~IveK6|C z&-m*tYWGAa{GAMD@F1%|J6Et<#`=qbe$OnFDXtZ7&LR%ivCPItF`$|sLJi~h#ix~I z1|b0}S0`Wp#+un}u{yU;fM^@lB-{voxJmzRY%F)Ky=*VqWJ@|{OcAp_Qt)Yny=PeY zLXkG()*kQ(8YS(QQRQZtFK5SymV%5r3u3&d2JSez0)8j9C{Fr4*G7onb;}<%?rIk9v1fb*q2O&Z$~5N+H)lT|>#mWU1gZ1` zS!rci&SK#zOHrcJuBMJQms4ZqejhWhqKH-Y<6Yi0LF3m`ux6vIuK%O1A>j*ZQ9&R(M8s|VEw2w{7i za35snrV8Mdl==ElBdxr-XdD>O6Z~sTztlh{LioP*S*AWPVZZ;GsmYOZi{aYEA*I03 zq>btNomEk=W41+I#Y&EcNhH5`b!aDd+Fo?Lm<)s@1`k7J4CAjjPM7u%&;$smr`rXll)>*o_ZwcXk}2ke4TP@tGsxCg>$FUpI&3Ndt^LnvYrX&e{NZ`RJ11w$cTSR-llOZ+ z>bU8PVQyU8(ulzgRAVwN>HK{AStQ@mCvjY8-Jxx=^*Le(^Bv;u1gxm696q;biKLfV zOc=tyPgpHU_*JEBE$`z^Gh6GK>@Y|T;ieHk;dH8Od8(K9f({Q6ojn@D zJ&*bOD{!2bAYEd~ilcf@A-R^`m89VZIV}EMW20dWNpenje}tOgBPb-c?!&c3ScLha zc&R616*;t|8vQ2)db@E&W=kkLg%-TAK0<%nC?LF(=7Bgt-Sm<$O7 zOUF^y6LF^$>9Pkli6zBD8JZzompoZTUr)#Q_WHQYpT)U?&Vt|4^s^Hs>^Xu`)o2SP zlvlE^_Cu#WVwu`WeBrv=vR%^xR7Vp%sH4a~ZvRTicM=?0qK!y(h!cF}O!`u^dL`+Q zxJkMN{VRYTPVe$b25mIt*N{X`vIw412k~)jaOkdhOP~k(vh)`0eoe%nFcnKKhO*uJ zr-JKLqa~VLW~}^;UjH&&iX7>$c8ln~$IF4#>_GOGpkTf;z$OV|bx_Ifew5U7SPZfW z%g{{lk&0>aF6xN3_wx;Qwas^)`<2`2kHOOtD zQX3|=t;`g@AW;NowncYnvy3|`v89U*{#l6g!Bu$)S#FmOpci5{g-kqgKxP)i7OlwC zIFGM~T&9?(6^Ylx>~@g}snHx;uyvEjQbT}L=AGT>VS;nozgy0UCiX~3qu4qqvYaPq zuUxKP!Dr58_vdj{N-7N#Vsu-x#APW8j#dE#$IgOp+W#Y7V!E*m7Jz z&#tq@T#Am4Qgg;^+W{%)l9;>2{6`D9Rz0;wMm4+pf1yD9JkTOBuPNhBInnJ}zFgsd z&5_zH=N?O8c7;{t1%7a*_uv6CRmdF_M?f2(cj{%8h9;>syvokjYH{EzwMU{LTmuBe zpCD>jy_DCfDK99_gbV`>ry+N45u0}g5JYd>0Nteo?XohjIyTK2MXqO)z|R<@kyc_K zVjQ}F24F)J%u`56@HcorT8HU^k00aNl4GPV81g%Pcgp}z0xRanX_0K6D_T|VEU_~}_}zdT4B+$xrSKMHo}DeQw-MO70N**B z^*}#=q$nIH)(x%408;j{?ij&(=miw)Q6cX;421zZNk!Nk#P}*%or+bHahGvJ2}bRN zTw@3`|K#d>%7dhsk&whvFI*=!e?*o=t8)Dbwg=}atT%5IqxV9QY8i!QSrP^j z3P(&Y2PDPHIk@NMVHRY-QxH5JLmRcc4gi(&uqMn}gBFlc)Znr7ND;47QYtUJ3kN#L zc0fbiI4Z(b(0eml-N8QGats5>kc}Qs(HIpd=DkE0&Wov?TbN`x?3R?`t1h zbYgQvV472&nl!Z{R|x_biCO;WPnk_2fFqPB2y;b-Qe6c^b;4Qq>S3-K-BAi+Y&GVn*r*Pny&|l z!VghWLkGzoBh1rgf;D1>@#bi^cVbb9YSNHJm^#vhb_HLqL0shJ^JTC_Oy4IgcQS-M zB5JJ|6e;o>WL89HSx*8!^Kz36so_H3Il?tHdl>SYrG7gd%tZ>AEM@!W3Ik4HyMkKj zE*g*sMms^7eKe16#_0J#pgj&<6H`kGTNZBl;gepgBNyv=SSIc*5m~PihIBL6fD74B zNYMBjmvCw8sP0^@M$DxX0xeIPEU|WwCX%rBNPPLu?{e+1hY<{OeCbffEHm9>*L0HD3Hd=8pOCoQzMhKF-^bj-% zfNKEkn}KNAnX3nE56h^La*r1ykq7Efv`*x;3)rm`r;;Mgaf-yw>oMl7I9}^{-bh@S z=E04jDjp$$D^iGZ&Y6r`B$%)jQ{R^ZE%IYf@)B8N31rR#YXso@12`{?Qppiftg!`y zNEGuj=sh)@_0e%^M8fW-*JGxSAe{qj4I>cMjMcg#7lOvam}@r*C1V$q6WoDxcsWgu3^q zifscT^GG~V(1AsAK3NF@)fX#CVL(LsIuR@i{4GLsb}C~M*d(S_tg|&t23;i8q~h|t z^LCNF{UUb1*_W4^qQ%^Ol1Z5gHn_xhkhXi%K#>wm6Z6q-2}2_425yeT*tMx3%k$^` zI9NKvDS=R5c2A_piTAzu2)!s&Y&|QY8*olJ+jNHn_Xt{+F4TDKKo33J_ zrHSPd3rA9YgkjTcVJ(uyQFBS2qP1dMmWb)b%@^kgof^6h<5P9ZcRHBXC}4@yvVN}c zSWOFBzQ^&91S$#A4%bgQ?!AchbV z1up9)ye}fOt+;HIQ6t6X9Fe&`muuA0*=jmLn>1O>9~H4}1V!d^>s3^V3zbHYB{C)( z`J0ijr;w`?QR!kTR(rTb%uN=V8gN@nG1rPjQ=Hjprws>4W)Hy?o!i=j+afV;K0My+ zE@XOflcij2BafUwu1n!{3Da8Mby3O*5~06>JBlMkPkJT3LZ*PJ5>pIGZL2hBWw!Ye z=4=&r&5Pgfz_xp>h*H7(N?V`YabOb|w$z)dbT=%*5lx?!dGiw0 z#M98+4ES(hiEUtX-n2qVN!+j8Ly_n}?qd`u^>}j)j@9WAT4viWRP!0Lg~Qj zZ{YMUw1WmcqkW9f91gm4WKJ|KjC2Q-zHhR~k|Bcg7B^;z&`dBd#px6NoDs5K7^@XE zzId9Gc`_2O^DUTZ$tuc0o6~`@4J#x43>b!^9ILO_Bh7+O8NG+#FK1HrubV&9U8q$EUC!EPv z@F^M)EzOOT7`nw4TEy>)V5%fko}Nhocsg$C!3-lID~Y6o2}UPpRa$hJ_oibM57~!N zbetpW>&oiI@oj{u2{X%}wJDlTLIiFx@c5?<5bR-$MK_s_7%E941d1sSV#^7FqcF}3 z_7=oaX<9B=&QtiXTLki{Fl~puI+}`b;gIj4PSLLxTlSGOT4XpCN9}UsJKec@d0VS9 zm8YarrA7og2&G zY=UDRCu8&y+dnpR?UMEGmKt)zru`{^)v_gODhnFhYpg~xGg=LHLa;&3G-`Z@&;qE) z+DyEzb_MC~_xrIKf&%1RqXuzsA`LKlDh_a=4$DJHQyM{U#bNzSp~`K}W1M-EF4VhI z8D`UoS(h6`uo>@m0H_-|z!)lSJF0!4T@z}M%sv|Sz_(yjs#J0{=|QM5QY~G1H1|Q! zN0FYZGK&^Js9Q8?mh#lqwg;TUjQn+TuYT|#RT4|fWs*Y=Qm#$#lk1DlKbSQ#c3#Wr z?q43nbVLQOYL~i>)8@1};U~(g#Iwzd9z^R{pH zcBf4<18&~lk@>9?)R=D$T}28CTTZUJ<@SjAQN7{h!CUe(%yf0s$)9h<@g`)d)t*;Y+V~SOzCX6{o0+rmyEJm zlWy?NZnSny%ns)h}g~%_o%5QFzvr^rLjRDp!gglBwZoizYOagzc%z%rmRgl9wh3Kst>)B-?AOl2$?kG1 zb8g19qC=yi!^5bs(RMH<6vWg;*OgV4<=2?0 zy0X&p>gc-hKIXiNocw5n?a3iN)RQbV3&;CpPEDoaE2{FT(ZLbHp+2!PilSnw@(QBU z5|aKXjy{d|DXOWdj1CD|ym)c&;!(jBRfQp8W5q%BzPx zt>n*o67s8atBNaYiYv+~d%fnIirSj-K0fw_o^5~hv#j!2L*>=MPx>63TTvELXRZth z3l0tWuL|YmJ}XmMTUGj`Yk9dL`K9?~`QKQVWlxiI9pCr^O>21As(P_#Do84%g(@p?(4oUs1WFs<^PIh6>CbPN9n+ib~F3 zT$*1~6O?MsU1+Y#L)TMTrMY|w08h`^UJ9t~wxy7fBg4iOvQa{bT1 zKDJMD+@A4d%%JYrUul1p{VT1a6M(3@$TsW$O3Qf@fW6BBa6S81nlFcLbWH&4`Rcjz z(b?zAb2o+J{M=x>L7#2^Yldez|9kLUd%^bhp4pB{$S*M0mex>qqvlqWR@7Ee)s^Pl zd@ATaPU8P}!RNa5Tt7ypM?j=<2xDO)Oo3@|4rE{4vD@N zT@u|RNm54!kYkW|)*P~ge34v3zD2%I^5k*y0(n;~7Q2ZNPe?pnY!=suo5gR6cZfd| zpAcUX-2ztHbcuAGv`g9}{YrXC z`m4-I79blhOP7_%EV2&SPT3*ZIoWNwT<#+uE1w}Rmb3B>`7ZfUxlR5+p;j0b@rrCk ztzxa>T@;k%Tg7dqQibLA6o!iRv5GT_=rGnA3EpGN(08+nqjlx~dkd z{nd%;Jav0DST>^=y}~s=S6#!c(r*Q@cPkP;~nc=?A_-5nfEoynKDtOR0q{h4H-NP$%a~k z)i7ZA)hEDbmQSP4`##?flMRa+Rxqq>7-By7dizfGt@nM;_pG1PFUqgT?+w2re!ut! z_|NuV;lJ1aYJh9Nq=2OX?**I-R0d86d?Bzi@YHZ}c+~KP!`~V{XvB=8jYYk9cdu@sXmDV@H;c>>T+`kRr$wv?%DkAX~65I3>6-cyI8H5Z{ojkXJ*Fggg!% z9a+}M}L?jQRgIx@N@dUy0c#|4dB zIBxs6t1$sF`7vEF7smUHH;=cD7h=&ke>({NLXX@}`X zTxeWX+{bah#7D=!6wfE%2@?}q5(X00iL(+nB>s@(lT?`WUeeIS(Gy>s$R~@ErzF3c z{LLiKNx74@O&Xd!X7Wpu`==xhFRBYsehkA&PbiHamMAeu(bNLBQrHK7tGu~^Im#f`nvS*W(Cfwoz<7&n30{a zE#sHj3A0;g3z;FAFJ*o?M?a@{&b};hRz}v=th;j)=e|DoQugTV=Iqn+0_N4t`+UBB ze(C&A7dS33FZhrVF|(QN%p>!3bEo-k&ZL}8IYYVexo_nDlt<^a<^7mHKEE~pO2PPo z)`F{r;|pIa{IO_4QG3z#;`rhX#WzcmOWrQ|W#RON?=Jkkbav_cWs)+c?2~eJ`NH!4 z3a^T~isO|dDw`{X7ouNy{e_{bDOFpmVfDP~eKlJ2W$IXMVD0i++oIS-8yDSQoU!=B zI;Xnwx?@X>OI9tpvNUPwJ1-J1=DyfhZ>YD_+g>ugWNm;AISqX;4|}=kui2rws`;B0<5s-Al2}>1a$wb{Rd23(+>+Pw z#p=-2?W-TH$zAisD`Bs6yz=|ng0%zdBG+wRPp&UtfBMx4uXeXOwJvSF@Y>YZ_OwxL zEp2yRU-0_p?Gf#7zae|0_6?yUrDNZlzHhF7^U;Q)4PS4J+xY$_k4>vK{qk1cTPHTt zn|HqL`S$9!A9BUq8S6yro=*SH_ATU=MO!X+Wpo{RC+eMTTlHI4Z~g7v@^^*qwC?_G zW43ME?y-H{d)Rxm@BO$Vd&l7468^StXV6aT`?~j6?*hAOcU}8{`QY^KDZBeVjQVir zM}8k|`dIUE%O1FA$)2ITMSF#PbM_toWb!9{J>z;l{(JD>-`#K6zwuM&PuCrg9cVi6 z`)5l(yUSPd*Lw?lFZ3OS7W}~H#l~%=XlKV11Bb&=slTm^6;rir@s7p+SkWV z&pLhPo9u6dGkIsOep~wO&9jTn{`wtzPIRv2d)4>tKY0Am`ESGj?R_Cq_|%qQJ9d8N z`R^{|Uij%^^~Fb*nl39Zw_owTvh8a4)%`yv{Wy4S?zKxlRsQtr_2!?Qe%^E=@Ww~~ zr2lzrD0Ar2&8nNf-&%9q?e@EOBJT9vO}+cWy|R11{?c;a?SA)zs0T+L&VG31*Ts*- Vk2-!E{#(!EDUZ+nUiSO%{|@^N=>z}( literal 0 HcmV?d00001 diff --git a/Tests/test_file_tiff.py b/Tests/test_file_tiff.py index 6652b431e..bfc3bf120 100644 --- a/Tests/test_file_tiff.py +++ b/Tests/test_file_tiff.py @@ -51,6 +51,14 @@ class TestFileTiff(PillowTestCase): self.assertEqual(im.tile, [('raw', (0, 0, 55, 43), 8, ('RGBa', 0, 1))]) im.load() + def test_16bit_RGBa_tiff(self): + im = Image.open("Tests/images/tiff_16bit_RGBa.tiff") + + self.assertEqual(im.mode, "RGBA") + self.assertEqual(im.size, (100, 40)) + self.assertEqual(im.tile, [('tiff_lzw', (0, 0, 100, 40), 50, 'RGBa;16B')]) + im.load() + def test_gimp_tiff(self): # Read TIFF JPEG images from GIMP [@PIL168] From de3f59d0a72d6b3838a89aa32f3ac3779cb0c772 Mon Sep 17 00:00:00 2001 From: Alexander Date: Mon, 21 Aug 2017 17:14:33 +0300 Subject: [PATCH 4/6] assume --- PIL/TiffImagePlugin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PIL/TiffImagePlugin.py b/PIL/TiffImagePlugin.py index 04459748b..bd66f4a7a 100644 --- a/PIL/TiffImagePlugin.py +++ b/PIL/TiffImagePlugin.py @@ -244,8 +244,8 @@ OPEN_INFO = { PREFIXES = [ b"MM\x00\x2A", # Valid TIFF header with big-endian byte order b"II\x2A\x00", # Valid TIFF header with little-endian byte order - b"MM\x2A\x00", # Invalid TIFF header, probably big-endian - b"II\x00\x2A", # Invalid TIFF header, probably little-endian + b"MM\x2A\x00", # Invalid TIFF header, assume big-endian + b"II\x00\x2A", # Invalid TIFF header, assume little-endian ] From 7f7b53447a5e3650a2ae77f2ac24c90dd064e76b Mon Sep 17 00:00:00 2001 From: Alexander Date: Sat, 26 Aug 2017 17:36:06 +0300 Subject: [PATCH 5/6] Add tests for all new modes --- Tests/test_lib_pack.py | 8 ++++++++ libImaging/Unpack.c | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Tests/test_lib_pack.py b/Tests/test_lib_pack.py index b4c8b6a56..e33d2c750 100644 --- a/Tests/test_lib_pack.py +++ b/Tests/test_lib_pack.py @@ -240,6 +240,7 @@ class TestLibUnpack(PillowTestCase): self.assert_unpack("RGB", "RGB", 3, (1,2,3), (4,5,6), (7,8,9)) self.assert_unpack("RGB", "RGB;L", 3, (1,4,7), (2,5,8), (3,6,9)) self.assert_unpack("RGB", "RGB;R", 3, (128,64,192), (32,160,96)) + self.assert_unpack("RGB", "RGB;16L", 6, (2,4,6), (8,10,12)) self.assert_unpack("RGB", "RGB;16B", 6, (1,3,5), (7,9,11)) self.assert_unpack("RGB", "BGR", 3, (3,2,1), (6,5,4), (9,8,7)) self.assert_unpack("RGB", "RGB;15", 2, (8,131,0), (24,0,8)) @@ -267,6 +268,10 @@ class TestLibUnpack(PillowTestCase): (1,2,3,4), (5,6,7,8), (9,10,11,12)) self.assert_unpack("RGBA", "RGBa", 4, (63,127,191,4), (159,191,223,8), (191,212,233,12)) + self.assert_unpack("RGBA", "RGBa;16L", 8, + (63,127,191,8), (159,191,223,16), (191,212,233,24)) + self.assert_unpack("RGBA", "RGBa;16B", 8, + (36,109,182,7), (153,187,221,15), (188,210,232,23)) self.assert_unpack("RGBA", "BGRa", 4, (191,127,63,4), (223,191,159,8), (233,212,191,12)) self.assert_unpack("RGBA", "RGBA;I", 4, @@ -276,6 +281,7 @@ class TestLibUnpack(PillowTestCase): self.assert_unpack("RGBA", "RGBA;15", 2, (8,131,0,0), (24,0,8,0)) self.assert_unpack("RGBA", "BGRA;15", 2, (0,131,8,0), (8,0,24,0)) self.assert_unpack("RGBA", "RGBA;4B", 2, (17,0,34,0), (51,0,68,0)) + self.assert_unpack("RGBA", "RGBA;16L", 8, (2,4,6,8), (10,12,14,16)) self.assert_unpack("RGBA", "RGBA;16B", 8, (1,3,5,7), (9,11,13,15)) self.assert_unpack("RGBA", "BGRA", 4, (3,2,1,4), (7,6,5,8), (11,10,9,12)) @@ -313,6 +319,8 @@ class TestLibUnpack(PillowTestCase): (1,2,3,4), (5,6,7,8), (9,10,11,12)) self.assert_unpack("RGBX", "RGBX;L", 4, (1,4,7,10), (2,5,8,11), (3,6,9,12)) + self.assert_unpack("RGBX", "RGBX;16L", 8, (2,4,6,8), (10,12,14,16)) + self.assert_unpack("RGBX", "RGBX;16B", 8, (1,3,5,7), (9,11,13,15)) self.assert_unpack("RGBX", "BGRX", 4, (3,2,1,X), (7,6,5,X), (11,10,9,X)) self.assert_unpack("RGBX", "XRGB", 4, (2,3,4,X), (6,7,8,X), (10,11,12,X)) self.assert_unpack("RGBX", "XBGR", 4, (4,3,2,X), (8,7,6,X), (12,11,10,X)) diff --git a/libImaging/Unpack.c b/libImaging/Unpack.c index 42b309e7f..a061beff9 100644 --- a/libImaging/Unpack.c +++ b/libImaging/Unpack.c @@ -1320,9 +1320,9 @@ static struct { {"RGBA", "LA", 16, unpackRGBALA}, {"RGBA", "LA;16B", 32, unpackRGBALA16B}, {"RGBA", "RGBA", 32, copy4}, + {"RGBA", "RGBa", 32, unpackRGBa}, {"RGBA", "RGBa;16L", 64, unpackRGBa16L}, {"RGBA", "RGBa;16B", 64, unpackRGBa16B}, - {"RGBA", "RGBa", 32, unpackRGBa}, {"RGBA", "BGRa", 32, unpackBGRa}, {"RGBA", "RGBA;I", 32, unpackRGBAI}, {"RGBA", "RGBA;L", 32, unpackRGBAL}, @@ -1356,9 +1356,9 @@ static struct { {"RGBX", "RGB;4B", 16, ImagingUnpackRGB4B}, {"RGBX", "BGR;5", 16, ImagingUnpackBGR15}, /* compat */ {"RGBX", "RGBX", 32, copy4}, + {"RGBX", "RGBX;L", 32, unpackRGBAL}, {"RGBX", "RGBX;16L", 64, unpackRGBA16L}, {"RGBX", "RGBX;16B", 64, unpackRGBA16B}, - {"RGBX", "RGBX;L", 32, unpackRGBAL}, {"RGBX", "BGRX", 32, ImagingUnpackBGRX}, {"RGBX", "XRGB", 24, ImagingUnpackXRGB}, {"RGBX", "XBGR", 32, ImagingUnpackXBGR}, From b9f3fa4a28b4954c8043c0bc5606bf0d5796bf72 Mon Sep 17 00:00:00 2001 From: Alexander Date: Mon, 28 Aug 2017 21:18:25 +0300 Subject: [PATCH 6/6] increase coverage --- Tests/test_lib_pack.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Tests/test_lib_pack.py b/Tests/test_lib_pack.py index 55e851365..7a4f16ec8 100644 --- a/Tests/test_lib_pack.py +++ b/Tests/test_lib_pack.py @@ -271,10 +271,21 @@ class TestLibUnpack(PillowTestCase): (1,2,3,4), (5,6,7,8), (9,10,11,12)) self.assert_unpack("RGBA", "RGBa", 4, (63,127,191,4), (159,191,223,8), (191,212,233,12)) + self.assert_unpack("RGBA", "RGBa", + b'\x01\x02\x03\x00\x10\x20\x30\xff', + (0,0,0,0), (16,32,48,255)) self.assert_unpack("RGBA", "RGBa;16L", 8, (63,127,191,8), (159,191,223,16), (191,212,233,24)) + self.assert_unpack("RGBA", "RGBa;16L", + b'\x88\x01\x88\x02\x88\x03\x88\x00' + b'\x88\x10\x88\x20\x88\x30\x88\xff', + (0,0,0,0), (16,32,48,255)) self.assert_unpack("RGBA", "RGBa;16B", 8, (36,109,182,7), (153,187,221,15), (188,210,232,23)) + self.assert_unpack("RGBA", "RGBa;16B", + b'\x01\x88\x02\x88\x03\x88\x00\x88' + b'\x10\x88\x20\x88\x30\x88\xff\x88', + (0,0,0,0), (16,32,48,255)) self.assert_unpack("RGBA", "BGRa", 4, (191,127,63,4), (223,191,159,8), (233,212,191,12)) self.assert_unpack("RGBA", "RGBA;I", 4, @@ -470,7 +481,7 @@ class TestLibUnpack(PillowTestCase): self.assert_unpack("I;16", "I;16", 2, 0x0201, 0x0403, 0x0605) self.assert_unpack("I;16B", "I;16B", 2, 0x0102, 0x0304, 0x0506) self.assert_unpack("I;16L", "I;16L", 2, 0x0201, 0x0403, 0x0605) - self.assert_unpack("I;16", "I;12", 2, 0x0010, 0x0203, 0x0040, 0x0506) + self.assert_unpack("I;16", "I;12", 2, 0x0010, 0x0203, 0x0040) if sys.byteorder == 'little': self.assert_unpack("I;16", "I;16N", 2, 0x0201, 0x0403, 0x0605) self.assert_unpack("I;16B", "I;16N", 2, 0x0201, 0x0403, 0x0605)