From 58d5442dc557016464fea9f0f5736d17b23efb1c Mon Sep 17 00:00:00 2001 From: Seven Du Date: Wed, 6 Mar 2019 09:48:20 +0800 Subject: [PATCH] [core] add stb_image to read more supported picture formats --- images/cluecon.jpg | Bin 0 -> 50243 bytes images/cluecon.png | Bin 0 -> 115565 bytes libs/stb/stb_image.h | 7547 +++++++++++++++++++++++++++++++ src/include/switch_core_video.h | 3 + src/switch_core_video.c | 48 + tests/unit/switch_core_video.c | 21 + 6 files changed, 7619 insertions(+) create mode 100644 images/cluecon.jpg create mode 100644 images/cluecon.png create mode 100644 libs/stb/stb_image.h diff --git a/images/cluecon.jpg b/images/cluecon.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a6e89751ea740a812fe188a25c30c870a9eb7056 GIT binary patch literal 50243 zc-ri`WmH^Uvo6|%-~oa=gy0_BA%Wl)8fYAXhsNC@A-KCcjY|iYMuNLrpmBG1y?MXA z&pl)B{o{P+$NhJ!*XS{O%r$FOuUX@%r>f@5pO;m@TX|_YX#fJkD*)Z!58wq3kOUyU z`bYlxM*J(UkzfBKsL04j$Y`kO=xC^DXy|XS-=Je)VW6R5;$UK7zkQ4I7X1w_9`0Mb zzvH+6C_(sVCE{z;zYE`DpkciIzm}KZ031}n{i|$51RTIC90WuhgqLmrB>(~N3K0SD z_xfLgiiU)Y^7<7b`akm?ZvhC1ul_z55eW|&HM`xy|QSGab1_E}a=O>{+IcGf8xAGqDIE${Dh}!!G$nldszq+WjbWpwB9%5eB8(^b2I z$zO9h7MSEmAeF~=ERadq!CLo8ip&pG;1(17`9qUpNa3YCb+_&N&MQ*Jk{$unDL18@ z{ZDg+!R?Y}t4sUSHm)o_-l)>tXQZW(zovnScMWv5oB1d0zgE^=J+~x&t1s$@>0C$M zkUhqZ*odZdR65;2FEh4ogVP$eCk+Pt%7>*7kJp|&(THCF#I%pV4L>O;ll3fx{qhYo zw?X9$k@)dAdP)3>q@N;9L|AE@hSMQ0^a^bPWg}c?s-Lkd>Za8P^Iq60tgK_|M&U`i zARNZPj&qbeG>SapR;m1}yM!-XayF=`T0NmeQCctSJOPO@AgB3D!oGa{kIAMPM;Ee2 zl_uRaugpijY5DxH5;yWW*y(@lIjZ$oNrnw|!3rSGjFsS{e=9K)reG$S_|Q7Z(#q zpW)}rE6J>@d?0Qz{@VN*YPHw#bQ7~*H*)rGdLr_Q*&z97`=Gk8FKTlzuK(Hz>y7C* zR0{m#>G)}96hrPJN!{A&Lk&$BsU5s1GD?|7bjZGHr9_AC&}#*C=|TDKhdV{AyX}%V zp0P(o?kw(RKTaMWyh5Pximl*Epf zTP$=mi!jbclonp2xdAi1(u3wsQ(t>+S$$_VXX#;m@GIT$i~Xtl0yyo(^uupGcw!*% zeQ#cImoQgtc)*PV6F$e$K@)f&g4|yZMLrR>Y}IJ_>ONmx@>xE=+sMwIcqn?#=S8g1 z4c3Mrr2H9E+s8A;?jx+*skt>`)wT zi~uaU^ZEr2fgy&Ih~IC->E^#kx)GXi4N7D zQJ|8CP;W6x_f*^8lf4^zU*8pJW^1&SN$8udpu5H+r8YdUS~9bhu*+wX7mLKTN=H;k zF}(xuA{u0qlmzL=xz*5)FLn6WtaWl`6Y$EobBGPKx8}t(i=!>Jf2(4?piW zLSH{KCrov9X1{8JMpfwFDff>cwN=%TeZQs|Y(1K`Y!a(kt>ue?HV^qNk)u62uMPJ! zG_quCaxE%n#eP?*X~}=$jl7yWKBihG?hxAQrslW!IZHhq2byK1mO&*r2BZYxZ(t(`GQ z>5$9J>4K_OHCveUWmOg(@!&^q28Ez)f0Aki`l;H_hkc*IY(tciMzi39;V1Fc9bX+5 zH^iN`lidDMKWWP9Q?qE(N7=oB2MkNgccOTn_a4Q$qQ32FAXl|bBgeW5}7Otpat--PwvQh|Ve>3Qxu(Bkq1jIId zq~Klnc%62gFYU4g!_y>+DEL`4sea?+(_J}WKtet8gHU4wt0(S;#X8k-UM-TtvB90p z{%Ds+_6s0JR3{d=SVJ3;m$9C{y@Kt;f|;{$*XbBZ8p*O7U$Z|`;j&=`UzGPEM5)pm zkJG_jMl4-KRPueUV=V{_f}R((#pTZz`WN!=}Yj9wf|qxrQ1!obRY4mC0iYfFH3 zWMiR=XtV}5BW=9Z*2jWZUYIa3e2Llj_e0KW*^$mvV!(e28hK+tgLP9pZ3WM5S-40A zR-AvhHa2Q>d-%LfglkOkjg5n=HlYHG4^qs=EcXs_N%O_~AU<@!az-WB_0SuQ9nq?6 z4U)tzJm7~r0VQ-AokU!HTEC%ah1SK~~)s_cS8l)Y`A`SsFy_@lJ=Z35>gIqFK5YtmkHUh%Kd^MoH zaxS;AsMDqsX#=}N*^lo>mjf;_dA=t=zWu!b_cKd%wVwsAYSeoLlY>6!%AY`QQs04zzxn&V z0918SB5YXsiCmq32`V#CJ_ef2_RmELbYyZkfpmvioTV6ZS&U?T#thN|AhF{f(b;UE=m7p~KxnG?;-02Osg*7e7@cDt*r)pspj&#v~GDK#tc=p<+ zkIsZgkw?ifQ%I%jM~~fJiG0~iDDV+Y!&Q>~&=mQ`AlB7KF~D3Ki<|Yllx_E_5=F9l zomJAm2&0lJ<4`75cy_i81#p4HpgIi}DFfG2CNYarm^nLrXgrkG6(2UDGjDSA9i>8i zSl~1rdW5f*9Ikh3d24U zO7!_;iC(By#->1M&-!~c^7q&KsB@0N*=2_MUTb^IHA~5eDik3}q)C^A4b}VfeOQlz zlC|*k_I24XTcK$^bCy8eMbLQW{`tjJzw@42Mn1jz#-xUh3;y=0*TTRi5@JMHXfYuPWK=B%O_R4WS*XnzzzHz*e(P51(P zj=NNFI|f||d2usMw@wWn@`Ki+-k!Nc+stC#I33MEObiBkIt$M-3N`r z;SqA!F^fYp%~upXuLDF17ku=c$7yVjOt5PSOiVW+t;1m(*EHC|jU648WpyX5 zQFlLTc3y3`k$pcXtJTXGM?DV%;^$9wx`93S_OGUcG1A7n?>GjMEs=-ot;muYcpBDb zqf(J=7P>fz$mlwDxzyGbA{oEuo<-B#9OMHtnEM<{n+15RG`ds@y5xEl%C;LR(uudO z_0P&;Y*rUHqy|ZI^+{3|Vd@EeF~jw-wL;6AC3UtoJGxA|VC9)Oz!&*=!|i#^tus*q zQR6H93LJ1N;ui25SE zkhrYx2f1_onsubO<@d?jCE>l27?e$pnha2^rjNtKHYVjVNQ`c!Y!lvbQ(hlYzMWru zK{Wib2f|WGW~4JHJ(i-X(>^HU_wO1~S@*F!?(>z^Jz!9sDvd6A55a_kBxuNXqr|gP z=go$OSc=+TyG$_J$e!SO%gHy%>I5AX{MI-`)LGy5$oPkil+7_wj-oGjps@VBeNOC7 zVgAgxFZz8%0g5|}3a<#gbV{yrNofV$oaRW7aK(c~XJ|m4;R5JC=nSwW#r#bnrz*57 zcTiyWrI%;g;$&ao&ti$3d;uktZ_)RTHdMyHF}pj-iu;4DL%!k0&$`r*Gm88oVB+hn zoI7kA`P2C&9edT}gyzAi4}TuT-j`+a?X@{PD5coa-gZfI5AJEpAOsy_8g5AW?5S?m zYX^|V!AtDG5@E9nw2TBawk2Y0&g6$1ytxL^lFIxE8o?)G&!LVag#;>~ zh~PD@uLSex;1h1P!`;TWb`Q-HU)ETUAE)GfF8~LD@VoNTFbjiNP1vTk7u~Lao$h_A z=l|LFOs)9@-5&hE_K*TzEgR(T+Sno}jK@}{-C-5BS^^U-ZSxKBLZV2s9$Pb^ z#i=cvre>|%s-cw=n!73Cz`XiBvQ6Rk(&QY{y*jxo=gGn*N=>2%Z77}n5i`ZF1)OQI3ZCKSbOgzFG) z?1FxvEI*-r{EMcZWn($K1{>Vql;BOvKKSJ|QI_aL9B*G%S*sV85xsf| zv{Z3`z3u#RaifeGSWAj2x9^FdS0XpCtb7IY!31~dgqz$nS>$$(XWcuv{^3u`TnW!^ z@3VsDvTFlRVqNR;6{vw1y_8ma{oko}y;3`cCn$6i6|!p5Qh%w~Qe$W5lTUZ>ihJd4 z*aGyld@yVW4ySYM6_yP7&ph1_B+XicV@k~x?I_5ugx$E_#)r^&rbmgo{z2V&Nblpb6+M{tW%|5N_*ZgPwiM-#D?gE z`RSx5j^l$EV#*8Pm;uL+H&In_XOj8GJDkI`6$SIaPmR$xcdL-`%`xR~_Z=cWgU%GL z2TvOoHUiy>F*$^=s-XLeVN1d1CTYFRF93;w~*V@Yaq8y5v^!)T6~gysCY;P*soDvbI-EtXP<@ z|5X@gjs%#H(3l{U5a<8pZ$cRWiB^S%PG$1Lc&3g-EkOka!j}+8^HlqfAn4EO{|t-` zGz>L1qalNf2G9!AIKN%c`cPGLAd_F>6PChQbwPfQ+6zF$x2T{ce00t?F}`ulucK>n z>`C8fl~W<|pWCpdGPbJMLW1u$u6P~-+k6VW(=}%CL!69S8qZB+ZIqgaidE&uYZ+f9 z()y#)eEEc2XGTQ0L1!Knz(5+S_Oscuuqj*W>;1p>9lwzrs0H~XXIW;U*LXS8j~Y-=t-2XVWgx5_7TO-%IWiqYiGD>tsZa-_J7JFI zbRv4Y?fYIJ8P`p{|IK@D8)@s@`gA#lPbJJkCGx7wszSwg06>{T%3#WVE1Q7`kGPDP zpfVMG*Rw9Rm%)wgQM>qDJiNdO3#YK#M}iU+(EOMwDcd-y87)7<>*6 zf4enmWJJui#A)!l8>D61O#C@Kvf_4xsT1A*Rfa6mXF3@rmkEY>Lx&8rZCDn8ecdkG z{x1jpl6(Vb{_p?gU)o%Ld}rL4@?ELA;g#iW0nJk})^UakAv9kg3Ge(-_ffAvgB|O7 z>NA4c7d2Hm7kaP3LhLR4$po!rP_tt&Z@FCWD!x)>U`vfBp&t7nY)xHj>D}Y5o(qa>maX%xGjYR?=vqG+SC6RZ9TE15An+jj&;7$p<~XXV zBs#WEY!?2hfAwn~(Q&-?8&=Ncfv%P;(==?WWORf@J`qFaHZ$8vv8s~F-qXI&KsxQ= zt1>K6Y=6)hG_sF|@~phl0RpK8J+@KEoyFcgfH_adqV1#8F^QV|oa$E(GzGcrpfpYn zE;czbY5f#_uiE44IbE!0c!#G3Pahusgxc$Hv|DOD>RMQ{E)8ou#I-3U2Ik5bvA#O! zH&)Litn1$tNI2BmVXBaqqi+2)@e%z&csNO@I+95&ib*#zeNI={s-iV;rJ4kB;Iy)k z9u1Uk17m?4ZJw|!S+@4hd9z0m=}8#;SE~K5+S?1DZuGGhbc{0QvmzOr@f;y)wmL*N zh+RTS_JAf%O<-Z>8>-UycvfrJQg+i$DBJS;7R%%X(3m0hIIAJWoh@6obk5oucS+7) z@uZl0ADoo>>#G&3)z&4aU~LmY5a^+w1t=ef{8J*U`535@vWq=ik-Dk%6pK3s*{ z^=0{IZMvM#4Ixu!UG5`q5X}ZjB)w!DXov3S8kuAm>A?$tX8xcIo2g6Cs3E=nOv;Ac zh`f5$WcfqOY`zqiA-Vak9t?VtSj(MmQeThc(+nj;-ha@*UrTlTR+|Fsbj&uk zb`H$6NPIEsxy1)1^0HJ^)ve#UAjNqj-uedq0fmi^%i-%zI@z+m?i*P(s?VjF1y>99 zkoRGb{_$hbAYoXZko^zyDPbC=KIdK_n4Yh5QG>PgWsyFvx@Yl^P3+3Hy{SZP#!p}m zO{fZ{(oE?QzMM$*n*Y3CAR&mRP9d9fHY8@u18BmNSD}`djs{xIL^#9W*C=eolsi9+ zBQVZXhwoHoW0x3Mz>L%|1!b`5h>P;;p(`#{*9={?NsWliti-r|gguz#ArAbG`P5bh zodt-{PwI55N;x6yGG^xq-9~opV zvyQv8Z z{k7VhP*Tv;I$iSF*5+M_iRv6MAx2ExBGYpsSWZh`OPW4S` za&t3zqM3)*NwauYqj=o+l~qYt*+l11I8CZKi7|7NoCoJLbXmmd`-Wbh6ZgU z)K`)S%ZZzoEy)Gl<{ce|k=}Mx!Dj+icjdesuTRl?`>d=Ye_VIr3duS%PTTrqcyZ6l z5jCW3KI-Ke*6Z=!RJ?3-9c)AtBt)e`%KxLm=9+laWIKQhiwIZr-<@O<9F!2uVlBNjxo{|zN9GtZF0=R~n1^BOy@+v_x z9`CI$o8sKUjnQ+4z(5p3RPlSOgYzSMkt7?5`e3$dZN zHJb%`MQs1E}#=xW#^eD@<#(i?6CNfkqeb0g3N9ijMU^V z-p&DRs#f!)(RXG$Ux(}Db;~OhOQ>i29WWacX$2-Fe8)bF9jz&~Uzd$WvRAdh?As%LW^>>X4l87g?{UeDfpk0N`7 zEC$Q?u)_5-+L)3`V(0#*c!YmOda?aJDH!WaIs=8i$x;!i?U!Ly8ZtMU$#c~xtgC8S zUlZ$jS8)ffuhg-;0G!Yk#5-#%>E5rlYz)d>zm~6Efc%ERgsi_GoVii|iR6QSb7ofh~+x^1*gpEL1@mYc{QGK68}!!mT3xxyqm8PPL^KP^BiN-9$B0Tv$y zGsrT(iF%a10IG~ky%f+V)PL2f$v-PJhlqjt-^%mN-#kV=+BllPsy@^R(uP)kqXW?1-UET8eNB}mT;GH z=YR29z5WPpu|1DKl3pI;6Z@c`nMR6Tg;Iq~6xG5LeOInhu8c`<+PNr*rlmtnzBEup zOIq_9GGRJk3A1Spi71j@{}nWe(j5yupUFm@XUxB-(5Y0`pdy5e9W!3Mg2(9b_WOQ? z@ru8#dOu_nZ_R|&+bA3QuKGL)FNA$oSgs7uP2Y}>!y{Yu%+L3C$L>d?(B)+@)i=)rcYNi zUD-wqoA1jHp%Y9uR9SrCH;KMC7qkZdwSYeMPXV3KV89cLZ1%bE%ai1gBK*96&n^49 z?tg1_ivE{YGZNmMK^XGSdw6!DzV^Ibp5#foxX8{6pyj{~`dWdKOkK^NgG`QUX8#UT z6I<*u#m#%3?N8yXq2}z}=f{U>0PH`&@XrVA!%C`Cs>iSc6SVs>`06)v-*66#FxE0^ zF$f>WD)vBL`C-xc+Re1D+k)M4o$p;uU8B6a+}KBK$)8Xk@l!O7-US<-W8c>`r)LWs za|W!C(jP=xIotwPZxp+M{s4y%%cYUz!Nq{Lyi>zqIi_8#W(w~>uZdjdv6}L!o(<~2 z$lIZ~CXQR5e$a75-h)Fx2q=M?t>`1}VP4b^c_s=K4VS$+om4Xt(ET251r=`5LS%t+ z!MK{&)Gf=EH<}vq8!|o9&Uz`yH$^$}GKQUCU1DkU36PWpu>3%7G#@4gE0~=#jW9Q0 zs3U;*%V`Vk-IU>#peuOV_RWwIIN&Z8kkw@9yC)1`m<&dBhdL4d%-yQzc?PnistI*= z%<~N(Va5%Y$#_7bX?+>b=Vt;2qwS-zj|Op_AJKVt$Zy^(H^`LN^K;6dSw1`mT?9E% zy)vPV{%E-10G^W0kdu#UgR-&YN|H(9+&c<14i}OAcyhO#wMjaNTY1>nBb-PuQ4kE(#8CUEIBw`;;n*cG$5yk9Z;g_f!hpSOTK7&aVr1dZ zaDS9g(llbIWbP;S*CpcwwG{X=<1*BSuv!jt%s+Dyf(7|`#HSEnt~336_ru{fy6md~<w|tRzpa^1Q=b0p-~Z+5hV9)mbM1%eMCK2L&9Qf5R3YvW z8an6OE8+a!b`D-_?&iG$XW_M88a?T(clHHsx(lJ78t{k#t4zRz{WN*tr^Ny~Aqr;^ zayb6#4kOIA$o9eVj2_0BR9d^+>CpC=_@sN#RkNr@cYo*HeFKl8Ym-0WXQ^!{QuH!b z9r2k-Y^*3jV49I<_y{1qd{s6-szJNM&H*yuv6KiDm@KRyh9o;qP?Fw>{`bVY6mILg z!-O+0H(o+*HI;`TWOepr7uLqCu0Atg7tpERtNtYz%dW)doYqx#i?@ql)V#;oI`{j! zVkkRKsYK%RK8jk-wePehWqGEh9oN+0uLQ?KA%$Sd*#{fjo<%L&FJ`@lTcWK64G2w| znAx9wCN)YJ48Kv1X_&L)-%|cb4)43;ul0-?GwKn@C$3OjgE>v=$VgQnFxs>m0`stI z23t*lF5caaRRVA5^%|-VL@EyNv!w=FI=V1R!6t>) zpr9>LOiLiHNORy@KS2JT<$fbc;rXG}qMfTse6t^7m)(dL+m`6^{({8Q@e#!3_Q@q= z-9(I`!aA&tOh+f5{;3^%T|uwRIi$)K1pA2*$xNOUccAi5_r5OoW5G9|91`u@Pvdjt zrdh>Xn)!@(+)^M1_-~gJX7&qi3#OxF;bq)brA)C6yC0SxrAe&ciRNx*Pq&xyl_dml z1;qpwC(_9;1f1m4q?B_P-mG=~4shAEL`SSL1!ch9X+{s*2j0U34T*0aV{sS6@UAq& zSqn~lih4j^;v(!QgCYk3($mA*qxFMN7bc}D%e-fd(#l6*Pl*a01y@{47b+OIY^-gKXW)juUE;wt8!S~UC6T0;jZl{B>bD;sX>|VNryE%bGwHUB z_gF8R1?Wx&&Kb4y$SXMI3^08WPV-3gd}@ENDuCoymSnI9C?5>O37hL!uwoqYnzh+T zhC9_Sk?p=^ z0&^0LnvdK6G}*fct2#TbCsVeqym~tq+VVHyXKa)SU@(rLSLanU6WeTHPEj21krI=J;!1k@_<%k5VI&I01(toj1wuZyeXK`6+DB{F zM4Emp_C+qTCo|3QX8<)u6skxq>*L}p$Kx1;)KO^@@+ElQ&1x5DGD?fuw7WfI=ec@e z5`#+A(&W4-+uv7Ng~|Un`j5PpLBdk$TGHVq%f{=O~#5ZY}xVy3PpbQ#vV@?SgN>Au>&utl+1*#E0k z+2KEw=F>kHxcfcC{}Zp9{>E$g`q-G@3*ba(>7WC*E9m5p(#GMHcTibqwx^4nRpQhrp{pEQG;U%*<`)b|jCf%k(!q2qBVfpkKc zJ|}&^;cWK3qUOh$vLhDE(y?X2_~P1(#JuLVWyl}1r2Oh>Mw{1MlM_|e3MQnTE`J(N5Gabj~F8UoOAGRdiERzCsEi2DXya_=3^xkAGXXEYHy{7)dzf?zW z>TU5S{WcvdGhffQD*OUJk|T;3wKv7?`CAfUOci*AIn*|o3qQ8KP3DU)2oQ(4J&fr# zUC-|P9QXRK4Tw>F=jpmWKkez*sb1r6`oQ2TB{*mr-Y%&Y~IsY4OmHkr&&>6$oo5l**PKizb^ zLx9FyVMn!=nCQ5boaia(fmBJPr$xsCTjy@$Yl6J(yn6_B6aAlpmMN; z%IOOru4tZ}xxigMQ^sd9Vd1bj3agf79Hh41_7L^EHW9yqnaSZb69!7DI#y2D(PD@^ z|6JOttRB9-1)iXc$3V+=O?Wr5Do)eHaM2&G1ANRTrwDvAeP#6khWfmjS{7a;F6++aB+W`wtR4 z%O7n{tYnzL&)<`2iiJhWU43$|?k%Lzd}Fk!F+kCT%MKvLP`tk>m!+e)g3^%7Q4J*BAJ3*gF(Q(db{>c7R{k)(u&kzbMg z0y#gRwV5oK^LqCI6mpF0ta~YB7)Uw zc)G^3Vml^`XzhxWiHJ!=o@gl$s_5C<1dtZTSAKV)Z_;pJA`HTy&eXMI^A-y^xpqBW zM(=WP!WLa}s9oeGv}T@Ie5?bzR;<3d&MCkUDq%u&L~h=LLiCuVG`gKun`*K_0_8(^ ztgv^QOBeg?e4=0x_TxF^TT!7Zf#i@!hj4Ah*TYs=3uM+jGxdK8_+nz@5V{%*WYqQ% z`!xggIt!Ep*dZ?VWCTBcD?l7vz@mBuP}t{*qKD!TkRGUq^@>?kPHbUzFLqhmbh3KY zPnj_!H&?;b3$;i&_}27}M1j(3U6JLTe3w9&A`FknMlvwP`S7b8F?lxC7X@YI)Wv9gBgDpjPOmB zt|48BiJdP;UOkZ(a>=0do3ieLT(NlCd8dc+Pewdu`WlD>`6idc(|bx!P5D6AVD58D zS3?AU%B{^Uw{cgK?lG$%p{XES!K|T~G*QYMz z^kKs5LqTQP=y#A=eU%>7Dm-pBMg6rgbLM&6B$CWpL&09Jva{Ld9%i;U}#q?nc> z8WQ^x!TN6+?3^MrCpKMK!|rX`kE&k)v`emzZJZ}}@9AnY81|ur+6v2mL0ThgYz+08 zYbcIFffbU-cnM9K)U;SM-oDYqOWNtRS*RZD+=!!ZqNsz$P}tN}*ojstU=}HVkNG+C znPEZ7(MhCNKuCAewS6g+Z_Lzb#DOefW??R@T2ua{`LXWsoizUlEc5>M63(2^?FdQA z^ns+JbgiTBL%h~2cu4n(`o6qTHWI3_B^RTEC!0E-POGzk?;w|l^`WO940-g-UI1_W zM*cywx)*?;?qA4SdI6w!`Z4r8sVKhbYYiSxpG?anQKm`3@5hiwIJ1V=f*!lSSu2)_?_E+cRD2o+Uo$0?eL;5?_Kt@t zEgR$m-@y12i8h7%(!4|X{A%#etgcI>i10dTlgM^4`g++%vvB zUM8_l-l^g%_4Pn^P5&~b-NBz^KT85jSb1H{+m1sql5AEf-~FO3j~N|i0e7FR)o)Cs zHP#FZt0(f0m|1iW4JZcEvDZTyGv(w^DkNQ_StCiF!D;7aeN|6+6MvL)O2Q%M3+GP| zg7y2ETW?<^>YaMU^(ZQC&|L!Ys86NMcE=KI=(<7Ak?Za(EhaL|0abefo0j5>(9gnr z38TrVgBrFl4T5h>eLs1aJ9Zh-j5p#5)2t@CzVcY(1|7e&NjVIJE7sypSZw?HKdpq*eU3Vn$=btQFPES7whq zi>#*X1ppl`FWt$U`1tR)MyN_C$^V_!2=srpMjEz~4_f}Jt$c+1OYPX^|1Kc#U$JyO ziB|~TY0P9M-P4NQ)m-%YJ&ZPZo__wd2D`@dcn~$DE?wJMj>kGlr-Ktbv_UJ*L+@^j z5#0WDt`FhYSB`l-@m29Vg4tfYtK^1`G?MJRq51W2=6;nD%^M9w zC%Hr>U1wEb&?@%qGI)6C*AQl~Li$X0meZowFy~a}W6Ex8ns-zv1&;NtuPsM&+pv2q znaG+yb^Y+N_LXDJN1z(+oPjLgAkWsz@eU3M>+i2PZu0ih`G3EeFW1!jL}!15<8i__ z?;^LHu>1WZgT`BteyF^2k;ZX{-f6e7rIB%w#yr0rjN*df)}h(3urF?bQa!0N?()03 z32$Qzel{xY;aske$D=ev&{c`KS|!`?Jx11%nFtTLVfug{UV{NNTb28Kip~1Y#9Y6A zVb51FzF9pG6MeMJz@jh>TU)G{g;bHBv6lCxC!#5-a!P+9sjRp#hkVv_%3ygksf;4@-T&kLZiQEQDwLQjzD_X#Z6+&MrY1Q1=;l89i|`5$UkZ#O7x_h;G6TYq(@ar_1F!iIY;#G zP7AEQuAh=Smt6?JtHo4?T=9;Tgl1Yc*9qLRLzJt_^U)H&uKnojoQNhG1+K#nW?%;Q zRIGyFo|N7PGK@70)AWJ`?R#=_U;+MjG-lAaJn)se%hZhFheY{F^}Vuz^pxgCawsON zxeyqCV+7tjcnzDO9JUBL%hEHJu@B<&|GK2}(dnxyqXUXQe&AbvtgJDu0^4{@wY<^_ z8WIo(Le?6gFh|lAf5BbR^p&fq01dJ^z1cuI3SeHZX`tbqARU4{8PNHBArb5?Q6o)I z#a7CEL`hO_mbm#LP;szu(;{!}!m7A?UBQ;OLoMFAPrz~SYeKtw>e=j|-o;JeSKD(j z$r(fLM0sr2ay>)KhM!r6>1un``&DIB4?3HA90+W^lr?0Cg9eQbVEME zg)|L0mx1*R0&vDJ#ff?Al8qZ`EwF95!Wlq}^A9Tat!0Gv!Jh4kzVeiva|&kbxY|Go zau2&g5`{EKT$Wy+awwB<+|SDIkbcW{#sY_5PwDONldZmPWQMD*IyP74!e(u)f zFils78uVxZCRfrqYEnb`Y!7!*f699S%+enLla}Pelz&JTmKyeKsYQg7 zCMt)D)9VQjx>;AJDhF?q*6y7hf!f)-6%H9fw!W6@+jhqieldpC9bu)XiG6+437AeN z3W{P6C|1Z0HQ4&Ix0SNsK4?4ZdE?g_MF;0j5D0zL2y6^BUIPo54LOrjrgY2+pLlOC z(p~UbZ=E;!@Y^lH3YUatlyoxk%bULWru?1@fCqRS98M5q>+F2~g6kECwhj+H^_+HA z3^p)*auLsYbYbdeXaXhMJj$=wSUNXaOYGOY0PYyR#k^bGP&vmj4Q@M~d*T&OaLZ?O z$%_lPXX-3_CUVj_%I>gPa%^C8l7nS+fLjM^Zp4&Zj-SYdN49NG4=-JpV9Lj~%|*6h zC7i03+UKs~N?U3z>Ca|nAh<=dBo18(E$gt zHv5++*7cWV68{gca`qxRmK`y&}&9Bd!J6oC{TixB5>)V=((f>(H z)-C>nmcah+X$jTU|CyGU{$(X2zRhQ5bn2)uG_5C*B;s6HABr)fEo{2mjd_m$}z08)WyzsUR3 zf_Setelam4v&p`uy}y}Hm!W|5Gl7=An(k0kT(jlg(Ztz4b6Xx#1|wz}y4lgm+o7<{ z5H1>cmS*G=ZX*8CB42?FkYF4MAfxZOD`m5G>cYb7V(NG{UqQ}Fn@_vlp5H$(TG&6MTGhx>>7as4VL9`D3>hoY1(Z zL@Ve8zy-#yg$<~sYs+`K2GT)x12TE{0T*IZUl#tP{fVBA_oX~Wf(8zqHWIu5IFw`( z@2<|)pSE#ZFuQ8)&m3%*-0Oz6i=1^!6KePQ=~yfoUq>4WJtOM3WP$O*_x;{e)$wHN zs6{sRb<}HJ?tDc4wvQZ#vV4YKlbrA{HhSSh&i(=j-n7f`9h91@X~$n8+b6;uM7!-- z!1Wu@h%#?xuCr`wPrWCzFfSYL0_km>SIN|M(@Xr<6TgT)U9NjcaA9K;@;Z5~go#Ch zrUGgq%7DGCP0!gRx*|3-X$7U;aL4WEV85YTe|BT2k-Ww~Qf(nB5uKW<; zri`p(BE#ICX~#qP!Nx6f1LQ(Zh4>7#d@H8Nrt=m{2YOtfsoqEC+R+vA z86S8or!5aiBg@V%^faCs<44y~YYvYVoNTY`hRbWZRouR5WflU58?j;pzj-AENyvPl zk;v>$28fElmUzrC7ZnrbfotrTZl^ozz#+CWnYa6!2?alg87uZwZO_uSH(GZ5=pSt$ z&eP!@6A29>$-^Y>e0o3V7moJ`J#_YqjE{vSnz3=!Y7E82x%CtcD78qBBkJ_BjjRtx z-4v{`5@f41YIm1aJ(CKzQlFY}Jzh;f=;$1z7E5mQZUX z3k5th*FW1wQ5q^A`l|$7>r@@}_jp=VY(LcTCVI;n9wu#`zpryps2Yz`jx0&=^7B@* z85B?I8Dt6UA7PFbo*xtlOB-?>Yvn&@Fvo*o1O~DCSGe)SKl(#{C9bQc42lw1;9U%a z+8^zp8VgtAc7J&&m>uAKaNd3F795Bf3T(h>dR?Hy#7qi_ao&}!^mm&Mk!NS?Ig?TC zhZe%0;T-2Sa~3QclrMm|_rh|WzNKeoaU-ZV4{M-Q7>W&--q9_IURm`=@15AZFiNPl&6Hq25f^#yaD*cCzERTY7!ItaH_ISgknU$pcQG}tuXCq68s;ysL z(}TP!)l*Em@2xnEiXAN~%5>9T;p5Z&qP)lAuC`PwK)ghUU5=53I>I+p;w|@IP5{cf zUm5^zU1c-Gk0WSiMeH&BiKR7isg;f5qnH zm3=%#fLX5S^@zAsJNn!xc+>l|;PBJ`3o!7NJNWNl0Q%p8f%89LAe~fU_%-CT6$uwt zJsRV`skn8o^DX%w4^3PCkB7=A-GX-LX47s8w+8!sN$Gs1F4x6x*Y%q{7<3%wuJM|D zGf=S@hvR+uQ1=1YT=?z6zg8V?H2!Z_9b*2ARfpyS(2#iD_QLT$YYv7S^%tbA?L&N5 z+nw+PRfZkr1$>_5bBoZ?#L<9ncn*&Pa8}>SiyNfNUkoTZy)4b3SztiU==L4C+TSdo zm5PK-WLT;yT3NX{zn){%frIG0>sRW=CWx>cikp!`!F-#3dQus+jraJ{$CuCT3R`(H zZa!V#$!^SsWXiI)US053Pg_mQNfGepQ#*dZmBc9o$4Fq&n%9T%?}QQLW~b%u#7*;V zhxV0Rt(go)&h;q!5^}voAgZj@bAkudSC^<<#wJSK4m>|@4Y}!^`?}Cim7>Sm)#vlh zy&y=JiX6Rp^v*wAf0fzj38U7PppZ*Pag*WEwPUH1b&&h9Q1(nDt-*qgtQp5 z;@ge*ow>AWY|hFJd-V)IfGC{Cp`%!7))L}z^jCk|o(QhU7<)i7Th&r;JpNR@~#irPB>$d%6aMY}!e45lH4U)>Z~y313)xn1X&7 zJv;WtEqH;4%UD4Hw^>>fXg2r6y?KIc>fC90YBxUG0Am2s)^e0@rlaw&uKF{*+$|N% zKNBOEsB5d>XpIK~^Rcu3ez48=OTPBAQmUG^577vGmU+$GQ8xOFx=tsHT{7HLfZ{X% zvV~Xt66lp-$}ZaHBjxsDg@FuvdDb-2DWvT>2tC!+4J_ZnXCV4flEbcqR+M z-}MhO^tk~Qxd>@&IVRFrmoZh5LMBXlgfgjmIBe|`^vUqQ%QqTq(X&t4O~nU6yEa^7 zSya@+*5T_~$5VWL31x?4ML+i^`QU|PR+iV8p>Of$^L9Be2P}3CnJ+6dl<~JO&F--< zF!6}9AfJIY)lt7tI)aa&Cmp7hcVBb|#q~tv3~`4RqYBNwC%14H-DB-CMk<*$%Q%TO zI6u#;Zb#Bw)K$#)t&R++6ja`kzk9qKO;?g6x5vNRHAV9q_AK2?PV(W&>vW&Ql=PJg zRR15139|gE8`q1Z*n6zNT{FGsO6mpZq{6ut#nPMU?z(mIWlnkPPJvD3&M3dMT>aj= zz_!aR^y757;Q*0a&8J1+Qug92D^aGCm1=R5ojmD;RUtd_mWMEK0=pli3CY#jdF@r7 zLESPy?FdhDU2qUN;XMwUz9tF=An`Wbikan^JY-QABUO|>?wo-Dt#97Af2EKiW^tV2 zeemcX42q((aI@4tZhm=vXi}n~unyhO=HuV%dOr<;^t8>_p-rl*s zGZ)SHlyWTaR;XLEM`4#C7gc#JZ^YTYWZiw|jHm6!+c2L_4zpA7TId!dUu;LI4vP4O z96w<=8fVRoZPE>mnV~t zuBp%7V~u}% z$}OShRu4ys;SIIzj6^Ps`5BgO#nZ{eHEt3Ecx5;ZbJR9rH=26nee zpDTK=1Dks!W>MR6mkf<)<`sq?1DpN>pgEh|Ql^B~Z)u~3DRy18?fI2g^;=s~10SC} zE75~iUnKYcPkPVMzx1A0|Ec%9U+^l;tS*vDz8v?ns&M=hD=d15H+GNZsM{*^t8knD zxXAscZ{3_MEBMqu7XgflU;Nj14V+hkG0dF&h5hLpr3q86Kh5@8WJ5QX_gKsRygiul zN5FfmBexcbB1!6)!Rorc=8Kdet8&&ro7TtoSgma0se5Gl>kB1+y9K15jZya4sh?#b zFed(sg!zH*qMP>&=nBi)d@=^P_l1zlYPQ6c^4XK*O~VVXbn5Gq_lGBBUT>nt3+Jqa z$ywVCdC#Q+6GF^IOWJ-TJV2*vRtn%y6|pb!WS>9RWh915bMqXq(Uko3(|&dN{SAvB z|6PAVlhE43w|;N6XzN=mCcN246b!%F-ZpGcJI6_pKulcYwWI7v zT}gY8kh!yUwvpaiLC*>uBKAnaTh~vMkf`o;#$P()8aAIbOrp-BfWJMK6jltR#oa4Q zadv{`?tyQ7C7&ChwT~heu=&V_TR7TL^V+wbRBiv(@lb{6_%#h(8|?Q<+x_u5pF0tH zHMG$_Zb(pJkaZQeI8+vYM55)Uy#c?D8KRQD?rrrx{9kr6g#L@&j1V2diR8_*nRL4U ze%6;&@ITJ_%EC$!JIFG4x?2`H^Ts*Bd^P$)&f7=#a@&%8&q90ZPnd1{TZId;i{C(G z{TAB)w|SlShm|Ej%Mg-l(*MmPJq~z_nz$I|0r!7=4*Uez*BqfY6!%yR4O4A?6=xTe z|2c)=`W=FvSJQd;g(?+)`*wiL!VEO|uUSM*+`f6W?ZmN#rT3qN41dRo)-}?ih^i)S z=L6=<&g7@8`Ba6A0MktA!5#qpP5s&B*f?p4wWr{Im+H3Ciz=2)jePyf&zW_7XYmI|9`Iff zif9Myy*GJpoAL*{S4dv{22;xUSkBmSsXSqnox%X{xVMpj(MnG@#^<_=7lI2>6Tffq zsIRdT7qx_SWvo1FZ29u_cIk;g4r3lRN2NSz0VBBkqgn~EN27QL*tQ$^-zXmpN4fG% z_c_UT%Ug|K-QZ^USECELw(LE(8>&Xc8jWTSm1y->CbpsLh81a_P%Iwm`Ro;Q zfsKr7Zim7aZR0(T#iKbwfCT>GfZ5?N?u2KqTId9RevfKKsbOeguB^c7}q-9*;-n_;cMgr32zr{nd0Kwr?|!@d8pJTI{1Dy_B{>hs?-4OgJP%lQH*83FtGsowhlXUhizBhtCSEzb47xu^+n*&JH5L6I% zcx^2#=}RNcqVuwsyBSa2z&76t<0HS@79tcQwjlmQn8Qo%(NsOs&w`K|Ejx+bs z(hr*hU1Go}m9+tVRk5G}A@zencJe@fQyrpkBiJu=Q+Mkb+PfAcf9SytsY^X`Z2S%vGhp$+Sf&n zj`U^O&0Bgs2T}Z&>0UM#uQa{*GFYF|ta1Y!TaCm-yEzV$4i(-cLI~nTijm4N(DO7{ zL{y3S>gQUp7H0mY_>t1oT9i2q(`iyZJNsNLCNPxo6;%6G9FCIv2 zWUa3o>iEEF-Vkkr^eb0sOK<&TjVxO!9qRc#30i`gMfk=~HJQ-y^0jo#B~&%ArElYm z0PNqDp9+O{-$488<}vi9)40b+r3ALjg|&LzdI{oSKCoLN6+Im7j@TdY%J+fW?^ zLh}nWQj+3dsCmM@6hCG{0RlirvZ9w3*WNeNdh*{zk-*-7ks4Y~Rso%P0B>Zm8*w<(iAd?ex@vlrEs*U$Y+TLT?|Cf++ z^(C`>`to53u9G-$e3|=v2}+aK`p~EKy5j3)%c5qN@73u3Rnl7L6_>d7T6k{3q2S-N zihK1WwZfr!nuXcVUFa-)vc5dWSh>8Jeg4_|4V;ecu>x^F`2=&KAdJ@O`mBUoDq}P+ zyzDS4zA|D$7OHo5-k)jnJIWz~cHJhfJ}JOU7%3_fnsviaEZF-_zfYr=9U;`F{CrgY zMtSSIheAYCY}3Jcvb%mU1)`R)US%fD3i*aXc()~(ACYB+E)|?B6oI=8pFR^g2i)Xd zS^A~5VE2??tK6~58yAVsjLAc9K;x^kmkjaF+o3o8i(uAZPATd{s^p!BtPt zA7bbVm$S*;1Ci$$&~q~rVd1Q>LfE<31ciBf5qf+%&Ck;&dba-W2PyxR!g5g|z4qj% zGu>^+(wnu4LO|M;wBbJN-&a2>%tmKlHc-hq$}1pUpJK(n$k2-po#w;3UDVeRxc=OD zL*!B?}$F z3~`fg0P{KB9RfB0dP9yt?=dN~+#|K!BfBcM40!rW6UG~$@AY8*;vNG}r{>STiyOrG zU!qmLv2$3Y2=2eFH!F#qqiHYw8SGNtTiVwL$d9QdN} zE?2|M>}OLM24d|!y4?S#`oQ}iafc`jKAzC85gLzIOXqu*)8QyDuc|unoz!P+QP1^k zLg9gm*WUD|eKOtPc7a{dM!cQt>0+^!M6M_0)*4FhRZ}jcv%0OJveEggct^?B7D zT+Za9+ld@le+{4(nd^{-!LpZM|MbtY55lOyeE5pP9Wj;=%zD(oqDA-1Ph z)j&x&Y2s)c65R6|OVqsj@MVGV(rj{bVBfZBUY3&MaPZW5C-(fN!-*I{6RnN=XsvnW zZ!g|duE1vt(%7y>-_mi}#!B<$l%W~QPP19u)F;qTZgI=n8mQ?eI8-SzB+4@5$i0=K zZT9`P@)b#`Z=3I^-ump??%0{s@i`2GXFL>7>E^u)2o@tgB1~JJFSbcRBWl=2tUvh zl?80Ct>0M??YzSFwayGSnT!GEkF#2l1-lf79 zTjO$2ZJa1eT{gRRT+P1~sm8}*nzSDwp+El^?k^IGZ`@;XS(}&^eomrKUuJW=_zRh{ zN7*|GZ+8nnplM_>hSd!?yOItmaJrXk>7@NW_w9r=RfJEnYm#Xrru8hl^m zuAfUiOMhu5M!!wt>zWS|Pi-3_zEQ>aKw6%dzAd@OBC;i?6EeyPyG>Wl-6w0h#~NVG zuUkBXsP_jhTT6w3W0zh45mwCXPqv>yBbX6=e!-v9;~Q3IPi1HEeg2q#@Xf=7}Sg5!G%JNssDH z8iQ-O-{eru+VT9*Eyd=s!^S)#-5V*Nd%y9JN_8_oGw!&w(@GXkEJb<5OC0sHxT2S@ z=IhhDS0EzStX0YJMPJihCzYv=fHcsbl_kZUbl1NfnR_yhGvJ-p==1Wa)P%wms-e(N zmVOfjqN3&$$!eNB(K#cpzb=ur8y$UpPD`>urVlVH^?=SEy! zEiVOv32fPUIxqX!xp97#k@aV=lvsVgHuMI=f8;)V@OWRI@&u*#N=d81KqU^l>&EXk zUtHt{)R*(-_X=Rik#|%WX~#M}qte*pLyY5T(H!y8c%xn%{>-r2Y&Gix2N)K+I?$0D z%vJ!fp46x%ZlT-)dW)9p)M*E{FJh3Wu&$}w?;Wdk$?Ljk_+k9{2S?C2=u9EWFkiH< z54cyC_!cBWnC=g&49ahPZ?i6#5gn8~=NvEi95$uz+O0IDv@nc}6poFbyKL$qtUMWr zn8|`&F<` z1BA+L>vR9&4De-piFDh=7Ys|M^MebO5~fmKcz~p4t?CmAktWQ#x>G$7M#eIEi`U7c@LmBIkSZ)Tz zL+5DmA)BWki-T|FN7Qq)X&Wi^Z&@Y zHXoG}mMAbcjqM}$9MK>4osdSw+NSZORyp#{7M4s{>7#CYZzix0bCGd@4l>kTzzXQ0ewwGEEp`intL!dhqLXZ5D zvkLMhPQGsk!AmkUorzBqVB60vJia=HuUHZ6N$9!P{J~d7f;ISPB)=T-<+Jq?jcQqF zksZ>hn0dT6wj>wvQJY&8PLo?K zkHiF9?yI}YR2s4V`0-BA{^?K$7!2n>R(qi8r24r8_cgQ@gWUR0$H`_&(&CfFajT_6 z_(2>dpSvg?8j=>pkLm2vo^f}HB4K{}o&JF`%2I{Ti>UB*x{8tua!?^*Pp=9C`_p2R z&tGfVV8+S(3eqaHomX42a}Lvlg3($iURORgj;fNZn*T}DeDRN_nJB)vo^tDP@h{8` zamF zawf#iuUI;|`se0?S}whdU#uF?)wSFhO_d`>!x%zwW4T>7t-VTo1=-w|Rvh3EU1qpIJa|nqY((FRIpIhRdGTf zgKKY0zexWKHS85GrY*qIyWI@bS8SbluKZGJh7pivM5Ng^TD}PFz+(+v)x15 z1o{ED_kCtit*`3Yvg*Un&x^Kr;PX40Q-|POfUIARylXQF#;KN-M{{kJR+7_+Lfpf^ zjT#ph7pHO9(z8Wbz6TO;Qc+oz=w^V1 zOKxrqwKVP$puuTF@4o`egSMLDRV^&XCY`voWu=y;ERXH^}UF92P;_9oE z_QqD88~jGAGdG=8v#XIs^hE7k-xr=qzxQ1_^)oEY<6%TR^f@RaTcsRk!8z+>wZXJ3 z(J2m)IF7prN9s!{p0dS0&i(S~(pUse%8X-RvKsRaSR>jQ`c$6YQu51dEEh&4p!7S= zuwM<6X08L|GEz0x+0hhly({$q9NT?{;@r&shma}Hu!>XieyMg5MfvDrna4;9H$+d! zN?nnKG`*6|D!VKnzN!LO6(X3|tDp{^$Ec6Zc9-IdJiJ>)1Pv^z`As3vn4KHj-OrRA zI#7~7*Zq;g5e~P#J#Jx@O%in-PVYn9Uvml1IAF7CAlWISvm`Dl$KVEkE5l$DD`njL z*M=RQ>LcI3nC;Ew25sIwm9Ci1Q}M**M%EPrFw9s18j>GgTT4tVlbz!`7w$fu*+Czb zd_#mrpIWh%QrNzEUi9aVibrXKSc#8?GuqKc>N9^e7nMu|Q7}Be!)5sE>fwYDF${ye zN)am&k*g7hI!yYHSQRx&Q-l@3F=Vw%`dmb-W#YhYRo$$`L<#MyF%ig@fR` zp6@zhAT`%Yk=c+L!=`#%d=R=l<(V7mll+KOmZ)sHEc+NTsIX8f+~2Z}t%=q@X$bGz zc)HxwOt|g)+(ym)U*|OEl&jULVkOEJZj$^-Z+P7zRf6DKlm-^C^x(BeseJOQKdw(t zy$^hs-j;Wv`WHR!v0nH=cMpX;xrZmFKt)VLRe7zTl2j!D-zmMTqUts=t6##?`VQUS z$42O6HTjqkyj8cW0nl(vgi{E^wiltiYhKC)odA`cB$i>&qk4AQoGpf?RcvmSTM_8j z;cGkRQVKU+^IOjZF%jb&rQdpPKYa8a$V(4_qN*B(QphY9nE}RD1t0^x=7r8w4aMt0 zeP=+h?Led?+HI`LsRoHl+xBCA#O|VWaPp?3EZ_2uaK>$lWf@v81~S7woO7Efj7UdykNMgBbpVEOgw8y0gtx z)N!&SW)aZ}@7Wx!1%TlvvK%CaZqZjDkFjZt?QwsFj4}khTu+ z*wd-!h>3&+ZlZPt^)#-Xsoe2)d%{PSD$-G^{Fy}Ab(kX|Xfqi%rh5^| z^=mgln5#EB)gYs2_T<7X?wtQx*h!nhi>E)U^O=Jl!*Sz!*mkDxTxHV9rjgWCwcq)I zGw^!E;OdfqUH5~a>&D#e&fX&bU(A`sfjoTJRyE6DhqFJW!)-cVptZ-o z2?!6U^)$XEsh23S+~6Db)Hb0K4V+bTY^*8Wg`7@bk$`5L(|{Fe)^?q>W|qPn8>mKi zJBl^CGsUpJzQ>h7vJec}DPtl+GGGi_4owQnjm}Xe%6wLuK#d}n-xlc=@%Jr~ z(Db0;Nj9m60^i85U6DTqDxUJh?@D5^?tg*cO1{Tr7dx_#BO&uS^|y8Mp*S2dv#SC$ zCHdf`045*3%W*S4C3}9KHh57>H2%4eKgEsQqWgtb!^)C5GHKr`e6A!riDKTnY6Asy z#hr{Ijr9RhZjY&}4*ZCwQBTl*!|n5a*&Ky(=86hMM!7DAM2efqdn#`$bZL!6mpHXr z>0$`D{y%tT`}6+$#5&ze+HgP4Y$xf*Vzd3088KRbh=ylj}Nd`x?8 zua%1EBo`~cZLmWHd6&8xE0$}?)XjKFxCrUnmh`PngzWjFR*J02AIz7z;;Ztc$w&zb z^R?2&pvw-ZtU!f^`UtW7w!0bDJqB{iGwVM^Eu3|RM>Fq?jjsu!wOy)MDD&NIOAs7a z!mwJDQ(F?+W#PvLwxwuBlZlc>vS^s5CH3t^lqrl}v3cnyfN~ zBWXV5yfsGOqB#h5*>1cEYv0Nei^z6zt-I+=Wj1oZQzPtIbL*9|bf|;#ah1&sFnWS( zvVIbsek}lhiPW0fi;*kYxbZ`T1{rTLCkiT-miD;_9(fRCP%ZXO7K?oUVb{g=+?(WR}?X?9s5T4JhE3DreX*=;t zcy`^xzH+oPxHLwg^E)z9m(USD0M$7c;+(!C{?6lqQgKS5||m^D8)dL9zOP8Hv37*z86?se{> z7I>68&b8f+6EV4m{NP9q#>0C|GN!RzWraRPy6L7i;LjTW(V~*BIP9vK%hGj#1|_vG zql~$BUWO8z3hQxycUz|Qam{7RdJ0OMVuZYim4EEx*ZX}KrQGDcDV$x{^=bRl7ErK2 z_pF4@vBj8kxJ&0P?!mec5O;HSr4GSF=&J{Ng2L!sq%{&pjDtqEWzLK;mMex>NasV3 zY8NqkVmAsli#Y<2y8eEf^md#>k5ApHPVrDPr!*B#eq8voByjGJ#|SGOuv@+rC81!# z5lgBYxYfKBY#cNrC(l+7N`;`@SE6~o8$5F833Djkw$tN#N;prqdajSkH5=eLab!0d zrb(#wj(ri`qF+rTQ9_wa1NhMSp$p>G8ay~oXT$TXun^drE7aYiJ*EVBmawcbt+#7@Ir0heCXnS7naWr zO0%;&&pMh0$PpgR_~dT<$Y~tv%rDSZd0OeA=P*~a+IWbu!hHU{W?EYxWnJiDKP59O zk_>e(ne|R+Bnk`l@b8;_tFKu)U>lM*MRFNug5WMG&kwfS(r9)I1cfn0Dd(5C7MSUH ziG2pIW=|}1L@x8k(}cGwsP*YjHNTmxdt*T)b8J&F%~>!7t>x_*D{RAAKL1%71yn_> z<%H^!Xg}KrD`nKqSqp>WcusgHkM+ax==zLo3yLaxd7Qn=wax3lQ=2!(3cYiR4^Xp@ zcQF{(3yAn?FH9-5ttS)))&t{?z=1#9bFJgnM_9Nr24T5}+RA#&`3oG0Vx6NM3MACE zt_8ZiO2Y3;?1*dnGD-8*Z6^G20bAlE(JT!U{)#nLRE zl%%I;>NU7|wR%o34E7VosD3w)JGdoR>cm*?F;_~-$L3ysspbS&9YSxN&oHN81aR6E z0J+EF)w}Q+RHFV$mmn5z?o9rp4xE;;-#oxgcXlL3$Lsghe(;ISWv6@lhI0p_0pbWA z<*To?BsbQl#4)g1N10(Wz0aRGX4~~juat;SZ=KBhI{qF1Z0w&5bgsDHAWD&*)e!WC zYXeo9VN#8fGxNaR2Gs8IaoD=eO(+ZcP{>@J(`L*te(p$4Xp5$6d*^hIg|$kYuUB82 zJr`pEBGoP!kv^%&DqxepZmTi76jXOXsyAPYmv^?U>gz{zw)6BmHdB55v+gUZ&D^z1 zQrZ_k!3O}PEk{Zdk@nfSf+;83VA(Rc#D-su%$zq?uS<_Osm(`6YU7IQTjuR%qsj|( z)E~>Ni_|>*M%(-&6XNoMQHi8?vR}rS!$>N0-JPU=@%xwIQ1Y9+IqCYKA0^empcD0U z_3Vf602kqglP9H_8deHq9NbUC`iI^bu=E?h$V)8}-NitQ5S?31@adM?3F)q3na0kC zY($-LMoP7}HAX9`rGwgCqW4%#A8X=+ZZ((sm{a#PZz!vTGSe;AQpIV-_q>66jd} zLrpX*+heXXMiPr-6AIGVC)Uj4vx&Msk&snGKiXlPF+@W_5q2U223n*U-0bg0XD6Ol zuXcH>v_tL8LP@jHhuA6-u(dT8{0#xY^ky#_Qob$UkjC$v;~K8{9Af$HOH!4P)DVE6 zc798}yyGG|{dOg_%|LB&YLUdTy5!m>hFRVUz(v=Vby27uI%K5)+8RQ|8JN}xkf`+j z>XCPKKJa7Jtz0tT3e#1L;M!x#<$M@RR@iW(If?j&&@@adl`a?LlzFu`kvEd02mn5u zrXHJyNuZ$b)V(;q?~U=@wcZKcV=0-smknNRUu0rrV&jUCI^gUwsEnhtOG<6tJpnaC%vC(A za9}I>=q*@)JRbJPSU#rB!<1;{+^xoenrl~9xWh@=;amRV~J{8O;w)1FB8*sF#WbOIeNx*BC=X=E^!7U;CRHM|g;WtWG z)lD^n-2x3HSdTS(zue5m%k}LETe~(L;EZd353DKGC#Q=4D0`7$C~ctaImMGWvMx9J z)NpD&t?59y*+r(kS(nFKSm^lC1|1t0I4m)}6)Yazv&in0z~^$&)jQN!I6rD=mia<0 zEtGaH<{NAn&$g%v5-u5V0BgoqFU=`Ux!N-OGDHSYIoQ8qSf5e!dag5J} zG{6k#I_|!Y24Li!Rjl};#)LPIc_`8pLLH9T{q|kWN?NP%5B<3lmbIFJ?8oL90%jkD zYPQ*>$@mBkNcLHTS;bEz!5avo6RXyRvgi|f`^Rv~lGf0&vUglmPsno<>xrCEjr7c4 z?&;nSO*zC&b*MUCdKBkp8yV|4zcLJf7d-TBSnf2um%7Z zEgk-?ADb_w-kX*45_p!n3lTn>=C<^e2fHW-6w|nq`k>`#x#Tt>B4R>FW-dA-bc|_* zC5RMGe&pY7HxGe?PcUZ~9D+W&nV8mew(%U)x`g(r4!dCVY*oICO(*?1o_pa)Sz4u; zT-tT1?D2;A9*d*3JwmwpE7_t5-Y~YwN$Me@bjd3+*DV

_yX09TLyL(Mj%AZC%>BfZ7b+44w-b2R(py{+T z)88h&t{F=X17b?Y!h&u+%#KehRPeIfud3J>$qx<82eI=Qz$(re2mXErW zYTLj=eSlZzHwHOSQ!IjTApi;~6l~zbZ2tbXRIy`7GTqD{d1Wjjv!+@hTEK)qRcRi) z)JVMVnh5lzyK%lt>1-s}FKrFG<@x-jaC9vLLunUvI&R9H)JGVH5Or(piiSriuezdu z3CPiLyRJ@ZJ|C%SHhyOxl@2@nikdB(EsbtUe0ERi2f0{4n7hlPZLgwaBf%^sPf8dy zZSOKi^_Z2P-onqASLvPVqu*Wh_Y@5f`?w#?6Q#HU1Eqp3l`#Qsfw4b)WD7=fJa$g2 zR~lPNjb<}eu3zRbk4krm+DA+Tr#9@DQ#3v5J_qpYzNzJjja&a-kx0B#Fx5%t_3yTFtG!R^tY?djaXt{2@e&G| z+UVh;jL)%BOAPw@D@|iMLz2;ijs9~w9-D0CzIJ?WJ&l)8@i@$uhGik8p2zFKCjWOc z>oIU%taASTL~1^*<<{sRk5)CX#9Oh#u}1NI`mXNc^V?3kO;kqo)41(B=IA8Kp?Oc% z^^hmkHEOos`aXF+&U$oHeVY9zhJrnTW=p9uW66+#jMZBezhMjK%ioTj>IJgXQBcgp z;+V7i?bFJ4+)?=(Z-0T~THVH)2%lrP2OdZxG~RE~x!jXkq@cgPrNx+CyoJq5LLjs`+b;&F`e z>$^vg$QlqppeGLUw-82ka`TK$PMHoP4nF#eD3)&~^A_fr3_-eslz>%Bsp$b)=8?gyZ5HI z4I9(8>bdVu5&6va!TX2&8zLWPZGYfu???p2Fda>et!k|}he-{UoIGyyzgLz{02f$J&p7BUX90R=}BwKiWFlWQgM4&WQElrgP(>fOCiX^U~! zjg>M4b2CSG;rPWYhFg24b2d|M*3gsrgF!{fvllo4LBzN~=!&Stj9z>ZFvA(>Qid+@ zO9LOCABym;{j=oiWqS@dLjscQ5?9>S^TY7R)CzzkD>6S^LpN+{1i8v)mzt(c%=q`!y6JDMDx_7cLz5x{Zft9V(Pa&OZCqhf-sH3JU^;wIu)xROhUj+*iGC~fFdT;N~zCjbNrtYC}Zpdb;3WPCP=S*zOb`NII|bS zKMe*aq9teKSk<#N3qMSZ<20+(G#eWtL>UIGCxK+A$QKJnPxkdvJ8K0PyWsipc1iY3 z(1FMc*N-Qg*?|&tv@Iz1g^*9#`{s?&TsG0_(R)WpUbVpkg{;rDC)uXxo-Lf+UDo)I z={pW?$x5>x2*pp~lhLdy)1LXN*Tpu@!qmC1eO1Lw;e(;~SnMqpX@fqW@1D$w#v>GT zB*o58_@3t3&oTXF2HA>j-WRAWkYfi@0-Fed%?ylvKc=47(lC}`D&RXW>OZ-q_S;Ij zG;Yq>X#Sj!!jbRxI>OzebW|IV^kN$dKE-7}p3d}oa0Gay1hmQrjk#_K+1Db+qltp7 z8bD87H_wM=IyNp$MQGb2t68X1bA`ifSR|Jb6`>kHyDiyF^&gLvTrRfrrQW+}E=~LF znutbD{a#9qM4J(5w`BURbw+p;wk#1eHhfB?aNXAqxo$j;jQwSs-oqjD4P7i4wOhiJ zYYU|L8K?g;?acL{qJ7)bd2wjjkN8Vgz+|tEV%N(xOjaAe-ELm}^tc;T7N!0C3)&~` zU-3fxd%WQP5ihd;B3^S_(nhGS=Os#mEH+(sCPw@gOa3;;yq*y>KuZ`YF+|k0nfjN# zk=y)Oj0jAbd_kqW$j6nxPDFm5tAMbhb)ii*ma8&q+$EKNGs0*&}?@-m`<1x%(iLS(&qlICQCmS%Xn{6FozRa9KT)-Kvu z5+t}g0fIK}5Ih7L0t5)w4FuN)8Yj5B1Sfd#5S+#(f#4ck8f!d2qd|fl_TInVaqhX} zjx)x2I&W(|tWn>ZHSMdKvx*_Uoi*aOwOM?CMWODiLz&d{s3Uv&KKrllIM^=BHU7?= zO=x^u0L#e*;B^fD{-|WdfuShQ_W;1=cmNpIUVC5ASJ>M02dB6AX>4TXuPL*~pMCuk z#?I(Z4^J2p?afWFTYq*<2)$VF^TiV$Webk@qZvBE=LFa9{;qVi5Z58a959nx^3H;4DXw=svV9JlE z(CXpL;`kr^6zZ!#n`Judzb=R+oec!hIss* zh&2;Yr)=ub0%dtD+ZlhndH0>)CKu*9p`botTh>4$ZfvB;l%h;?H zruQo{w_QgpX)4$&r8}2}ruQ6B<5~l@)9*Y}mY3#&*WgYePDZ?bx)CB(1~2|~Cd$9+ zQg?ZP^<#3-w-U2!IeXHTZW8X;uU>urxW5=?E$`D;C5Tg-(kgN|D)`O7D>^IuGisJA zbz92Mee-m2QTTTNv^vLq&l*1(E;9LhA_gg<`v}~a->KT9AZjf80q|42f}V%gQLUur zfVGL0--4+UrK${*IxQ-7@x@Ppu4sSp^v-!2Z=Izx0@S#o@T7CUT70BcK2|ms@$YkT z42+CKEh(Vf%gq%lgZqw8*{bB&|3B_}{=bj^TaRcgH{yJ`Lj<6Zr5c)R%-n)o7?z4d7{6H>l^gPzs# zsl_MIl`RTS#cTvZ5OMMr9!n$u);!Yfv*ugc%R}RE2ezlOaI@MgYf|qP6TGmoBp1)s zY!ml#IAEg=y`UE!&l722Xk6pjW>Qtr-s1+MLy|-dRa9rRwI-xUq@d%#K0O6 zu#RY!0ha~U5f#(HgW|qy=s&O8P*K4oR2ITqK1>|)tsExEBp8_jI#&^&=at?Z<$wE? z@0n{-c7T!_9DoR#iQ- z+$Tv~kX>~%K%14Rzyh#tN|~Jm2V;D`<`D2mqDBJ%kutSuo)fFn<2=4ggZ?0IWVs#R z7+&RoHY4BFN$HUbEAY@MFRf1*DPvk}>1#+zGS~KT)_?d045_Pv?hrzl7Y~1RTE>fx zr`$wAOD?Mb@}58y>asxL=|qW%zKH5L6#A82hlRAvh#GU6SiloxJ20FDu?FF;r63CZ zg1=`E)!b;FcCVafnpLfkPfJ8<#H6K6j7CfT!SS zgOsV*k7Cp*_%*PpieejjDdT7Sj%H81n%)Mc6O9D7@YenEh8MZyzFG!p+iFLtuVKWT z6`aEC{_DAN=h#2z@DQT@{>2Rs?LdYW25+BVGXX~v7zV^*vem@F z!6cMr+*jDWy_>lHU)@fv<6(3wQ8#{bcAX2w`!X)6;X)&P6)_2Xe_?g2Jv}>E_6c zVbGwq!p5J*MrI3iEg*tkSf@NyBE6c~q%P_2rIjW(95fsZ5lM})or8l*Z4}M6rQM~< z?gK#eBg1m)RF@~cHCOwoEtAKNY;rr}eI3w~{~+Nr-oH z?fcJ0hg`4gNWBJ~Rbp2BBO3rCVG^lQ8)1$j)Jn@gn4c4~MU0K96&E9GHEaJcwUR>++ zeySP5KQr1g{#yM3@I{cK(=~Ux5vfHZp8{toW~?YiQ>Us%QEV5-`dhBnjJr`VxOS=E zIUI4Jx-|asPI?EZojd@bbB2^J^UV6Y(@F2XtKV)o7NodKBdQNL?ui4kY^dI!^BDzL zm=IAwW(UPv6ucUSj;P+zlPVgsER%7#&S%`t)J;H@u|nV2hA+r_esciHKEuW?NKvAf z5>sq4kC)*?sc*(|y$?RiZ1%g=esxoH4T`=Sb>VSgm4@4#F0Di^Vv58C8QP=-zr|qv z6H-?n)ZWxRN0qVNH@>KD{T>?T<;G7ELJ@` z)*k-beOTvdhNdVr-0I)ls$sQm<%=%4zs5i-9~CXHvcMoj*xm+)T_7X3{1{0yd9CRR zUll~^=byN?Z5452(8f(Ah;^1bIMd9fhYQRSJJ-+S%g6j|1bpFg0508O)UaMBD3K|6?(o6D#+4_ekq z*u?TXH!3=vyIT>+4_!*0_7K~l7;QuZ_1h}e>dHNFR=5P)rJ$aq!*!6&L&UJ*@k6N#j(Dc zFw!!Ju$P_@Ig2>CCq3d_T!sx)>vHqO4vS2sdr&A-5O_53{hjE8`iqh z{yT4-vACQ3%ur+wXr!w{E^*gZpI6^_ z6HyPR5y3D za~$kGOK&*xgUB(X3RutYj6ne@~;%w}^~XG)S86t8SbH0fIu|9Hvky#kv2l~}4(nuJ5;AQZf=soxuq zv9SN$Z!TKuEdxI+i(l#e`u>j)ZySit&!w#0gfY|zYXgTInrbwiR?4rf_A0H*U`=dt z@qmLz7uKB{clj>Oqe7;H2X7I&`~aX@X1*L8+aHP@yAH`Xy{NFaodHek;-@@i+z_mL z07Tf6DMy7IHNn z;d$-_MKUuUUCoKPY%F7Klk=w9n`xA={ahd;ED%e(c;nYVM}8Keh0|_mpASG+%&T+Ax3jy+XeR#=R#`ourc`2lGCG8dFI`kFSJZqyUG%LOS5sMHH-M;oeZfiB@eP260>k2Ne)GA% zm^XZP%f7=MBc>)E0WGVZmjo(zYPPhtmXMGVm(~9UcRwpL7WaO zSuuu2>P6x$LwSu7?^>4~-Els&PWV!B85UFK2cLa*ot2k=8ff~ZzU)IPU3vh1cK!YB zy>*ssjMU+)0f+fVK^#zWu{l?_;!bm$kni3)-ci3CC<_yYi+3u-2P4e5PC=S}8~dZ98AD6k>X898G1G58KmE z_e7%~0KqG;yYFTUqvI2QWkhtORcQ}=kOF%VuAG08^mq7>z1``m5_CPsM|ze_c*}~L ztj%c`%Wfj61A-=oi%={_U<1+7`?4WX_5TcVt;cZ-!1OdJ44(DgDuSp;nB}B`hGGaV zp{fFTMs^Cl)`;1FPOjauYAA5K0a|6)`mK!H{l?Q;#u|#e@$8<>u7kgAU%x-vvv>2g zbaQ#%l^fhB*`t!7JI4UZRG!w<55HABhINnQNEvM9^avCUt1Fq?TsBo{T8(5e zT?uT|?WrpBEvdyHqz*Q*)_3%)sJ73L{?VlKiN_ylPwTmU>e1IOvF4*o*1k^f&(yAx z=hxD;!hK?@0=uA6sPM+x;ug>@lRZw&44q;+Or7=2^pW-*zJce|<4JvHMgujYpE#pdGe?)eIdd_uo7gZ9xqDgmk%>lz2w@ z-X96D`TaGo;>)RB(VKFc^9*^9AHrrkST#^Z>6}I$b*5jp469;Ebqd>)_PbEfG*ef# zZolODoiRqPi;T~{`@I6v#^UD@G zdl#YbiSQJPR;jRJWt)HNT?e#Oaoyv3_g|t#28hZiaDPRO#sf|_qVa(KqYy;%vYu6) z*|Uo_zq&c8H%IXTiwtRq4g)T{N`gL+Do??9sk_Rv_joT{S8v2`B%MnOJEkpDzmD(4 zgotE$7V)P}%J^oZ+RH|cGQ<;j?HU_%bSm)!_vFm8U~&tLse7JHl~ z)3R=BQkqPKTAmepdk~kx!{+T4G1**ZQ{ptxEdX;!!~SdhfczVii22hfiQq`#_Wh2M!3A z{Et-mP%Lus-AYN}t068Y`MQq@!CRB{+ zXz)=%)jE5@cA3U7*gNP^Apm;g_`d9YO|U!5b^FL~;^ceu+%Ykt`Y;}z;wa^}#n-SL z=mlwnJShf#&{v8AY(p(i#-{>W8sF8yMwn2NRQ+su8ITg$bfS82Ok+m%c! zE}O+F;IG~#1K=oU@LJ^jzM9ipao6Nya=g2zA~Ck=Uz8o>w(pCA(_VVX_JH*RJ59YC+C9Of`$5clL$Q#b5)BXN$C=6nFi-Rm0G z^CB2pS5=TtxQ&JuZ@iy{@yR2f(pr@0ebk z*VY}?t=94A{mlKwUBCGi!^P1g-F^oG`T#ibXoR9xJLdu_)bkBw=)DW$>&(OOTr<6G zeb1#?>i-J1yhVK**m8AzXW+W)#00I-T{iSpk#L;0krfiqT-^;BA9t5V`9rTB0LyHJ zcO-iWZuLHwux(eLCYj8U%`++AjwMg`DdPrdjS0{0fUs)B+^9XkFLQSs1nxTWMVZK4 zW;Nc=8HemT7aSW7jyL1Ix^9WaIBUuDF3(u#k2dLRDU3xmr=8w!US^)+W~WUf5u0@h zUc*d|Vp>zCz)~2tG9A0`=SnmgAF_MW=28^8=MIfKUSavgR)DF-aq{hw>`-+<@Io6= zO)f`+e!VuSQO(ROSr*|(f?uLkga}7qPhwjV0}54!DLHI_ZQSiq7U(7<5XJTY=uUkA zAP61+&1Ke^HL$SmZE2+coO!J&{R`e}YiJn#7V#PW65Y;xCqD;wX)0^u7GG)sHgx(> zU!Unue2yoE@IBs@@Q6S0wtAyF(riEO*dpd*p<)j)cL_Jx_sau7NF}})`K_?W^bTRR}BBIq*HBT593gyD^0#RRk%G9$~9s8shtZ)eHK!VPU*ydAmBL7&f} zR6v1Tu5U$?74SYu`F(Ku%knrknYZm9$5_WRi;T~=nB zJ<>X|>V;RhC%R${r0V4OoAN>V`KUh$cJvKTLlkStOzn)kWiJaWV~S|iVc-H*%o_?%pE@$l%$hy)2YKhHs30mn`>jEA!c{Rvor;W7<{IcX*iawDTma;dh&nzO) z&fwgV&}<4f;nr`9jFrnwTc|y(eYCT8E2c3tL|Uib@3LI9_vFdbsnw@30hF@8g%&YI zH#Y93t7snpKOQHFA5;+ZpVWjk&!(D)!kAXfsd?2wH`B#Yzg1ygiFP3UwXFZ-Z5i=2 z;sOC8Ed~|~kP_oyvk*4yDR37-_uQ- zfPvH+n4|#_!M|!!_8Jo34F1JLcCEp)1Dq)%&Rox>WAzBq9{?`dlv`Eo=fK&MUEi8| z$SXSAxD__FEyK?yFC-1)&4-uZ&!!#UVZ5vSKq?yTRgM&;w35n3v{_4Yno|rneVN>v zoO|WbPlCnDNtBq8-5@e{9)WA449cFdAWJGt-fT5!+4{?JBMw8k`=nn=qGAAMN0VbW zE7x?(<+YtT!%iM3r6Vt)8ShPWWLPa(n`NC4+ znMFq}^CMv>b&Y-`40h@%m<}WHqbO!qyBh`~bJT?IdssToI`tuTW6coqb%=z7h~P^h zE4G4+BSt%gI3`X+F_+QMJ7#iLl>Am7#}K5fcI!fTWU0#37;3cBj#SNe2IY(A`PjVtK#B>r~v{nN3;jPWnaL>UCaaE4v5ZW4)+umq#=Zv#GG~?#iHu?;;GL; zl^)W^+D{~-8yik@H%k?P$QBpr=zPdxM^+qJER*Q!!G|`qIM$lWt`owY@j74gsGtpcSF) zmrJaZY9%k=Wc{*spvm*gq>BZk8K#;AP3<5*42z&}-BCQ^!n&jNskDIAypb~-A}3$l z6NA45r*$)##%p)8e>DjC%}~ZEDB4a7Zvt2E>~#03w!@_c`!1u8Hg9GIoNNz!;ji4n zM=!%$-T^BT7p;_|Vn|po^f}Rb8z&1I)5%H7pYbrV2jV2*=bLRV_vqbz+o%YqsFDtA zg@*`|uS!3Cu|q9j{bp;xL*^C7%y#0L6aT2K|EsSG_7g<;R9pl>-z;J4{S6W~Ju5VQ z_wnELASRwYdZb2}T3f@v_L_wq0Z+Vr`)RQk-LVUTH9QKAMes@1KiRAL3b@07c*1mx zxFaY$vsBnjrTd&obLNap>%AX(g^R*y-N>6Z+UdNciIw?nQo@|xm32N&zTA0Ycuw_t zz}nc{)T-Wu%M04qVs6(v>#%md>Mbh2^vmocr=TlQCvzN-ShU*lb2$wTdiX{@#>;?6 zyw;K1$?u%q;@UYbr>$Erxev$v20)gxi1?Kq8f{!o7(8Oh5F%#-Wj2x}GU1XG z70d&kIpW)Q^{WfFNpB(NTzDaQ5G5HHCCPaprWr}Wf#dRjs`N% z*BmTG+y(W>g$Ywi>{}Iuap_q|)en7NBmH{IfYxlObK4VrCvdkJ1pN7i3kot^fDs`v zj~L_MF+F2_EjN;Jt6@-V23RF0DiFjyQ0{718w24a^IJ~yfh)ndX&+J#+z9_vM<5k(P_*PXfI?1-i7Hnd;i zH-}ZiTOsN(fQcVn7iES}J^H672g6}?+@*&u+^1`;XB>vePDfZKPs0~s`C$!-1uZv8 zT0`FyxhL-T+|vJr2K?950X?XmAv*rwyw|}_uO5|i6;ahhmfgqybY3EYbeqqWVMVOq zlw$i95Q}d*(}HDobE&x3`vfj(#AC`jM)8vZmoy7LxxKlk2lRF&{5`u9C;5(_J2aK6 z5D<)pt^8N%F+oUsa-D0&!^kb2@~F_GH>sC716$DZ)UR_gsZB2Mt;;IoLtn6{O^!z( z=MG#!qTbPy^y-p>VZ=c;o5V4}I(CfS%4MO6;|Zzl=QcV_rmf2eoth@}G$Gliii|9# z$-{N_j}B2p%&HY}CP-}rle&@S&9aXY*<&0?d2y+q5I%eQ2ewR`xQAu;4iFkloKl1? zcq?cK^)MFmYK^dJ><#Qm;!}gesZtukr0?n!#wFxsu^c5f;(^9?hSP=REE7Yt=ErXm zysCcUbvPki2|vWLS4jCd9B__2EdiHGPp6v@=h&!O7W2Muc(Of68%nnfQ2vp+whNueJU&yWJ^B(fbKLwa;_W=Y&@6`>F!ei561GcVFmcLK7Fj`>t;{Q_%v)9oWLY z-Q^>AkumDjaQO~10*}tL=Kk;{mnzyAW@YnsiA3@vAZ9Vm;9`>Ogf8BhP}M>Od~&%v zE{U#li-+5%L^O!lRjs|~g*H0vT!?xR9eLnBP#kU;cUWL-i)qm#MquGYp79h|>6Oe> zPre>;42NHn@Vn}NzKo;_?nx-;dl88Z-7IFcWCs_>ExUojN73G+bH9mPp>!r75&0%c zKw)%(6}%Pd^sK|6y4gj6-?1hSq`WwtP7QmTUy-u@Y!NhXX?TT&_sJyE5%a2`cD;N) zIs9HwaPl$ON6<@{ulvmMx^=z!qm1oto3~;vFho4m6v|OdY^aF_lWAo!UOpSR7wZLs{e*kMU>*_gLhAJ%!a zcJJ6cA&^$~VOih}^vm zFycqndzMhE(VDyW_XW^+`;KAcJffvv^3s3Xb`X`bkv_O})v~&B;U4xXRbjkG0+mV-z0{G;UN;Q-(Hn;}|H-M$0h)i&)ULgbLCe+u41| z>s(P71pba@fwv2q*QA(t2YOdp$h>Ck)okdrKvePKs~^U;u%I)k>(3^~l}(8B;}!D?RAzyOU~t^ zMc%-|2|M%}=#12(SQTJsEZhdtBu$oYFlhM}D#c2PK1x3OK;!FmNz>$-bSa?|g{@lW z{ft*4*R2J|1js5!yZj_lLoTUNQsS%v*9?Es!84jkw)G1S)Ti{Elg_qg)8Flfn}#=< z1+&r%vE-WS-7w~_Dw>oKl~4V8)~OXS9ONTLAx>8TPmpa8@1ayy57J7npg(XrqIUvd zJJl!!dFk(U5z&O}i+T7ncnvP}G(NO^@x&QU2vsv0UC|@*%Z&>B#h>%FW+2{tI4en( zce?Sf6n66IA(EDjqefN`Wi6$TR-I~uBmK$6v*B+E!`EJpn|Hade_#BrA}+4wh{(nJ z3Brp&Xz7N%PSbf5KdkfXD?+@ijwH_qz~?tuNzOdLy2X-(ntR4J)1qDvQT~=16KJ{P z7Z5F{LRR{#bD{>8Mq(TlgwC@)DIcp6^!1%k$ZNCA2+LY%udcUufLVlPH)x0TRh9!x|GR(H~~d{rHxqiKS$Jz zun%ab_kPKJcq;hS<3Bj&;7z6%E{|8;faswlP)|}sxQ54ru1%vp z%IL>nVp>MiOMPEf8}A0?mE6i^VP>5q8;d}Ff?8?Idj2U%25aEgqYz*^u5b94H}#!} z3WTP7iBcl*U!SyA@`(-g_AjYqcX)wG{AP|P<8e^^r=hfqoyN>VAEmzW^9+Ud$?MeI z{dj@P$pliKPq%0+&T)T+^OzJS355d_bw`+YY(8XeIjG!gQl1kP8B^LVN?j7aKY z4twifK*F3*E>*4tV<624s$V<({Hcdv#Fk78r)wJZVqz<0E%#Mta-a)au+*;zv+j2e z&EAy8?n!iYy=WODZ~V8_l%~_PYoERG%Aj?QZzU_k;wqpLZ?d!|))pLRT>haSXqeHy z6;OD5#$S12;slmA6+y7AfTOj@&tej|xl92rLGyt{spw)Rgv+rpok-jH^zd7!4>e#b z<@k&%<=DZPqy<%WmJe zobued%yR#@2aQEf=J>WCkVEY4q#PG4=+ zl?!OP1o(?!-)`1Hya0Z3QE3==$>CNV4N@I%yaH%iVG&x{qB9iMZv8dhHBJz9M($e zW=JOL18YZvbn*j>gOx#%)Vu#E^C-{KFe@b{Fk*uHjeLVgKq28%0*WfGo1Md03K@-y zI=Yj{Zg(cEpIC%wT5^ad-1-U6Xh|$1uqo{=Gb5Wupdyl=cqwb&K}@elJi}U-lr5bk zGIl{alcZ@W7-8YF9U$!nix66W*jhWV_a3uzv#k;L?3$PU57s%Na*8>LeEn zN};)=##hAgg`@){IV;6MX&JJkt6?caz3`NL3g*+fP>a>kE*Dm{WYP3!%Gf`9nqANr zz*$7>)k%A3hP(L$iGvuxaDVH&_|kY#Xn0p z$#Xwqj1I!g71^2J69&c5SN&3_@FHKYe^Gps{C#D|m6^!pZqPq-h4t*FeIVy@FTT0k zqu<-)?Ud2Va~%l`exq2bGqavcT5uv|9@!}?5*+GNLfUXiR?!YpGr(zX8CUp6uzW2c zQIq#H&`}GHX|Qc$6^}XSi|ablKHT}2;rYV#s|zRhk8ij>pHeyPIutl^>Cwsia!A;h zPoUdag7nSc)hFU@keEX zG@(QuQFEa4ld$%r*{aiF{^h!=5mNBi+R}$X@a3=zJ?m^y(#A`4ge|*zCGf7eceffH z)W>bR4E5Z#6a~-E%_rALrjTG!6F#=9{t2*V8U92}xWs###wcx1y zk|nAN#h47DeE`Huk8osztX>UE2u#s0expoUcM797`npH<=XEp4B0M&ANHs>A`n9U^ z^Dh!fI^Wskk!eq;R^#XyVsMsPT#j7g zoM8NoO#cd|2JkuEdU@Cxc@_2#kKVTSiv;hF3w^uCZ8Z2?J z-~vJa%Fl2qEAXGLM{xLP3goeQ1q}OCQM9j{sNaS#9DUo$X7-cf#bH3X*EOr5EL>W$#5bIW*KxMP*^&;Uh}U*q=3=uKSsjQ<=MkGa zOEjbwp~ea)w!Ch>PTB&_b4H8XjgzO*4*DB1f?U+=w#$zi!SA=d=a@VM_Pweeb??ib zuOZJF&{B^^Q!sk=w3r}S_TQ_?oUWhe=$A&s&eiUa;{@4ddH3AywDG&y_P?mkqnh7e zNt<09i}Y5ssYPNKDdh*vHRm2a8}sLO#=~nJf$#@c&MvvHS4^odn5tU-kzV2zATEBz zI-LSdtdmui2>o-0`K(u#9sjP!iI(cR`?d$gMflfoB*y2M*%YC`EpIyAQw zVJ66K2^T9G0fB}zv6(oi_w(s>1YL+UzvoL_;?Zhsph#-ZZ+nL;lo*;3RU)1aRq&7T zXCtf;^p?n?;&emZyI&J%oXql7xr%6P|4*0+c^bXEC|u45Ky;PNR2k13N4Be>M`=0M zytLxpP1}dIO1>2~t7`*hY2`sRh=A{M{iZV|Er4~q69?EDP47a&HA(WYFMh&Q!}#D? zxHs9~DH0TxHol+7Ez~2eSw54@C*&=qMo){g`wYg|GQO&#}-wA4K zB#@#CUm9|OW^VV5Ndlu)_9Y2)G<8q&Z2(g2oi5C zn0?c_xBRQgaaGv9`YrknTK>y4J&#A|X_Vv(|A5}x8N1`3ZI%MDMr@wZgS(UhI@$bJ ztbSf8Man;|Fr;cp?aisB)k3xdy}MU-_^|S($gc@sG22GK5+oRe;mmn-D}TM6m_0Um z72vXT_$d@joyHsBDzN#1a7H8hiAjs8{ZGkhk>Uc7Y5#^)M3!n0Cny>x5e-d6!oGms zjnDm_OKfVChws(!?c@Qa?gC1+^O9HYb<((Chl_ajm@8_()Kh7>&27eTe@eDxf89Jj zduN?|CX(C09sh?%Ba#YF)r0P?uN>+@T! z`?b32tFIe(62Y7DW01>HslUAfC+e0PxRrA`&RNoAEjOX*Yl}WpL5}>`rP(G-pWxWf zR4yy?i9Mnzd98VCE9Zc1QpdAq^MybCx58Y^$bQpkO&0TQoP4wOZfGVhD$6ei5RxXB zv=Z$o>{iMAQzf7NyGojEIv^8bAXCUy(uETx%O<;!T`upY?k0nuY57epy}$&T|NL9*t`}Yg1z$4gTqLSb4gp&Qc@} z&644ydgug+>dw@O>P_%a7qTtk{5MrgZ*$hh13*TstQK6;Dg1FJ;$Wg>d3!lLRfGjx z@~5uBvoAXl$*=_sE$@(>FJ_M~vY~hd;kyX6mcgEX;%{U*OZCH(2HJOgxHspdS=|2D z1eRu?rDc#bDKFA52Pnz`wO#}GT@!a^-OX}e2%24I>(63+CEFqNG(PREETxH#SF|cD zG=so;<1~jtCga|Aex>)pPG-RCHXGB=SREUjh8MfFJp$=$&2jmvZ;i?s$u zX`^MGi@7fh3#D$#1w018mcI(-iSrx_Da0(%x;8}~A<_#P_h;*KVts|~5M1US^!_TP zjqdcdHn08&hQV_PPa}Vs|9sLKCx>qQuOSWoeMkoByl4{y`TGX|86u!m6M{s%J$V4+ zW$Wly&V#8t?0PP2AgD9P9#9rBaO&fNq2z|TGK}Cfty^cM@cX~yDpW;x^=@p8gQvdo zS|Q?vy4mOp649th6t|KYA`0XzvL9r(4Fm}MjLNtkR^|4 z9M#p_wO?LN9`VD+{ALDHhjjY}Eu_y1ItFmILLFxelcW>I<9&8`IL6zjep01JJBsRc za5<;lwUTvjZyqWB@KCK5#!9CsiG`19X{8inpD}UFff!x}$+BZ#pY2^0pIu_52K4GN z>`e>8{_%eIeaqzJeg9u~tWgY!Hm&C3u~;Al?q8*uAj!%fBzMfgxy_3^lJF*?0dU8m zPo~szFSWZiG{^Uq{HAmEXa9LU zQ&E8-c>8vS~ue3*U>}ogKpKcfNxN`%q_0E)ho5^45(}r@hOkfu!kB z2koS6*%^l-I!#}ey@H9LtWP-M*w%@3CE3c(XMx)3x=bH>MP^x^nzlu^-R`W_q#0T^ zf11vGTU<7v%2<$}L#)#wb&eq_p)p>HO#ctzQZSJVk8t~Cit1Lk#KiMI;b`HfF%L?~pM-dWG-b7B^Ap`>K+^RJn4Kd$kMUHH4S)*Kz^Nj5n8?2Q|3W)|DfM*-G*xsKzzNHR8~9WNT-C`TjZBs$L{%={eP6>?09B* zQ0vTpa?F|?`n5{!q7WI7(nwtLhaQVV(Vbbg#mp#11}j_pGC=aoy)}sXDV1Mo%XLpb zv3?Jmvo6th5{Kr1Uv~>PMc7p!6KPCu+?A58#*i;7n$(P5vUA$yOfEDhM2lQMBZw}V zMI;Zmd59YO5=2-Ayp$BL@QgB2(k3^w!8+;0f6>7lAmxdtMo*2VDVU8)4&7^(O;;WC z#Q(Xl?6N)*dHTiqi$)Ld+266|^aDL~#XWnEd*hTSr(x4=WA{I-KP8X@ ze!Y$>*v6sz(?lU(VKR$E*|+*@lvM5+&E{C(%EtX3y^@@|?zG{piv{nLV$es`a`q)A zi@-#8?EUR$qhlDs^|%a{@R=o)k$LPR$JOZ9d1GbZ=p^UYM_N?=mZMK6m6VJLhlA~{ zR`T!1Utaz18Ijd?P>xYKL~BQhJSOap+3tJJ>{?7jk+b$34P@srgo@*Oc2v8vWi=P7 zf0f7Yq%Uw`()|AauZIfr_WJh&-~#9$UY#Lx^ZoMqUbQ>JrDV%x)zPxd*6DR#$Lft8 zRSRJE!~f)K);Aasm-`R`kJUpHRR3~9VZh;P;Z3#Mk<5u_6Y5B&W6HYPID}0HsR|$F zKP%*U@^n~@&V8um2tt|6^T)oI^;*5xfjeVB%UobXGJA`?c`4{MFojMF8HAgNAO61p zJ-Jrj;B(GsX*mUyHuvB6V~u3!yj*oN`bUKkU9KK)n`BkalE-0>(O=ssEkW17lh?T> zUo>99ME zQwfX071Aeu$!#>PT3{NEPwq@Hv-_$3GfvrdDp7M|s=7hP>nl)GXO&6LfWPz)wQ5BX zF|JrT_OCBez1)WIVmKsN$iWaHZ*Q0rrCSB(gY^2UzCJh}?B*~TaDvA%tC2=G$?tWY z38v$!IEDwXy-IAe3GEGd6UL#o6l}~-(BKuFHEeyqBEHE#q)yszxYCE>isy`shF;Wv zQ%jqC)90qYUVRx1BNZP+qUw^_mLs+xWXpLg86K6)VVvat-0x0H?vgX1*K|7jO-ix6 zCS=Iugx4+Z`iV?xpYcXr<5j-iP`FjR#?F=g4u2E9QH;@nvL>NP118nWwh-P=Av zWPQQmFYA!M)$b5LlJCAJCf!~#P9Rk~mg{Pcke0_H( z>+2&5w|d}JuTk&LK|BzJqv-dVA0GBsbRuS81R^ zW_JydN&~}i3mrnpk~k@`G|aUGtw|Zr|2vFZX|{?zP^aTk5+wC2HH7WvUvq9#n9o>e zOxp2*FBwync5?FWKb1dQ^~YJ!SPlqS8#;txtBh80^8?Jpii2ui3wy^<)Yob=%|K?Y z#WU!?`XqA%kcG*llK#^P++(+rw+0J;kl8Kk{k?+%z8yWdZ8|Yd8~;86R@M0Plrnl? zdnN%5j7`P1g)xsFlCBs|k=_~L0qbB{HM&gl< zcC{T&x|@Sda|O%pa{mx6k-rAh<@VRnW%UZS5;PYYsM0JV3$BShPnZ;D=%<|ovJ_20Xbx8yzq{; zqg-r#0XPRN1AA+{r_X7D@Kg?|zi(^UpD>jeXzh`5?uYL|sha$`d{>LPqOg2{6r8k4 z0+jai{h{J?l5tLHlg;8UX*%|OdHuo}7om_k9D}(gs@h27c=Zog2wJ*otxQ;A1Ib8)#j|mB zKlYr7hU(8Wi0AP`=;HWoLBh4n;aZF^%v1B|{r^Qt1MlbTEA_o4bF*1V*EOeNZKWOs z?i8q(-SnEX_dlW=>bf=hgK`pfEHETi$LP^h^^`qHsdlU(fN4?9vc)lKubSF95pgyY zdhKJVt<6fP>;$?ko|oS8HlXr$+g4PgoD)zpl&@>C9p_!p@YHD3UKBFlIj|v(q7)Bj zRQhCqzsw*kP^QO9Tr$1L$eC)DX8Bk7yl%8y*c2+2r&etBEVpNtudk7Pa$JUBj}WEu z*h5zuPa7&7fuUhZ*@Phs({L4^e{R_Rewm&$*x=^!_0A?(2DTf8*Hl;TTMWS+>4)xY zw_zQPQg>-dNhd{`;9d^=?W@~M@KbT65MT}GsCo3157vsXQFzQ$!DD^!Y-b}Cfn~HiZiq`9YCw-wVL|{D)m_}lv%u%`{md{&m4>f1_(rg2P z|Lnr@e>5Vj6ycHn_0C~^mjh+NEW-^n#ZA<+$)K-O@7;{SxYu5x1* zD+VG;s7lx@p9vI`1U5r#Z}=&z6%1tIWsgXcQ_JF;?uGpeA<;O3Zg(}uh5MuuXx~x| z>|X4)ph|mY(35mR@zX)bYzgn`PZi&Pik|4CDnNCuyytN=V^P8zBvNEYUn2wQHKW{X zD)#$rx$LQOBp(EwK{0!gfN6ByPrD^AJK8h;7Le%mNLI64ABubST#jj8OA#Lo7mUm< z^S(nuNAu13+Ui(-+)LYDRW-Uzhw7e(lkZ@ddo#_^=oU+Ac4}+JTVM!GXVsZ4md+Xi zIfonz_ve%X4d(AFVs08-aq}rjW0eK+nw0KD82$0GPttMgi;r%=hZ*p~T}eL)tTU?p zLXUxkLUZor4Mm4HJyP1!P5$a|qjut$>md@v9aeCm_tf9nSqx@FtcI?vkK{gm$U>BV z5Ee-KYUDkVft6s>fl3o7H|88Z%o6g-3~#tIn9#(oGv}Dz^Fx%z8Sd z>%Uhx)9pH7(kRNdq_A2fj zo%g`A183sDH{6YC8(Hr%dIZ{hW_Y0=sbI_~BbU0u7s%VgH^G35@}tWWsk)y{n6*OvpcUZ8?Ak4@mK|R$*eTyjNVWMMD>8{j9GcQ_MrYI2{jd#F$?d$6E=Gn5M3YsKf0=bsfmaJvtYJuDjuBo)T^_)ZJh(jGw)d&KNseySCPW0SZ^{?Xr zRzojmGZz^wbZ(plQ)&I!#h74NHq&Rt3^p_PO4*#5K`Vsh18S4qjDRvb22|+?J+Sz{ z1A#nrsu~SEg*or?p{DOrUsfv35QRQkTy8C!F-A=zhUgD;5DNX3YSv`80UQCUd} zR#3UMpV9br|Ja-(VLMicPAWo5uGZlm8$2%J>t~W-V|)GRsCREq`cTd%<+tbLJb*)r zsVn#oRQc+wf_p2FU7f@6qp~Y%i`}Z3KWn-aeRJ)TVMO=RWfb2?fW(zT#u)Im{f4v|u7)IT8FoLcuDB=Ni(Vu+-lghDZvu?8r%iTRaiwRk z;;4V}DHW0ek!DQ|j}C_G9MnX!6F=tev4t5$Kz|z_}~T zS_#rOYFG^kUd1DqR1NKm%)SpHd5(~Q>tfwoURevL)z zw)l@(U*3(I>{eMC&w`dTtGe{HNPV?@>Bl)*ko%fo`3*(am5j~N=4sUq&6Ps5c~~dq zY|uwrRIJQ|Tn$LQ0%McS$ayC!uOtEGDiXSbL}? zWW{gULB7Lw58tP`k!6;xiD`mPSkP_w6ycai^@Wcb(rU}vk4%>)IC9e+*^RonF9JT! zFg9!gYcpc2>EgXQzg!P*MLBgju^n#$!$ZdiSwSN_WP3^ceW^yIUd#B3Tvok zv>j8!&WXc!e-6VCqxwR$qRDCqE|=?vrR9Od*3cx;ts6S)Yr?-wg@$X_lLLd0Xk2W1 zS3Ns=yy~)epaJ-BelVDms^wAj(iShgY77VguXIILD^aX2rGplD-GOTfO~UD29QVT} zf6Ew6KKUxIsKQM1O-SEmEYnvAdJhKw305q*@TSYv)v!dPPfmB6tKz^mz|+fdkhtY& zh1S*Upf1J%Z!9^j-5qh%E}B~(S-Hb~`kui%UD0mGuE4?P9wI5C4$L59&Ac`=%w^wR zb+pAgE;vAE$1ib@ReEac;B0(~LIt&p;ipA;s(Z6u#tPmom(=;$z8x3H++`S7IuFZF zi+!97(QcjS@EU9z`%dr8rT z!I#bO`DNJkqQFM7fnl7NswD_hY6vGY;j<^vnFF%C#J)qS-=-~p8JH_{g4&PW?)TgS zC~}MYsV#9u<|tfocNV}nDFYeeZB<=ex%FLgYGu^7_GgfpX)wZV%k#$4$CpSwo z3jU0_JiJ6c2(xHWU~f* zNExP?lx}|sZ3R_@yO#dEQ<|o+9!(k7_Hy=Wd7_X4d{@?q6?N2JU4q4s9>-jWk{3lB zE}N|#tv*f&ENXI6JSV<*OBwdF3u~Fhc{=ZKd7wfT^g%}5w!_vH3!0``PM*9+Z@3By zy&kKxdx>@fZdT#egM{T2Xc=DfPjfZnGS)69C5O~4tktT!+tyD$IgPWn)zQ`rsI7NqCrV6t z{Eu5*ayiwtT*(^qZmk=)7 z9M?4Db4^K+43gC{R3Q#Srm}hZpJ?+)%MWl2!nfO#+^L2qVk2VlyEJgQt)F6>{$U+@ z+$+5~4AxGF)-7#HjgV*i_**zt?9~P;okx!N@HQ$^&1Hloo(X?|j^nI7YN_GEfzCkq zh2h`}YdQ~Ax?Ar~1eXCcb1+DPz1TQToqc03h9>C0a4uVChK%?Ai8It2I?!sZxO zullFTAGWeb9!!*M>JcDkk?ck8HHqyMaCN`Fc|~u1hjL5)0GeF+wRb-QDWTQKMX|eW5n&W{O$Ba?L)+?5lB98B&q(}Zw0T6&ba^S_z??e;tM35;1E|# zr6C@$dxkb-QDZ3vzyCMg@vE)UG=6UvEZ!022;S1tJh$Jx2m${YCKz$)8&P@Y#8uRL;{hgF~72!hRggpE^icfXe>kE+_ zlF4gCJ$bLT$d0WXXVWn8i7W(2WKsiILUdG-aNzhuKCvVPNHvLki{Iq9a1J5;6~PC7 z9cb7FQY+2)M|`=jIETO2GT~)$Dno*2u%pJGK@9Zw9s61$$|&q8tSMBID4f|6 z>bl0N6OlhQaHX!`3G-PBGx5Y-5f2m?B)N9-8Ti5fT8iXA&k;gn62Y$)RI84bEgRNl z#2m|a@;%ee3DWlQAS0-jW#Z4k4Ux~so)mZ>(Vt=B)hNCNIBF561CZ=#J!(0vBd@cQ zTJmD-?^(J$-q^yG0YbH0i9NR^cPAnlme32y&zSuj#yIJSOSBW5O9Dn}=JS;l0O}rN zzyloL0Jj19794LAi*s;!9@)~#CWIZX$z&5(gcIkO=aZS> zikjjkTJlv#J6}r#KBO%LfIW&Ma!)5fK>i0q!G~W-r2`x!s-JP;c^H%}MEi-1e+{Y$ z$JGnP*K%3FCo-sylr6klNHWjMpOlOPtx7CB&(K zswhcyC}L1mJSI`D7j3miN8*SB!8ZV6;2+we!HxUelt*|_vAODX4zHY%wv z{Bryfka}bnE{NH#dEFnr96PsiCk1DhU zW|}pV16651zw;0;k~pbH7bOJAF?@8vnjj)FF`6&Tr#v?n6C}0hZ;?u&U!eytH{Yq}CooMwcUhIg4;r};41e}@mz74gT{i>|t zrXlsN;p>WfAqHsGJ%V!GLy|R{iXMx${ChHg-CyarBr_-&$OkOBuBmurV3dw zI@|;jK2gIA5y20}teVohM{j(hhrb0Bbh%5`1#zG{X-GM4O1JIYx z@5zl$DVEc>uh!s?(WL>9Ki}l16*xh#Yv9fYOPM&q6%~tw3qK)%Q6@+;>rukdu8AY^ zrp2<&JuKklwMVKs#zgL=w099jJu8VYd+$15p7z_*qoQE1%h4RZv>wRrUTveccKC3m z@hX;1DisJqOM2eAp<26&_fJFEA~{72`DrX(Efz8RB`TgO>f%=;jF@16T*ao}sQ~q( zR75^W2)cMleH!0;WT_VnMoQ2ImM@)N=d&F{40={h{2M_mq2%FFMY?2 z$ihmwjigL5$GG2O&JY4>3&5Y^hOW!@gLVtJ%-J3Yb~O*LtT(EDjAkSU#0!JFovG=D zg`mu(tfJ$`s#!)?i)PouuzA)6%cI%lINaRhr$n+8Cw=EtQ^wKnKL^eY~*yntv9oX18|8xkkNrt^r^RO_l@dJhfit&H{B4Zh@RgZTp zq%Z-d{Ir_;GZo>C6dY!ImQXlO$NCT;P>4^TbSKC zsB^H!;b_E`p)YT$UvKXrrpDk?hjs0aN%d*+4wrY3ZIy|}I!Ud}$<)gFmktNlWO*bm zOyQDn5c%Nu^i6qUo7l#pGI-e_UyYHOR>ie!1VnssoS^DSunLuD!l=gxR+l)V{3T(9 z`B}tzCBBCL@E5lZLONX91m3*-#a9l@{x6279w9v-g?w_kOP_+G#I(Ho|Po@cia-&V<2`-VW8EZIVkATRid%oaE+nrI$WKKFlx_xcknI4bPB8 zQu66ED~OA9dfoJH9e;4CCJG*Wri*13N;kKfkIku2Jef3?k-D+~AU}|G-7*HgWJY<4 z$QpAZAYzZ{F8O;*=+7O=_PBX>Oqa$F(Rb;IWcpQZGYa)tl1Gz;XzwcQFSOiE8}+Iu zx=Tvr1eE@Ds9QC3sf+$e9B)fI9-V~s*c~6oSCvd!>M^T$RI4t>*QqAP=A4Sv2H85c ziIO1Z#ZKGD0qZq+^CzpI6*1VK0OwttAd`CE{BuhfV63iQD_Y*`TnS9(4ZWq{)jou4qW1bL4?5>;2Q+|%#hX(yNF z?W}?><1JilW>wj2$3bVBgBFqwIb8%zSf_qX@Sd(2|!uDd?+Al>`uK-1{7tPPzbM6a?qvM2p%dvhA> z_V`mjD-k!#c9f0SsJ=|;k1J;;kk8??`ksky@nB{Y%^6x?*EyP`D@W}WpM2pmuy&C9 zsj%7sTmoC2Ids*GQyVTAm2lr82vu(mKvxjz=J_Ww#(z$@;&|-$LP<=kkR4ISi8wJW zdC($;a`x83|Cal_2+g#7=VEX2z(I5wB1A}2%gMaEA#zTj zTdo^MG1alcB|SVJifi>(xUga)BF4~h>VbQlt*3%NcVgw#*ZR7NACX7Cmtha6v}~~I z_xA7NnF-MTp>f)4b0*bN)nGmd?KWE;m8r!nk?+>iEH+7G>Tgzftafs`%0J9XFC;k8 zcbdk3wso~t&Q8!1a96kl65E0|4OUJ3Z%SH_`JgY^%tux1#94_|X@g#Rg2N|wU}yJV z(cjUh$Cyp)F#m1!^!li&`yC(LKQH7f!UPo?98~hub~0n!iX6gRGB1y>=ZG}EHc~cx09CBbK;w+ z5{=-Ge)Ws$pcn2#?@jm#@jbj*J~t~?*bi@#*D4AEnn7`9Cy$ayt{axhChHcH>VF#~ z7R_0vID9C?@W+T1LArHGuf^YoJ}OJ!(|DY{$iZRMZ2<6`4G{|LJ-)x56r*K)i}mi` zNf-S#k3zsB%wHjz+_T@u!N2_|P-vGHr<5WCGbX)ZL|rD*1By3NGPXRX2YoYJ>_tur zNx%`*9>Q-GYAdRr3fNFf}(-CUVP8G~0R0F2`NoZyeR5-^cV<>sngKs}M=z zLE2z8u};Nm=j$WYxcDRPPj%t-uwefOxZ*2cMp8eKnn~v2rvXKqGgJMEG4Tmj(FIZf zGyplQZ~O2E1oX${GZ6vW%~A=v7~8ucq2`WBrjX@%&Cr9^C5n~t%e@fk^fU>XXe?L1 z-f7hwSCtdb@MW!>?&I1#`Pg^dhY8?S`V)cXDu?0(5BuP920*CcThHbX9>0g9*xUML zG~LtxI|~rcHiS*uc9`L6i>3N^-iy3%1FOG9{iGA7Lg}JlI^>bYg;^*Y>k(vIw;a$G z%*XI(sb;qTqtt^BxRG*h_FOZ9lWMWQA9mv>l_TLx5a9i2oTIHj*jsCc-G z2;lqQwrd*}eUe<>B%I%dqB65=Akv!3f^EqEoF2EXkx+c?@;|;(d@`}6DnFin`Z!x4 zk#{AYea5!?K;gB*w#hX8{L3Szk9*ZeFG@e$-|=f8!d8sfkH8chT@YLr_h!P2+-y zzCY2L7-b$<%~|@mHh9tnQhf98Phu2GD8xpVFP3(2s_T^0!VfN6I4nX-BiT98{YI^0 z(nmsI-tLv{Z4}HCZiI-mYEfEdcLQ~XPterIpLjLC3e>@A5kq1uT`NTy zQBOj27D6ytcs&l^OT>*3vM}_0+5myb94*yb0z(yvJ+4aKq>&Oj(W49&vgXg%6tZU1I~b-#A%x!& zdZ$A~gnIqiCG$Z!F97E`?dX`Mm0{>Gd?ppQKvO0W7>zIZnWvBqI6)As`iPJ}y?RxK zj9YY-s;dw3ZI6z_=kutFUaT2|?%E=Fu%K1rcQI+4PK!ld%#d^=ZixW?dAr#kN!2LD zqew*E4UO;g5>AH1BU}~oCY%~Y-Beq0py&tIoXab=W;Yt;CL1-M5u!HGQV8@~R~N@+ zSdZD`s&RNC9B5p>!6nJ;`hL`VytrH8MggAu@y1=)v_`N;wUs%mK#$|Fv zJKsXg)x9pE|iBrodiB^_ujcT%v zmevu?#0TUT<`|BteaM+X4~EY&)WPA6I1W~1B8{rLI*}PRbjs~}L_gIL@NkdViL3s) zsJ1BF0z6 z1bLef8ZMukv=VGrF_EwN7Y5I3R&^~bShO+t(Wvk}hmybA0EBOpGqPNc7IJ-}@cz3^ z@~<^2oIH6>s8A1X1y5SbI1*u^Ed`;`M1GJ-D0AzQTtw8^tKHU8h_H2Ty(}{!`Ws)4 zV)*WhCzNb4U0i;+)<24(=^efK`pTpOjXC!4SLD_iv~fX~8=rjuLPO2wv=(|u&p>&Z z)XF;g&DE3^snC8!lXrgk&+)bLAJ`eL)fgt=iU7%CG^n=|z+3h}5{%q1-$UkL#TzLf zzn^uKxwMp$hatp90CSB)Z4hdM{?iWCudr7OH`MT?#B={f5SAvra{7w6-VVu)>U?&8 zF=9Z6v;JcKxB04wS`{cnXqQT<3Abop%96tX-CeqwEy@ zuMw!)xtoAZoXo=a*?i>pT6s=ks88n8nfzaMxdu-v20yZ~el-vf5HOwuw{}7)PepS0 z!(QnkAxKYH`vx?sLTwLH>#6YL^DieJd0_>+T%_VmJS)Rv{EqCR zao|a!jtxNk3C=k2P#W>24tf4^Sj35uD!lmqq&zAr?fr9ZePu)0Z+~@d_5hnWkcWzi z;BbN&iD64!bc~ZNMwsWB__u1*E>*$~147stAhCw7+)ryPr~YV}9l0sj{jzmgoO=-( z33>T>_G8ZnQ#`0>a#)_Jo|DqLdr%ZLM8ln3ytk>~ppR`7FC9bWFnmiHZ^FsfQq?*m zg#M~j_V4LQeANUHD+x*ZuyF6D;v4^d_YL_&dG8i?A;^Tg-BW2U&9JnlGSA%=Q^f)+ ze;S!+65Mm8wWWfAWP3q;(V-XY1YDWleV!b%!OX(A2ABN@KYy`5Z0>=we2%3)6MpP= zgXEtQmpEz5R(&8z#7AiK3sDkLr6QPDXRA@b)aMrBTZN_R5Fn-UwuC zD*5W(%lW;@3H8na4>Q32E2}`Y=V`uJ@-(srUMY?UM$t(dR;*YPP{UDt*J=ClF(uHr zgi5B;&QBxYxq00#D0J(02nRzR<`&2Jr7-PYnx&sglTx-ekuVGk|&!B!9g=ZMy}ti+vr!kx!2TZ4hi8KgqN#RR?9nC*GFA#Z)tcHOCU`!4kK zA|q`9?|M9+z+b_EsG{+>vJ{IqAui?w|LnSHMX=?6#8*33aILhl8s~ay1>_Rb!rhkDJB3o=F~s zQkzhsTxOctMnToWPB8b|lyYNSh5f<^_8gwbe>@G^fy7w)RffLX1t#Rmq7tbK05_;A zW;jD=>1nfpxzyEpf}VN4EH~^|RU|+4ACn^E;HfxMpk|ha;-|rw2itQ*vu~Z?XrV7Zbs0Vre{OGzbhSVqo{v5> z^d?@O;4#(WWnXGTo4*i?$5k!GpR&qkw$8=bpyIp6V`P<%G{@`M5VdoMn|{IVA7kDL zEr=kD7i|(uxRJgF(^2(shB6b2njLN2ltU34N`E)u02Y71>5*YLRi|!|E_!>;{=zb7 zpXz_eF3)3Gj*K{(w;@h}>!9qR^oEpRXy6HyQ$E{5LgbPexCx$38(7Z&7D4Rfhw^}bH%9T zr}@xuN^oOAbAFdMsb>{d6;GX?1AcP#=9$pt?ym_$vYjtVXn8!Y0+QZtS6b0n@|{;D$VA z1<_RJ{HdI}5KnhbiM(MMut*xQpQ^HmNu zW!1Jhc!geoQR)&$f|8zCkje;p(jlDmeInav6$rohX}jYSH=f&j8Ir>1qZfQ?Nmz|)kK|7AdW&2e2HKtef_7WnM<&1ADIkIe-Uw8E``cN_nYLD0upC#9 zVK}d5?fc{>YKGoM>j2*A>tS>F%^j%d@@ZfEH?&yF`Iyd%rk0K=0XJ-OgXa(V6J+_C zD2$`IGus<~{a#==0l|?6huDO;TV(P-L=Oh{kM0Q)nNI$dNVM(^7go~|;rdKcS5-0f zO3|RoK(q>PasbzaG{JVmw}F_CDC$q$zVqx*=fd7^REhZq81QNRq}psftMz;@RZz#u z64H}T^e-pYeG6W>t}10YZ~_XqA@jEbHY`QCGrTgD)Jp%Wd#{^$ zZ9Pu7)$frPEH{`A2nem4H)w4tnyJ!t5goYy2}1)Jg-DIs+xLUVs?;lVacCyp$(cAd zY{*3(diW77WC_v2msOHd z6rLT-YFy=(Wi`Jb%OY0hl~r6}&G&njv4X2ekdc)2k62Ar_;BX&`E}v)_c|xyf9<>v z=WK>q$Adtz*i(oY{l&5fE;%-T=h3X>WuS=U;79UzLo2-_?5m;*ebXsV%d*I)-_0lR zOligs0B?k65ppdG1X3I=h3A}awZ;iI6W_Yba+yKmnV%cp_qwZ-SRk1L~OU6$uuxji|q;G)1?X{Vh#IVQ;Qj6w)# zYq~-nxTJNw{{h-f*@LkRLLpazIO8nh_>^X<<(DiIuS!2pMY_iU69C%lZXGdf?;q`} zLv4aTfUG8e-oDIKDe!c3WMkFnw`Sh83tD@4;PsiJ>v%LKrM4yzQuPC&Ah1(cACX*- z6laQIyzn%)z*;=q`kW4Lqbj>2+GVU{gr7`>O;1L3KhvsUZb-wiu41TWY z$Ky}^qs^l3`~Q+(;IK~DSCaYbM}chJrN;tA4CBI~7_L)uv{i{v3!uAGrJ97CGnszr zB3!01NroY%H5R}_s!|Bjq|Y(Cv|=1oQ&ly#i(sZ(JHHAVr#8{va2Cv%OgH7$&)B^> zs{6Sgr2tGDty|p@Pm8Ov$51zD^2zALzbbW_AXHN@D}I{f@mJnygs=8r?UY|a1P1?^ zW>_FZ;w#g*_a(ye7Z7NJkkXy^pPp<)Kko?5fgN;kqDL zRkMWTN5JP3x0}=?cGV@!{Rcq}|UL+t~c@f|&@Xzxfjc-x22dv@<03(&Am; z$VVKQ`s`2kKGtu&Tql=^G}u$0hj;q12)~(<_n-xEO~LrMDKxFF6G(0~pGgT*>$&0h zq`B(@VAg&kb3!*db6QGY(sd=d1>n|3Puf)swIyy+pi{CECBqx&!Ub%f{(A{I=>19+FiH~evVFa~BS&O!|JiGg#?|nJ z>7Nlww6!sjzVo4+J-W1!ADX0+oBaB2``zP~E!5Xz7UdaXAO!A!Cp?2zKLs}7V;w8`N|Zb6(<4Vu`Eis_Zbpd z=7w4EXE_LsNx_q9hh>jkwni`hnMs!@pfd9)Rf>x%lNUXQ_LlHtQ?y@n`}Z*O^;qKG z@RwoQ_A=p@&*bt6hB{1Z=?T$`O$>xbDIG=2JtS>uAgbBsUKhzbH#O1vs?s_V#!uDK zr!F7sfqhD2ykdNJ7^YPi0`pfZUC?Yw9 zZg28*l&^m66j;CP^dv9#2st{uQHNpt82{wEak#6ooDxKp*pV z*|bZ~Hsf=A4e5|b;O&0^1;-8Z*aaB|3qx#(BEqS{`i+I)I^pCx}NGDhw!zJS7@Pp7hg7AVW9a-Mpj9rbNzgte=+VmeBjF2&ocARY{8 z|6m0E%!O1s99SkCqE+gvbr&v^*gy5CiX@)sWNmEImp7G35Hey?Uh@A8@VI1x(woNZ zh#iRslVVbki0HCio>bbs(JSUBhgt{BUzcR&v>YUa1asas9XW?`zRf_P3Ggx5!H5Q zTyfJ>a}K>)=r!-k&HvWJV$Nb>hlD$U-H3cD^7!09G`+f1%z|Z3&64#JES8fd4-C8VC9#iS5hX+lxCT zS~vaQC^j;y3v}r`9D(U}%NEU#S4b*T9vo`-m_s*W!M266nhn~F=51e^+Atmrnzy54Dp91Jz^uKCg9o_FMI^T_ix>`JE%EAb5bKlL7L19jQ+s9lv z{Lz=_^UB%;ab@$CSH(cP1l;!D zu!e}_hg2E_N(q798wOUf2E~pnD#|fe>E=!%8XTwSa_WcvKQiezpFw1C-fBLi!Zc#V zQziXogq<9Z#wzpU*k~8!XSB%-Nt=bYrA}#eHogGJu*I)m!#%cOWq!CjR7cg4J~}sn z7pqnfMy%jD^rCya9bx|lBrAF zyRYW=Ck(%#|2tnNLR}8m9zGmb462BkfAN7p zFRTfKM}&p#H+}k1Ffv^t=qKX$!NM@Yu256x7Z{r_`taVJI!&;P0J$Gd<~uN&^nh3R zK3vf8!3p=0HSvGFEqpBQoZRs{`=0+z@kqOe4~c^}C8J z*#|HeYO%dLFjr^coM|(EySM)zt6vvZZ;VRk{B|O*oZ5vi^LYr##6Os7hc&bZyWXI| z4zi`&d|Alt4UUe*-VH@h-VwKm0fe>hqau0jDjGe_J51t)UI{N+0KXiWR@wu?9K_r9 z235MIw->w)k9+>P6fKSiSaY7=3x58D&`-Tlyjy0e;($;c%-A2f)1}*M_CZX+4LOBJ z^?)X3P8dc6!jlrOpo>f~_IVh5n6yw9esPwbCemV|xsGG2d#7IDEPkb4V0>F5+o)=> zRyFSx^ZoP!8zs4}NR)HRm7S67h#jo3a*Cl1+s@%6UWu|vzsR|>sx$JyVEM&E_=-M& zQt|m!+NPQ8WGu6bGHbE(<3BSTlO0NVaZ3L9pIqm=&9UA{XDTnaLMy@EF5mx(2E#x& zymC`8=gwVZnCQ8?cgYJ=@4MeiR*Gr2B2eyK!569eqS=mY4QBF)#%%z&l+mnM|GKk6 z%)#~WFmpCulvU%f@XXc~aKBz70bL^h?X^xyMXK<}o6BEYgMq#3qfF%2SdtXdj|NNU z2(k{Ahc0yH=@!2(x>j~Q?$$NVk85I6l|%;WoGZlxc{1jBOS^2>e~x-3!*QcWAB#DdA9`t&YVGyTqZWlp*{<)0`$h$GnkJHv?s_RE zcA!cF)*c6Z4StB3n_pM!vpmf(V;fgLjDNR=lSlUUc>%Je!T{5)J>$-Yc#pmtI{+pJ>cabKQ$4GggpA(qFGMVb+A;DHp zyv>b=+@P}q?B>x`oY?C^g!P`}a)o42Vb^hs(kfPuZyz#IRj-j;HS82S4?}hk$++kK> z^^0vdF;y;M2b&&?K~^Sx)c(sJ`o0XbfV{V}x^JsI^KT%KxLIL;4QE%`1`oFK*#wP4 z?HKn&-mR}&(@(K9kr8h3J*VmGry?80Mo1+i8(Am~I)+_gU$f{*&R*k+-s{rYZ=YQ| zONw@c0E*X2GoZlPe?Hj0gx%2LUL5I^kJS%vALFe{JS%QomhT&-!$}FX{wW~} zksb&&c6HL|YMSn|;0;crKtgduIKpSrolqwITYUBMam})Yy?nh#1Cvb7 zV{>ef&Uf~716Lst@WO*wzrw{A_hV?+mmI}|;?YaR=bI2>4M;;) zNRim6iwU4$DXiBA*OYHbckK`3>#v`6O3uZed9Z^RvM3v|!-?q9Q2gWg9yEK2cKCu+ zNo2ai--=SF1)tqa+XZ!(&ll=RJSo9fE(h;-HR)ZHWHXC0j-`)_%YT#O{VvI_O`hUe zgs*%rX0&1E-{jw9-q(1iMV>J+fUL&%f*UdWXC8T8I}@Esu=zw`STG!NC&p$+qL|~` z0DY9O!H!xN>qhG95>NAQ*e8LDBqzPdF9TZgds1!HO|&_#18jzRm}LcX8Ac?qt8v5P z6P#t*w0H4m)4sfZ8@f*8YvTMr&iTlsUB?d_IaWfYiKa(Gx*L)EXBJZeULJ1@RLNo% z&(R03Id-ES-;hia#6QP?q2RLjs;thgZDj1Gfj&S-F z5)A^~OcwjX!mB@Zr2R0y@7pj6KAuRS^s2l4v1OCELn6u$!hey$rCmH;<#}okvQA?) zgEO&lfSwdcq+x8+S463W$-rx037dX#JeuWkr-EAV$Z7W^IgK_bywcBdjkG;Jf=hUA zzYZ7Oc}U&JjgG557@cqPeofaM@fUXH6Mg%P`KLK|^SQ;_U?T#mk_I`4$^EFd``qdY z$0*~6pz|JTemXk^BU{=SP2we?zc(d8SZx6z8yO-T_1`8y$%F zVvVbLNc^k33I+tR0Vg0qzpLei(OS>x#J(tozo5%`-ns)&x5B!eWuiieE+cQbMzqX%R2LGYVRyd?ERl1 zW9ED3GH|HOc|Cady$ZHVLTxyf)H<)nWaR&`&G+^cI@rx-&Ukjh+{t!wo;@_PE&l$u zdF7vUdlsNl3>d{~rp}WJ+Fse(XQBV!S%8#-(7z?>_}^}BS1GgJ5LJel2Pv}__6CL1 zZe&!nb^vnZpTw=g&xMkLLs3(4mF0UE=eyP*G|gr2Nx67YTvn>u%q~aM{j14y{|9hD zkH6V)Y+W1ugZ}e6OFsdvzjprr{H3oM`fuvzq);WH zr_eh9S3dd&n~P68wF6Pxg4U;y4*P1*eN(!topltM0P7u7e@k)%5$9;v zA|#o@u(ykyi!WoiadA@*laH}TzF$P`^WXd*esX+@;?l*m6N?Z#8v}LG0|5NWM?aV% ze_85(Uwq>G{+*m({#lg_-l@{$)Xvwx3}i!qL5a@NR=jZJ!}VL%KJm?8{D;32$TI}5 z>b&FgCs(rJv$aqiyJQHRXKxmS%smtxP|HDRGmYG%%qN82B>b<#H66Q~j1{f1fG!r;Oo`aPX%iZ5^Z}AC&7!c~I(YG!rnKhsOU5;9o+@lcL#P&?=K^ zFt`AQ3jj93a30WoOvaZayX`o>;<3A}ZqhNL0>!Dzfkqk1%DA?`RF;2IoU$CQrMR0{aAeBDG5NT?d|t*ChygPVea9# zp?TXW)E15)9epc#e3ZVw<2in-U1KJWAvl9l3R{=fG2GqR%C@eZXN>(Uz@7zg0nn+X zKd(lh#1T_cr8M*g1N#*){9ACbAX+mgkq*0BsV;!$HS}d@;}=9+zB-M#MWI)gr`$*C zTw}wbwDr-X%sV#%C^0akkG6h=>WP|fP|AHU2|dc(XrSgo&}KyCFn;-!`R;r8+Gmb3leX)pd%V@(J|oP$AQ(A`DS>uzQJ?mDvc zQ_$Hn&;9(5KX2%;EkQ1Jm^yh&E+IM!O6yoU$CQ;1?QP#^BNmaJ_6cpRwta>Yq0LRmRS= zh%QgqzVW2$)fGd^^eFw{NYe!XYbqVy%Nxx#(e9wJb^_7D5rFahxLxbL7mLOxOj>Jj z21v#c3l5cK7z_p&c6T?^LH`A$$!8c7UtqGf{@g$PZ^t{HRKGIe_-w>wI}{vOJ5!yp zd?VilJ-hh$lNYs+O;)R4K$i7&rn(y0xom3_FMjv~CVR2TV3XgaHO3OHjkXb0Qml z08#XtU;U{cq5PB?Ws-0WlFR8#^)}u%gZJ?@;$M0CLkWQMqkp!xR2f{dD7NPRQe+Ilse(^|kokF1`#nrQu+>p~bdo-jZPS!|`gS*LlLwHg2Q~1Hw70uj zyY)n~dB@#o-F7E zBN+W$B@uktdRY;nE2t{<6uE8$(0E$1&*EFMhX7O^+r}@H-WUh)+qcOF%42E5ciGbz z-<43gc1K*RVi3xTyj=Ard5YkZr`*n`a}&KWK1DBOpx{vZVZ$v#NPMBh*uD0PPdxR8 z?Aq10>tyhr=52Szt-J2W%mc57=A)k)PKN-B%ftM)%2TZ|A4@c)L^GDSaOEoc-QA6> zzxzBG`&q`=bC!O-n&GhH=c|=I)t;vTH)D?a&mC^0&O>=k4d0Y}ni`fTUB>+>+j^XMm?H8!W*~U3DIojjgll!JhA`FnOXx%1F>MJ3y!9gxYkdQ42L_zB)QC$ z`ctm;m%jQ_KQ!L$<2VSmM9wymmHRNhHcdFTNvNDOnDpXGM10%mu5Ifo6!mu>oZnP~gu zvC*;dvdQC;*~G`j%aw4J_2{BgE;HGnO@0@DUm{$_HPJ5X%GeK`4j%-=84bNuzvVb; zD{F}7kL0m6Q~5KVz$m`z1E)%DDG_moEK?XHgPmkJd;wYdF>vvvzx=7ccG)1mO9y3r zAfRn%%(Bs>#9W`uW$?w7Dt))btPuJxn$$j4iNih_%lOmkN9cIkA%{%VK%xfNkW-NcRJxdF} zCXCUJCot3+t8t7*BoK3f%iB8`CWGgtPX7Rn#_xaS@4REv!j~$yX_7Kcg1(8Wj7Oni zlFf&6*yW^a|FOF(`#g}jPDB3kwJBi=y)J{PuIxC}x+0WuTy{!HUMO_R*FHL?iP(fg zwW%?f`tH+*Z;U89x6!f104h(a&AMcC>BA>8bUOTD2zip#8))D62IukJ2TVxlWPtH^cQwmBPiY|28co5`k^-$r;9@U9 zFU>ZREPGZ6@x?mBIfERgzPjRwNq*lohF)M}@#4{XWA!*1C+-BVHINMkfZlJaM{iMU?yY9u9Xl`h#^Q zqhD(Zv0mV53g96!n&_A&hBCfw@^H~G>5?KpwT~2h-?eMJ72rEmr@ZZc-FH5%ygXpj z6;<~>8GQW8yvp@HIZQY%yRZc)ip`kHDK=>1RRyOErZ%>IRgu+(XOqX(#@4<(E);r{ z_)?^8<2!~}4+dud{B=1q6W4AzhW0(LgAg&a%Am3#@&)1kv)W2)43)-8JH|{T5ebe< z-9Gwh`lU$l{}JHlp80`CyOzG26{oU z|HSj%l&@_t4ZFS(@>A`@1VQ6y+WE908$qYT(+v0lfXirc8Lhh?fM~S=jXe1TM)^v< z^O=r<;%%)O=4%n^g5#UpJ@iubMKJcS!Pq7;Ri0!*uZ#Dl)kOIorFOu{u`Si(C1d|@rnP2@t2S8h#xa;24c8jmgH1Y6K z>q`-5J3n@Eb_eb;G10b-2c@pu4;$EYUj~vbpZ<-1e>`q?78-L)EB7t5y9;%>`M^T! zc`)?<#<6zlp%cW*(MOjbxcttgSCedb@V7tN)ST6|h*mQx+nS3elW{v1Tt=Mp8OdZU zxQaMKgNwctERmcgP0lwsV_UK0Tfg$)E#*(=xMZxNtMYwSo!Ml3ry34kuLiy4nFrp; z8@HWCbo5rJEXlv=xtDn6i~FI{kc?q2;#h7($TV=NmmtylgNeq+0eq3=-w&pYJqq_l zaOuyt+hW4E#WE95S6fO1_0s#Ka$&*b9vBbcZ<3_y3 zYV{7{xFcs;x5zk-Wvy06Tx*IrmZDaZq8|6Tlqrwn1Tx-aLTocBcSIbmGtM`86kP@r z&oeHP`+o8tq@a!YBsy@lwb8f9 zV%bsbsN{+&Q5;3ZQaMhPSc&W?v7V3W9tZROAkB}hpX4sTy^eL+G?JUD%Is`;7%+= zu64W=UYQGn)oNg$`|^%%-CL85F?EcpYw+E;vDyFkxc(eh&JnzB`L*A17~_m}iv(e; z&czy*%84;G<6PAR;d*FY)mT#rohyV-Yh2YC6B;2f;$v%)z?ha3Nn&fR1V(n8m7QOG zYU33k5hMwW>dJ4zz)bI#B3q*rVZVySiAGoZ~o?Dwa?M}shK0R!ZMZ#VBGOYf?jy^YHCXDOdPhfh;9&-=nE72-^yT6kWDmJ_9j z#CxtLZ8ER_B8Sg@`=hr%IRT$hFiBXOrd@BPj9I_E)^EO-Fcm#SI@k1#kG1r+;iH0+ z;*`c;_i1tguNO+rF&_pTD}_YX5L)wuz}JDFqtNKgRL2CET1z*g{8`4@(DD>r1MUYt z;j?rd)vy)^EX4s!QGhjq5&lP1KM#CrLLJl8JM7y@ZN1jIx=;odfro)xfK$K)6uK-UXJO@mQZ8=Wx z9F=$2LN}PFA13k<&C(wf7oM>dOX=(_M8~hg8bh9YQ0>i0IM^1>1(wruF(|Y$-MiAx zUkI%IhmZg0ZNo09n1th7g=x$DUh~BNzwz8z;ab<3Do_VL4%`TwLF8U>7=svb7HciW zIUEL~g7IL*Vh~IYqJnrqa={>o7%--=Xmt3;tGCOb%wwif-b+4gMYvdu!ZWAh+G6-1pPEfaSiv|L6^4?CJCS8 z7s=dz8012pWt7g`M6|k&DOJe#_YUICaljCBuaqOp$#O(sg{IfWRy*HvMt-O5^>b)%RfgrpZ67o@w$A!*f)AV4QJ%8o_gDoX`H} zi6)7qhaNFNob7CXMB$MvY26QoG@8L9dCvTozivbT>n>pI850H{@aQSA zZkcLrF^EfL7lv^dm#Tpa!oV3K=Lk)~bVCu0fLEoJdr}WpJZat)M1`_goDl+JOeL_Z zp_O`I%-P78+dVWC-TV75?p;Lq4)APff-Ui#8Q9|0BT_jmsD?8+P8Z|h6<+H$oX))y(2ONEueE49F~S~6#1M=e#B zjqqzPt3GkE5Wt7xf8$^MA3~g~W9)JtgI8%|>xKDp#su6qTI|TpWZ% zRth2083HjFDUQ@AzPKn7Au2fP_dS!$Q9SUsct1+pDkPSTqx2t1x;G)hdmGeJ!-KWHjpPRywjFB?74q2 z8dk<29)sTwrVp!Un*9Cg!-S(FFiO5u?e*%2YG6p5&p|qj>bo9p#Tep@!kzg1eiN5h zT)9G2tD_?9r#Y9K37f5y(7LKKw(7jRAGj>&;=`m(;|Cg>KaTN zY{RIrJPzkk<(Shy_g{71m}TE=)JzzznlQRuTyV}rrT5#Yv~I$%?&1&ZKctO=<6@GKI_+Y5v|qem1}l}GUTm6NAy2-P?aPm$$kMfIHI{y~97qp}!a37jJkp%PYc z)hfYUmC}jh*m4C|sSwWBu~CSPB5Wx_oW)oN#ugVBNWq&`J*pm`7r({Lg^G&AD#VDX zODC$gpvxk%DiE8%nU_EP=?yh*Ltyjdhd!9~wdY#L)G*r2LQCJ5QU+aD@82VEw=I>I z!|FUirG|=dwVe_hxZDg`j>D=G6FZ@d=x0>f1D@(H|J2X_w}zx0qkh$=>8deyO``C9 zCW`MhL3qlP%F8Y;g45EUD2Dqg90>mp~I z5#k6I17mO^XN{39gKR|Bv_z;`k&D0oM*9Vjty_rC`#w+&n%_85B%%3IZMr4aZ83)k?&x`)$%(pLWLlAE1pt zeE8g`23-rxTGlvWZd9I8jBir8hfC#+O)afzr@DTK|gcGG*Z zEN9mjj*7V|X-CNNS_HK$D(hTfAz(xZ1R`Syt*{sd%mNapN-^XCZ{>O@Nm#H+`!r3hOtVXGCyIZRNP z;l&s*ou#mIC86ed?_b_-lcyOz%}AR~@-!t&6S8)@xIQ}vv3g#F^G3`^5ZO@pvcNx4 z_#}s8d0*?8noOJNVIBC(nrC+y=T<6bZeiin4Y>Lu+wFvxcM>9jr>^et@85ia+v+8E zW27rv@Ryr#EAaFEg(<{R93lEy(2t;c+Qk)ug=Ji&N?2bY3_`4RI8#^^y(;@jN~VRi zI8jeV5jsu#3Kj$_g;K9%43(fbhIA|nIaUg(M*-K@VrrqQmjhR~!hh1vyian!1M;_l zKcHA6W|2!~g^~PaTFoaMW|Hf`?OAg#j_Ql9bn-@m`6Y0cJZbel=*lle*bmQjU|gO-n8jo;D$lUz zQTe-nAHhe_-c3|TVH$7uk#ruccNh*uTtoFnljMFAgsT#SR8F5GTv#qlKHg(cjDgR- zvBOU8*-vx+;@L%VBkQRC03r_PH!bwzGD%C^52JR1(+X^(@{HYGEEsQlG59RQP(+S+v61lG&%eoH$#U01ncM3jEzi61LU8)}K>5>ZiYD!R z$H5VS{NzvnXZPgIz1t)RK4$0US53LP7%r{EL9K3FsY)<6kF^#th8!i!ay(jS^g2P) z4_y`6VY=Ee_jSX!0i9rO1!Hb|Ps_u0l2cd*g>P;(sE3yM&~a|A%&}6)VjQqmjR=f6 z>kO;yl=GSD6Mu9i{Z?S?Z=v`H7Kcs0iTq${8V#l|J@m**zPEE;RqqRrop90WNy62W zokidGyxY6+mD+hu$r_G@j>R~@tFqP32#ow*=FKp{bCwOqu=Wn(K5hPS)}LYYoCfD{ z^dB{MN8x|1_)JUBY1WHTd0_ybU%c+*IVJxV7?=UAP|bAsGMmg8G3 zG)>8qgtXblcArzV001BWNklfIYxZit^@Z;T&cPGG0LZJ!j!8Z7JQ46Dfr4)wi{F~zRB}T75?1WC8|cx zmOa&fv#tO8SKr+I%I99Xyz|9pFRu8Po_V(oTBn?~XM%;L6anecRzBX&creL%~G01U~YgGB880T1gMhl*uNipR0fF^VtKGQshAfe{jx`a{L1QEgf zVrPtLkMTJXuCy~=+H3Rez_6b$VxWe|sr`ibE4!M#drpRFKPNHyVe}d{*`}FvqhRd! z3M;C5T+<|W)j5Ls1>9T>pCqWyJEmq~FY~<8On7dm&G9JU9rFP>vgTFS#^G$A98K3=ztToL1yM6SzA~sr<05%sD$(BUn5}P^n>~5;lr}j)18-xhmf4p-QCp zD;PQfEmaZIcLrIcHx3mF?I_UBJ-I45u$$)WB!;p}Npt0RJ7uL55?aGtXlj+f)SNME z1{NJGTj2?Xjn8l88}F;z{zLnt#=x-t9Q+-{hx(saHP26Io-GIUC4%}Au2wGuPoH-z z5XCkTRWdCu?O2Q)C2MHqK1p)F6B>Ei+uovbt-|tP+uqLn(`<%jNgu`Q2KoHZ-NcBp zrmc4xTF#2kk-GlU`~og;E-sbMB68lqS#tkD1F?lTvJr7uq7=p~p1Pj7<15S^Ut#f< za|H7>f_e?NyodxLgaKl^0_TBQOFLJz9x!$-rd&rTMGS~w0tX&M6%z%J=h!sGHWTtB z!M9o@jRtv^Eejt3`@h_Ih!JhR=z3EZ_)<%W{01!6+rK`WH&QLr^%idVE+ zyHApE)rFx87M8Kq8m?Byx&Sd2)Z=}Q@9@0C8|i~zK@J4Y4)4=GVKh@E>sW>oRV2-E zlF?3cw$qHutrSF9uZA3p1GiLiXRMJ^k+5ZiZ>m!J(vB}%BNqYgsUC_LGfYOBRn9uX z|J;ZV#tJi%`%|FrBQ6=YxI%pT9O5jR`X1%Fgll&^+~=I-L?yxit;`cx^Lr|O)*bmU z<~b?vxb$gu$>U(uVlr-#nN;tjZ>PbhAI7zBoK|2ch;+Sbbs)X}uS0P@$1Qe)!cO;H z4OrHsy=*FT1WU(o)p^8N@-zVvoD??PwNgMc%XxgW!3#~L9!a?xQf_9fQFvYs#&{fT zYnRrO1cOnFMn4SZnRQ3l|M!Z(GI>rgw?I%^z=jdN)dHU*o%_1I2sZP4=W2tx6Ye=t zrr}x3loKOx8<#fCm>XA4?^j`6;C2!Dbv3dqak*SNeU51PM8SM3wc@;{YOzRl&V?7+ zysnVh3zX3f6?_oSvj4Zkm{kjbTsuTG2!awh*ZbB3N$%NfWjwdPLu7x8vB z$=(k5KFudk=zEn)V7a~;0TzZwJgOh)xS{hsN@) z&}Q0==qNrjX@2%^OdW+e_rDh-7p#%9c0a*oLgWoA=gv`EUt|8d6Rh3&4ob@l#K#s1 zj<0}o;4I#QFaCpeyZBWPc_(e?xher;zzSFc)`Ba9S7RK+5n>F+7{Yb}X$na~)M}F_ z8EHEq+1)*uU#Q3*0RQI{ba|^Vv`kg%n&+$J>3Xnm3^!lLR_F0v z!KWZ#G0Yj|d@16McFOifPV#N#2Tv|>axRX`&Yg{ooL#HLTz_nd-8dri9#@JnaT()+ z0)Z?;(*)lqYD(8}Ynbk*>ub^BkKMTGU9ch`2e(Xgk0ouTIWM>wZ<}T;vVs5C$ zeDL~ZuB%$NTr$gvm%q_W^~q)?PXK>j`)>w1Os{L%w2l-~yTa!*S`h#iAN`k7DP^ROre#dH6xIWl{up>4m=8vh4%h*UR!Fm)-PE(42)QTp$fUNv)%2lxmOk{cMc~JMnmk~m(#`SlwUy|^ zsW4nvCR$y`MRB1?$TM=)j+Ui>LYY^zt9$gL>)=-K+=H~vWxYLNwfn3(_$wU&wkXE{ zp%nsS39adwxxTsG;9{dqbz_GY_gdUgD{=i?#QI!N&Xo`5Dz|@W$KNa>kKQ{cUmio7 zS$WgoH^ux*^Y1f3cm|&n9bd=IFC0kU(4&V}NWG^XIF_O!{8s8cioRxrKLlDFhFN*u ztc%U}8fMXijce;99xw}ShUJ;HtcjMAzp$`ifb&7Q`XOt~1A^XbT4~j0p83iWwPVZ7 zEg$3LyWUCV*fN!sCFV|FkBK9QL$Wl5b^>0}Bti1LBW!lh4@1wHw4b^6`SvNR>@Y&tbpB(V31k<)K}?Q0Jp@@opO ztlWL~IK{!VFvGajSn#ptImQK87j?9g+M|hf+HQaaXYnXc?KIeb!Lt+vtd#;?Io_yKee5+{hSW)+=L%+MPsPypZebeO+6nlh{Eu1im z9#$^yw|S|V@Jch`9gAho)?&VIwMI3N)AfMG?M#0M%_F{G&k>nX|~_uVKaJ8JUqz8Kao<93GQ z`hT#TVRasu#CoRI1Fe^lBA|G#O5&APu7J2soVsCc94BCo8|Q;G>fyflz=sjUWzFWA zZ#B=Da^(SAD&OzQ)%9>?jc8?!puUWoo5yqnD4(Sr9<05#^h`^gzo2it^}QD{hw>CZ z2l?qQ^N=c`NVlDG0t&k2s$5BP_A`%ZrOa8&e&%WAo`qP9vu52HvtD+38Sszq`-Un{ z1OCpc>Cs_;PUGm?|IHzKEz(5~;>V@W*tgCMOPVfpji|k zHjpapWS-}Dn_O-rTx|serlWlngE-R(L)D>spWvxN-{zT)^`>uQ-Q{;ZzIdSR?6N!= zu+d9LE84ZrI}~ROs!Cg7H}|wNCEaS^RoP8)PE;dSVpp9HO*Jy|A%!g`+WKZo_fT5z zEXm*owhPnHcG&zdaQMvUC_!y-k-b~xN^psL%L;6tH~Or`Iw{;8O20L?Z`)!Gb>EX?E6f5 zN1=Zs+)I0V%TpIZU;xEv`5Rp7*0fn)E9!>7q0B`*wuY%#&ETDoZFU5+_F^Wc+3y)XWYA+ z%FiOa7ie(UTX$Oej_Px?FsD|1yLp?b%q<4>#UhMdxkBD3t3{qZ5VOqz?+z%*lNT-r2i&9Jm-dFnKLXV$f0mNlmTUH^t{k^st( zciq2lL%7?8;ol+4FlkD;?N~T|oci$k9;5F~Gh;w(M>y+qP6F87?`Y?gJP06)pi&{5pGN|Ri6WdT z)(S4LxHu}j<6CXgJViYrMwUh7HxT(E@IM28#NntDv#g6Vt(8*5&o{ljY`=pK99rbM zJS7xi(HNR}&eb&IwInS}Rw7iK#QI5H!0=2QjuA#J><&p|6j8am!gZ ztxq`a3CkV+8jBDcQwW`z=gU|2_~OPMFYdN@|8Ldam*qqJeulsOGd`gWGVG90uk+>C?XY?@{< zIjVUXCf(8}(sE#e9a?K&{s}NG-ACn{v>6&F=#SdajKt&cQHVYZm~;g>dd#OU>$Pm= zrp~kU&?B{cf9JHO$uF8}{cbnExHfd#Q0LslqJ`p=ej>18^L$%(M= z7SB}qCof*%TU#+VUyk|cjVqLm){aLKZ+m`Ql|T6AzW*aco_l9mCiWl0=ldbL3c3h# z-nUwzn_n`~@(FCUh6G_D7JYbEvR~jv19A$|(aobHSo?K_~x)Us( zS|ci#2%SNjEws@r_(iKtH$+m;3LxN<6tWCW)8f4~h;`Uf39K#Rdq(AAo)}YDHM@dN zlH%KKe463Yq-z7lghgCXam7ZHW)rrzF;}lb6eE=~dAWoU!KfnMW30iIOGskz-jn+r z42W<6!!H4~t4}=f#KP^je|-YY-U=M_;UPaqJ*@quyJ_v3ygPX)g1rZ#M4iF}u=ELm z+U0T3+hB_xSPX^2#NUbf(I4KbYgI1dsdi6^b}WL{A%Vp@(?M5@v!rfN|;ISz+W<#f}Iz#(n492{-wp2O|Ro_+jslE!8n0~xEO zU3&Nt1Gs#5=Zvb}g>@fvwfS1Od^{|jx{+vk62} z8>GG?WM&zfrI2U%cB}Z?=b$+~X;zAb&sc}VWlRth&tkikAlA`cRJ8B>Fd`T&Gz(=T zB;J##^5T9Q^`4zp#;waW)=SPsW$QwbhrMV+0@=!xOW$f~@{U-NYv||0d6XLHDfO8% zK|oMjz(f%u2A`&fwBB9eGc-aibi}SW!)k>;Ga{Gz%AIzh7{;N%_ek0a!I>QmmB!5Fr}dC3-h@u5(G#XAW?`dSCPO$;IKgmMv9ALaxLa! zo}=v+KFJD=YD3Vx*wpznfvnJ`YDahyKwB*&ilN;m_a581&eL}1owbD!C52hKAdD;m ziz4z~M9kH1fBO}Ijry&(jv9lb=sK)#hkko_+3CtNT_gCxS;`*2={yTyRj@_~I-ed| zp8Ad~^l!co_*Q3gZA?*@&(SO`{^dEo-9*#0;CDXnRBJFnhy)?x0&E-?!fRLaX*wdX z_r0)9-8P97M~-YqV1BKg^ZZ_u?Ih*4%__1GQMQ;MwD*YUWwo@PPW{s$t(yaBF?{S# zGsgR$jT`u2+@e{~G0X0dFkT5t6~g5eOsR}d4|e3*>5g1IEw8MW1C~o6)zGok&Ytq{ zonLw9>cxS22J0QhBnNTyL*5O8QG(v6Z$>Q)gJq3-Kkf6VZ>NE2=rAijz30)QE$^@rD?|6v}1WNj{{aU zO@A3{9yGOu`rPgBrgG+HDrYaCSq9$Y)1=1};K00o=k#( zQ83M1xz;@YUp{{?@R_yDS^4s?JU`&!A>-s{BulZmvQSy%*!8DaKDo}RyKbjcE>SL* zajg{5b`hjJ&pJm=q=?_C3b~S8c@s@DNHfBd>jW#ygsUr*Zajlj%225=2wmsB{^wrA z6IEn)k9>QZY~w0>&pu1Kd6n$Sl|ncwm9Vuc*aUX>iu0wVGI_O(sn25rhcOoG9JX9S zFo<(xY0`=7D`3n|19wSr9`v^;qL+M6#>;`Qc(8sPR(SNi?`beQ+RWarus)+WB)K(mxAO?%pC7sl9f6%&^U7MF4J zi@0iy@c24GWeyv~pq{MVB2QC9J>6ZsqJ^agxIPZq$}(PWCH(r6FZ09ei@f)EjYrli zw2b_S6&~Ep^&-XXP0x*^;Vd+t`fm57haRZ`wQT$9ikqudU2OqVnJYY3v$RL&F6p}# z_@yYM78Lg^Tj5EsyfU<=!|-;g*Qe3wUMox#)c>u95zac=w}Uz~uXLhNI<4l#_sq)! z9)bM|b~;+LUWTDE>D1cUaqw3A^qRgOhk2I{!;j^5g}j-nn@KQPdibNYe1G?>Cdnrx zito0ydbR$2_ft9l4#K75#V)-YPNmz0-6H~YwE~6kT$so^Y{)D5_7&3YO|so>TCZLt z*?g01XN&aeMo$wUK2H=9J-9>wim?+)@z1C+h%Gdqc774Ju!O5EP(FEvpuUKktK$}y zF+nkQeXCh4(j3M&K&S_nvNgP#qt*SR=0pY>lYm-xfYK zHNSY9zx`goO!&Mvjzi!h9zN`>z2Br6B@;3iMy#Gc%kugfOKYo?Lr35}rrCr}T-+ia zWoJXBO1`;OXeRTV_{JLukFOA(IF4OjMxqcCM@SeI4oEw1kZ$jwX;PSOlVV*zkd%re zEv8(?L=h&6uya++Tn#rj$K0_ce9}f+Et=0fN4l{=^7jj)q@zPho? z3;S)BBg>g;z-r0HSotLnzy00JH_o{uaf8RfNK4?*w=zTXvt}Gt=4#W2!>!JS~(Rkd(jmM#|^w38Qg7MA$)2QBo$b+^vUyWAQT;+zF z373vz%T+XK_s(PbxVYA2a&IoWk&9gN%5&dMH9Hqb zHi6z<=-=QQ-)dHY6%&<=iObkZ_28_lYDaJ{R=i9VYlQirV{%s-ioOR zP8#Fm_|~}bJ!~uumOV{*qux!EciJ{GCT+0X{(O`Aa#US2@%FppxSWdAVq@MXaEDPn z<5VaGF>|FV3#%*4FD+7?pCdrAd4^<#rV~0sPL@KJqgjr&T9_zA;tJu~38GW$#Mht1 zizzmVX-c}ii|+2BJG&%Tw~G0j7D3{BS|mf^scvj>1!o*#OC{X$GL&MZ6c@K8&DW5? z;TtV5hJ3$4zI7FCx5>OmoI|WdtVPqbF!zTcAlOm~D}uNH=`27UokmUI0>XO)@!Q{d z<|0C4{^pyqLHbST&v9e@K-n_rSk!mS>>x5nC+i^-`~mdyy~Dz(9C*qcPn|C6q=8Irylx4Lmg$vNUprW-gm!6`||5#yIUEp*0bV*$0Z298!jDtR4^NAWJ{Ed4inCLeXME_aVRx} zDsWnr^Mc+$mVPMT-CRpIUtiq$&Y$8ca|G2n<}Tbr`OHm}Pu@sy@_IB$3SQ<9NTD5b zyaBF@96On3FZcYdZ@c_Pbsd!`qNHH<8i+5h zt<0et6ol;Z74ofZ@|_*(58O}n?z^bmb9ZrdCWV07{NvA)y!smLS6?H0`BgN_@M+q) z&%NXH(#d}?Z3_*2o)%{_)oXDFe5s7g%~8JjTp`?^KTG+}+o{}rC#uTMAAW|$Q%|$| z)yJ@l3z%vJSFfY{`-LDHh4{S&wo=B{=7<)TkT57Tp>+0LUJ+~mW8i|SZlLlg2azUb z8E>QdqHofVGrJ#FbN0;cy*&MnMg5;DrbAcf0+Qw)>E1TY=bxqZ!gI7Y-k|yF3mJL( zB&yH4a{05E+6(I3W#AI3t+>d3HA2xO7kR<%_7#*!{+% zlyAI+_~aSt?|z7&R>M>(OEm6)Ic?KMAqVwEHLs? z=EvSR^Sy#`X7`C2i3w#5OMknM4ZNLYPO7IrZ3rCf0uP(r-$rbvC``J{aQNG|1B+3c zk6HWS?dv}o_+wb}yXNhKywhj}rrN0ac54;*nLJJJFr`X;{*Ldba{hLr)suzbnPxpJ z$bpzChctG^+Md?7IM2C5>*YTqdGmGBovl{3z4a*GKMwL;;39?jcu$Z`g_fvfoahcY z001BWNklZZ$I%B(|qM3 zyNkzI{=uIpZeFU+qpjv){QG{(#t@3InPoh&xyPH0lykL{EQR8hB4cvPF95#}{L3*k z?T0?v%c|ztlKQ+BRjb%?6&shKdlOBEvR(gyP=vCz%tx*eJdEsE_%5S`&rvYV7@6gp ze;eRh@&8`%cJ2xS1FQf@K)1h@!th6o$Rl`9h@)a0D{IGDUOC3X;sPawAk8p&@u_wT zQOI_7@H@MRu~aVHMER!k#P7I(tJlF8wm+yx}y}d%lk=pZa~W zt!Cap^^lU&`P{p#~sy1(;f&C;iV zKLNQ6x&v}qp&_aXA}tlkdR?t#9f$2r&^?e>fR_Zmpislu)2=%AZjcM0_w7Ib42{=b zB-whC%DLMpU3Z%J#Hk|MLC2A^i@m24m|lc8(u{9x?6RL^+*)5FHZ0c#chT#|fyd4m zd3p#vr?#k#3Pjz718o#qR^=E#4tX-qf$e^1lV(+VGl^2r#Q^~@0cJH*3V zMAMm~opKxBnVU<+qi zq|xzmpH=uAh2yXd=-`HB7>}ODq(6xsqj>+Qe8ck2Dmc%Ij1=Hw~?a<>`&t!yfJZZ9dR;O8=%`q!;A9M?0Z+^HA^jp$N_v@ip@_CEdPCa&@DT zUVXEX?QFf0Hye-US@NeQjz0w?S3mbJ2aoIwf}xn>o+8#Tz-7QJJ@irIqPPz1sn2(` z*;vkYw-)_YUKR1Nh@fdoxNxi!Qp=%v*4bMWS_>zFH3i1A`ISX=VPk zl5-m$KUE#3Dt{}_{eO?kGrV1+^G_09r!~7zlV?=gBtdr?0eD*B<50fQy2rk~-^d-} zk(h_G(4dd89@aV)=G*@37!S<qFi3$jN?KJ z`EVkHqWpJEo&){uS@qu6HOp|7Ic&KKVTd*wy<;e<2NHJKTINDWy%f;7XkjN5`y8_i zpIx{Xell!s%=+CVTxQuoT`TXMRMuPhc49eU5X7kd4I^^OA(V2VK3C<~`~u5M3)G{K zxje`1?sn#Tamj*qE>&oJ`5TnZ-$;D!4A=kaf8FDuSO3vJWB+T9vH!JiAYus?<_Q+- zg@-l85pmk>jb31&WF;MUsMPxr9x|{O8WduY=86HZ2Zw*UBZy!rS4F%m@tXHFw=gg8eY1mw*ot~Q5n?h~9ifi0DB zahdMjLpaJP|EUyr!T-t({V=X?e2J-^}5LMT07;n-IRa$ z^kshJ)I2}1T6I3Bw4jGH6$47e0hnyk9u@$8 z3=TuuGblMtC14JDJ5&OjRWmZHHe;NyItlvn_8(>Gfb`R$-{Gh~j|`gKXRP-yEIs_u z5LnK3wmyu={cd52>iOHK+;{1HqMwsvGK;Wr!EkC?=f)& z6GRxXc<6*#I=I_D^U9nvl&zsuICOfTVa$=Uru{USls1We!^ZwJ&!ftj2A^@(uSs={ z!yjhDV;GDpXWTc3#^ZgJ${jw>Zx4gutnpeFRchrb^=g@gYKgM%<31d+MUZe;Y z_WGOTm#;AY;CraP>rN_n-GO8oyI=YWyI=Y$jeq?mP{q~eFky%Z0(_ES^0dQF`UJ{8 zI5@3+kY^BdfX!<6pMVJ+%vX_8MDpD~y;+z6J||u~HoC_JSC5Gs5Q1v(J7Ac(iu@{2t@S$Y38Z z_^!vdM)J-+0li14;dUqiVrwV|4g>7%?$F-cAl=*95cU65jQKq9ERdlyjh|sK+=8fh zge`%8q{vsKT>bY)73uaC)pNHpcj2zi(I_c2&YgA%FmElP2!FD%%VH&< z8V0<3F`}v5VUZSxh0mE_lG(k#C80u1oGZN1g0RitC&bDb8Ze zD(H>EY19Hg4MXxHo~Jdr%qld_DzHpq(xdPnRUT91Ka{uF%#Ko>jTcSnzCHZ;G{W5B zDvp*o2yt>5M_}q>X*j-K|!-z1hh3_nyZ4KM}ECeD(kO+fQ+A z8@Ya(kD6yk`sK+u3qPhF$kLiWdyQVdS@?HdKTBXju9vTxLz5=6Tfjv*sTKgJa8#$vc?;5I*my zRt*puI4>ga6_L83INDf=W2#|9H4KQnCrDFFmV+2Df;WP0Z=*Xq&}vbA*BzAKaVzEX z=V*QBS@ysB7`uP`d9sTy;Z~M#E6bQLq&OU!Lht6x!`34`k^)Bw#qTwQy>d%D7B zH_3E7*^`%FBYER8`8U5!=6pS?LaDz!hu&`%TF?gYCkAb=gV`HNjS1RHC!MTQB;8`G7aK=yz9g&4xX&B-1 z7^00!yH=rLR;D*AL%J5T`>496$umv)qtd2jya(@RRGl3L8I+x-Wda9v50Rb@CjB5w z7>;Y7_H~x_55lyYfLXtvD(@H#@<=*e1B`B?&sRZyQSTq&6B~f8l@n#Lph7>#gECds$%QHI#3m{wK*2 zwB78{yf+1;cNf#4bfMU(-57^#wG#fQ(dMUiuj9H{+*+)zopZM@0yB@>c=te|1|}8^ zu2jN?;X!4c0pC4}nkrPRrQ#fA=g8G>sp{tc%iO!iOOjmmo!=9Ynf1Ewd;50x?Vj$Q zo}TwZqj^a}4+N41NeBtqNPrP|ZD8TU8sq)281rFwz4qddZNN5WS^^x_xx>)@(6Cf+kw{IU83zB5|a?@?P6^Lo_0IpwQ|SqD!EB%{r9Xf zpTyb@lnUcmf(A|N1J`!g%YSy&oXuZZptHoY(kLJcDBuRcs2@gH>PyX&W zZQ<1{j0&G$dFW$J;1`zP`N6-iNqk>5@c)m!vro`G`y`dcRT?+lPUYwch$2jSET;v0 zKr6+J7M|GHWxL(wT_qd_9VbDEnQ8UT#add_#JR_+n{I}z&CxZ z+PEV&Q&2LErg!+=T>kxX@+B5uj|I*}X1r1SO=?>+BJHUB$7#05nFR+)27l~t9de8D ziS0kk@5SXo`DuAQWI>Lw(pVlpAsD^z;Buw!eP_dRN!n<(4u zJ@%T-mWty)G@^gY3Xc}>G>)H)CZ!qIuKV+elQ~Rs*jS6z8WmL2M}3py;HfUDhBwvp z8lWOV8)3&7F79=xDxaCE$9C7wS!;s={)Vp+Lmd$pUq*YN^ne*5^#Z`)+BnccMGJu^ zbYf}Z%wVRV`&(EUfXR&)N!1fMM=;`aMO@U{2H%GGXV&L80L6n(|JtLLr1A9kgy2gl98Y)Rq zIddb)&Ni3-?f-?U22@U;rg6{RtbFHpviJDo?EJ-_Q$2GFQmsO#g9JV{PQdd}jRrQ2 z6{@sGP|7M*wbs7NLLK=1G2a9x^tIl+wlB_S?pMz80fS06gNwbpT=AJnHv#T-yX-~L zMXkJF#xs8ioEvQHvGYbg4I|Qx%4c7_hVpn0ktW*zB`>JH#Tt9dl|TIy27^_a%F1DE zx0@d2E9qeymSs<~9UHdyx_s$!n_FjmuCM!^hIauWeegMMJ{;hsY^Ws#R$&QHI*kLS z_i0`7zmy1pQfUYfVkNy@Q3nNkWzy!~$)_t4Xk`G}xJE2WH%ZVH@iB>)QB*Xsj(a|; zto|g}e+CQzJ4;UCHaJN0ln%-=-+F)Dvttf>GA{FS%zJkX?eQK^!0iLYBkM^qI2o0; znBVdF50_JvemKoO>Ytj?{|+!%_beJfLHm!&zo>5;nXjYN%?>xe}x+e>dMquHWrf1}W(sbjofwW~Zvyi8ZarcxLdVut^g{ z1rZOCRI{Uc-?O*DBW-14ExvN07(ExPzXNnXbgW(k5~r1+qx$i1K9l6ksPsjBzbK!B zq$$hir0b$_U6g+Ky~6zO@ckf)<9gNi-wYhVx{l&2p{g}i5dvfJk_53fH8m?tyF;?O zh1uC+=B;m`ao1gL7x{1gHoFghj_pr=iu#Rrq8c@HC4g?1oH>F_Z6`Td0uwx)a`G2& zrw(Pm^Rq@TmTy0?nxmBEFAqG+bbM5fJMka*x2~_R~*)8iHD{5O`FX|O5DLZGoB{0hA>Wcx^Z&W3o5@QLFKtG|KMLA*3M4TzehcT;{Lv`|6Y0M zW9!TB{9sE0{Yj$eh>hd5*7@h=s>iR#TRcQ{bnByGm<1V1j1qV$slWYGjN2}Fzoo#V7K)6leSTa;#??7Rhj;F{6b`86{8+j9~i zPko8{g${41wf0^?4!JIXWrsIcmkE(w=l?2 zQT;}P-6;G<5qYN$Dl~4qgPEJ}!mHJZ_V%0!FRu+02#wolc%XRyv!Nm;wd*jIT_ldmXRs`5JuC8HcYFN<)+Fznz3pCVr*5Wt?0S+;+xb3a z6Agpb@1754`VAs1i@xS?#V0g|3(bh_u3;yP*RkY7kref{^tTNF4ZU=xi6x?g;l;D#Hiz4>ii_oM$4Y;0nme}Shy{4Myi zE7T63#&0wrHptd)8WAZU638M7#N;G&k8<)>hUWC#^|0LUZLzWaXM)opIwe7tuf?MA zW|nB&ejk^9`Il)w`2Hm~? z-XA>q-4A}A!PcHQ4;G}GMqZB0@5)0TYXKi!e&+`xOXO{Df2By0;ax6J?C;Tq=J^-&i4Fx9P4s0Oe1+( ze&;vO05^pjmv2%*<#_eF>#44t#9v+|3A&H%=*3}vd_kS(bW2aEHx;u8T*S`I~ zzyKJ{G||4+)IH~adA8X_i*&T2bF}6^=85Ee-6vQ&M3I^F#T_VR`yFAROoP)T>E1sZ z8e1yFQc<5TBg>|hM@4k4^2yVvx|FHwwAYi$ES1+>wR)4l*JiO>u~1ctx^_OFfh2ec z$|fY%X*{Ld#Q<|(`!){!jc-Rp*!XY1!{$eS4WBxGP)9fF&RmW23(ZIGlynn`o07$i zxAcDM2@Z^p1{@ydVL-7HF|y)W@=93@42Ho#hvu?POu-P9QZ8mgZn}) zNMQyGuJt zI$;t&j;KeU`R)hH2&QWdY2LuK+Wljo#~vy7&(Y+2LhIq6wh>(R)v-nhIB)_Pu&oB-|u$N*?1 zjb2dG3QsJ`EiteHrrXBuH3?Q%X}s=E7QXK7gs;9z^U+7y_^sch8XQ6gRTttYiBm0P z&NngpmjNf!KmQ%i1K$JB+vl>BiTi8;W{rg;>RF#KHtm3Vf81xu{3lZvDhpPro*CY2 z%n@#H&^r4x-6x-<_PWVRGfrrZ|5{jdM4jN>{*p%l z%JbY&gKVnr4Aj=6)H=*SIvJo*BSHWX)IV%~<JEYCV9a_%`Bjo z4nf^*))P$sG+021>UCUWOwUxU>pp(y1DfZ4@P}CX)^FwH&-_bn_{aZ{SAXN5T({c)L*mMe<#=tAUmvLn*QbLG~`=mhcqrd z^Se03aXYcB)qIZB1CBN-ytLaPHp#_9RqtP52R0Z@H4hG@D>Dxj{Vtwgv}%d9|6Erp z--og9-ul94(X|=8*#*4Wc}y6(eg&x1>XQKHc02r;-r*asYY@R1UrBug?_((gpZUs< zzLxBs1&q^vmMw(5_Ad_%M%^23GYXy!zdJI`^1DA2SZm)- z6untQ-BUSyY&BS2s|L%5sb7C9s@_1nfH>^BV=VLfbjj^>x7lVYL6o399}~w!VMzDl zi^Q!x;#LzqyZB4uc@I->JenH^WdK~d`Piw5tg)`loZWrE{EzfB&|(E8r2e8~`|@x* z7suiKCM~dv#$K5@piJA8nlqI9Mh{qPk4Wn4sYMYeMJM~Wa{vG!07*na zR9zG`5vmA28czgeE%CYY__Zq4n{Hz6{s*ve%-&N^vGwSm;TubE?1USeDQI-sP1CbZ zIPmEvW4p79-PuCldMmZtZl!w19dw_1hUmHHh@W~2eRPdoj1x`oXgQ-#ph5Zz;{-VXGG+SzyMng!9cVS7ISh%moU*+%ap2?A%!y z8Ebgon9plIhX?GS5L4;1ECy8H@ge6A(f@7JG->};N@SdtwG1dKNQR88^WV z=P_<&Qg-z`%tt=WI8E53=cA}hTa6OBL+=gxP!5_?`p1V2+?}j!EInBICr!w{yo)v* zjXvsg0D(;cg2UJ27DQJ&85O1JmpP(3gW6shX>af2litHJU?k7a62`8XC|vU!v-nGg z@D`R3rFsE~^BbBHYtX=)?=kCZs#?*GlTbt+Q%XJj_+PsxFMNyYUNk<&wP#_PL+}4~ zg%wPM+%B47Iw_2vP*9=5{4|w9K?|aW#iox@!v7N2ijRT)%aG__@i90t5SetsB2`I51 zh*!{N!)-OGzaNy!%BC`D4$4p2Jj&!ft^6&Mp$FWF)5N=bO7N7Tq7;EB0ukr$nc9Go zD;rd9xry41H&MI(diK8Z6L#tpDFp>gKoBlIoQbPeI3Z2Q^#CWf} zi`tvtOyliuNB;PavE4S&Uwi?gh%BN_Ue24H9b{z*@7NmkcfJeLZjoHMLO8cT{NfAP zvk_)@7a|Q|7xBED>xk`vg#3}n*aQ^>NUess{3_iGFSGO6hncF!#FG(SGh( zY!so*3bx%LX|+gpcS+hUOs9c~W0bMZB@jHUy%D&81D^-`RwH~q^W?-s=I`m!&ib0U zK&LJ^>YRu?{Tp9*!+OaQUyB7El&Js4Lm!WU^ULpe|MND9&m~uOPQ{z+L>re~M5CP6 zIu$j{C`C6;c(oI;9a$E9sx_zHUU4dFCLMGE^ugyS1_uR{=n!byFv3JJHc8UD4Rj~K z9kmfzxBE3!`3JscK7C=@4l!=!K1{>Fttg-2^x1WmZX7t71P;q+6NdAhMw59p9kqaJ?sMrZ#A73l_STgpSqD?evxQzH{FOse@DHzVd_Na4j*Ukb#Fk|8|X@v zIEtJcvnB;|nYMFK>zQdhgG$BCqt?>8_!80PWunc?gqv5+0sle#;QtQSFTQm4r+#D{ z$Q!Ol|F^J*wN6VMMUW)@Z!Ueay9g*OUE_|~1dFd_25V~t?RG8tav2(zZra7zv~q5m zMf=rUAEYgN&wMxMzFXh~fLI|Ap{9j-?J=XB&!;bfvbbYaiCKKxTRHk2-+{H3?LYVf zF8=bbP{H|GniLGF)Zp%X<6Per?IUpvQAGRfQ&jH0o7(%nfz_Y?H;Ct9t!3txn;{5@ z&z-}3@e9b}GIIDR+V-8F;&2DOG)v{)yQ%%PZ$_%s{`lD1g3Ie{{hvQi_t8h`Jp9L? zJY;bhee^g<9FlFfS5}b@B4P!`T9Vih99knf{|Ybt#6RKifA_bTz2gpU{GWfEtv~oQ z-OWu@5@T8|?6ya=zD~HYi3%zN^YfUX;_~)1R(KmOruc7<`5xmbZ%Nwc$J$qjL}?hN zg}~!TJ>XEyh4h`P=!X+y|8PXV7-DI$AliR>xN(`*^G~zzhOcw7 zQ7deEiX9f_e9cyru+a%Qza8SwYL+}tS<7u!B!-a(3hkrvyWL%;9TUfxIKo5`N(n~X z`f7NdPpqYrB#6`Y2U_ghhz7||z{Af*(WJ>~RN7JZr!hMngvL!Y!#oV9pVYa=-7iWr z?Id4JLmKYUB;$bp#JXp|b2!L+{{O?}Pc*t0_q9or)^Hxf`4yGJi04)p!plVQDMX!;YRzdq7gtYwfy&w_d5oGP=Z8lL=ydAgd(vS=|sNq&u6oE7CiDxcwJW#@xQ z>C5)VeQo>3!-wX=I62}c<`gjFLfBY*rKoC;iU@&dd|ZHX+HGvNL+#{A>Su1CcIFJ> zv(FKJ^(@Kx^HkQ3qH8rI-Hq%t;}(*1_qu>;x3R5VlD#G~4?c*0`g;5`H{?K+TVw^d z+|0~}zJ;B~zJwTyiejwl@0Aah4>0y)r_0fL1?!;X31Od)Yawr=d_G4r=fG!+ zBsMmQl}V!BZp+*{flO;=tR*y=OvTe8bp{1PzPxe5s)$B4ZrP7INyr?elT4$%EW2tc z16;?IGyJSfea7=upiCT^B1e@ss{Kbk?`fTSnM&^ed3VsfkeCQX%Y6HyNp8}+Wi*@= zq%TdwnqL`JO#w0!?S3j;1T4Md14=+8oz782)>O6boX%(F>BaNS{2x8-DN+U7zv%`6X35c_YE{D*pTu z%F`rqjEUo(H82D3ZlcN0Htv}cx3MQ~w}^JP3Ae8hZCqZ*+NUtdqe|4TpZ!-qmT%Ld zHXlE3Mbe!WU}LA1m2ARG!{j(`Cl_8RGM30#jD2di5^U%aO&%y@QzNGx1W1=XC zn>(KAw9xfg7tlYOaMHOY0lL<*-HqwSKB*_xVcbbmldyz=Vzc|c!KjpO0qZ90K(~!; zw|X7CuMBh70YZ{kwz~-lpoMy%S!KUq9#!Tjey(-;15N%D%9vS|-m)C+Ob;9OZs zAOMcoPU|iSDz{XQ9H+8+41a!!q}z5rh?4mlg0aw!4J$J>PBbda1wOk`axSsvW%f8XpKyh_xtd zK(al-7App8+@>}2%6aPVe?K!H{2-0*`Y!A%7cnotOzS`YD*oNCBe?GY2ZE0sLmfLt z{aZgw{Dm)&{Mn=EGj}?#QfunY0p3AgKN=JMehmx;!7__!$P4<23D~OnqhgXW?pm z9CqycCl);&TV@eeE%vlYqN*k!SXed&|rZ<5IvM`VGJ+fdvAN+m7ANgUD%`NPO7w}dOgVMP8kxo`SuO16Q1-r6J^3p3LFTa8` zTU3r5rLwYu1~-0_1d5#PBB;771icx+7Cc!EVFoSRg%V$b{qd^*QV_j4>pwCN_yvO}g_>&gNz< z5QwlFC$tkw=q82*ai_GEvKmi1UbBDg&JNzPi7_S$mFac{G%?u@2rGiGz*tK&PKXQy zTB^Qc$ymI{I#%6Pm2ngL)zY|$tBA@7l53&aEE1N}*8N%t-3h`nZ+aLsLrA*QPm0n2 zX|I?hq(@GQnc00fPf5$MJwEzn4IDi=$it{|hiTlRqD-1`TCQ>5c&bIvfCuadr6=iq z>_`YY9zM40h4v%V7}ftK^WR?n5FXAz(* z;(1>l%kTbBKpa=Cs57FycZt#udX2fY%F0nHM~+iFb_yK?DD4qPonGjo%wIJF(l+PY z>0F2uN~zQ|9}#Y@6K!pT@%BcCcIz?V_p~4U=2w5}M}|*P8CRD{_p)nuM5Yoozwy9* zF=h^9k7N_LSc?{gCxV~;)fxDV6O;(}0kvbt&_M;evqyCPMN}N48#5@A#hkTh>;5V% zV!*W9B-@)*Zoi%2mRs>}z8L^pucI0b*F{=w?4?V{%AuaDt=xMb=1Y$e&d($5HewCp z)kvZ?%F}p@i}-il1@$`OY1nJhedtpp7ha+DM}I`Jvx}OU#lPid^s!@jr%vJj!q3B# zPZFO$kGFEjm7NAJw*m&Yanbr7dTx&B;w8-G4a{znU~!3He!*EGjKwAiHi2|TP+W>8i$$VX_*4pcE)|@imXpr*CmSI7fuKcqUN}%CsDq0a}6$V}KaSry50;fy^12L|q>lQ6No(hAw_KvkHV37FfBIBs3wuk{g36)`-mU>o(`L4;`; z9!Bv~Ce0`<&?Fkg&((CsvF$n#+cWo2kRHIvYa3;>=CkaiJ5=^?x%*+3^n6f8r5Wq< zS%%6?K+|fxrUJO5^p_dF?zy;3QjhMZ;xT7!9pqNAGNZhJ>gqAPS_7rEn;6LK8W0+1 z;#;YC9IgkfRDBYluJxBg&pyI%BzGM>qHmNgSEd4eB$iS{P-_kMZG5WDT_U? zJZ}S0L_1r=yW7}y8>v(r?~ka0O}dDohHWtvXs2-cpFN+q@2TIcI2ikebX$pva{HqndA1Se0^IB}Zp zg;!`k@ifT`&!P{l;x8ZS0Z#?aWNknh@JRh)fX4j~ppG5i$JFeD-$4A_b96rW5Vc#} zdENkaZ4Li}A7u8r>)8AL?+4pJ)oS=_*JEG4Oy^gAmF{mpggSi^efup`|IQCk{qTpW ze&i$6e(@LSeDafQ{*OO|->Bl50>Qii~W*nmuzVJ)o+Dg^Ewj6RMtsbx)te?mOP|TK3_xd6dn+f33s- z7j2TXuolzW!^A0$wtb6{;577^=5sGLbRs}l0I3d@RmkTkvwQw;UN|*@i)d|39AcW= zm?&~DD~&ZtkFh`riM4FS3EN@9yf65H0ywUbCJua#YrIJUuTZbOiAM=?O}82xP`z$ z`liCkVqnmRsGNto6XIN#F;nQgOl8(|DGUwXj?H#@4O)=Y5Y^-=pU1 zxEUquTFFJ+=^_WAqOsKD`Oy3SMqr|FjwJamrM-JqP`RnHdW_1^>j(}Vp?c^r;s;)`b^H_I8^|b9V=~ll=(`Pffx9C>riB`xg0P zWnHv)8D+PUc5}hBnwa(;UagitTLIEKMHu$tm@DlNYpWo3##7wLV7$+watGSBfX{2S z=sw81Wq2rCr%B~at7w>%$3TAHc<;T+T3c;Be{K=%YJcM%sn%2Di$b0|JfJR%Ki72>Jyo-=djG(?_Ne~a(Caaq7R1emOeFelIF8_ z-(p*WtfMtHiAnZ$ojFeXE&#PjdZtoO3GKwN8yj{*Ls+%=E}J7F_Ci_aM(|cdlYqjs zK1oG_WE|L>Mi7?eXS9j598YBce9?DjV9Flwt+b=>59d5`EA~j*$6F6m4Q1h+y(M>@ zGenOpuF&j0%}R9GJb5i9r*Y2=jP~ao&SA%|{efNgz3M2Ti)&#(ccwQiW1y!r# z{L=apS5|gxExrh|o~G_;s-BMb;^d+yvhfdYU)dSXdjuaDl@iL!@A*~*1SSd>upAeq zKcs@-w5~N)Ysasrdh8^@%3=K3c}yH*5`#%%H`$Wy59m)U`DRn1P}&91kK21hyW4cv zFLrFVbIEqv7qsX7dqj55{`8MdIwEwM1@lPRaplt=-&uUigFC=h(rL{lot84)w)+k} z?Q=R6ijW9&jA5%AVXQ@=X0&je@y8~Ykvo%Q+-pH)$|{n52U&Oz=UaxSvUv>jg(OJ; z>IidKJ7=XY!*uHB>7&r7o?J6~dnn(-TUtaa6_R#~@Y1E;dm@4u*O!&;yOanrD0;Iv zw$k_46A|qEJTgCrKR1WH@Cqn}%+Euo1A8r0tA#Hbv4SKPqSzguIXgq*E9}+==EYY? z9{Un<-vj6{LI1$_q2rifx5@55{9jSa%W(NJ_PXm(r>-Zs_ddcu|Dpqs^eot9hda3O znjU5uM#MWiSnW!RIpfu|XBN7aRP>>W07H?`8ddjey=obkW||esr0aw7WMD{-xX-mS7jh!I zzc0JeTF3po^<&Bmkh6NEAR;pZ^kOs)r`*TG)wJ2w2!exZaDcvn*j?xD7dCGSQTiWn zTs?Z_+9V0E_P7eFRaI}GXXdd=VT{@LokMF;2rD(8`HIJkuRGgac}zrxf#;~j&_S#L zRp9GMlK(-JerN6QF|T^+W-4nZXk33QN-0DsqPE+WpZRcR?IH9da=3ruG&Dh#IO-C% zTkO5?4Dsd_lATRM6#at0C!YVAAAcyv^R=Lf3mD}G>%imP^-IU2jms*$a*677H>4-3 zbm<>a2s5GxqlB;S?y+kZnN_UR6!$T`uiMqgjf3QSHEFMvyqmVH1Lx6dwF2O{B*}^- zNnLy&(tfH%<10m=oz_#~g2cyh7uBfauO7wkrFTa@fUzbW_P#JI|JKe~+WMpJ7 zT!7u(!3AU%9R9Z3u(#ZT{JUSlwpuQr`Y-=K@bDjFKm95E#wi!$u_Lf~9y$4X>|5W2 z_rL!mz+!iIk?;9FlBb^}{9k^IU~vJt?_T(OKZO6!{~7$rpAi1=4-@>-FX5fJ0sS4{ zM(aQQM@+kmLM#7MV)HZB#E)DJy3#FE2!BS7gh2{qJ)+E?i zfs!gBN5HHJ_5vk?o@bQb?LM%tA#Gm+7;!?u6T$Z!Pf9SpQXN}H?{wtc`I}(f z{-HQZ7Ycc6qx+u%6hdqaQDTUU5I`W~7rp~DDPezdf{uVe`xk5+ug1IE3vqJ?6;zSg zd6z2d)VQtqK5(%WvN7uu0iLoqDda1;{QqhY{j6M0(r_W^(T=xyH2teQD<2I#+QY6N5p%t;!g^Hp+{nVVRSEEB8UUCmB5AczC( zpRZoTHr;85gH|gG-4NPs_{8rcfxgTYx z+z5Bx4&VFT$nSj;eQ_Q0Yad0D2zlT>{O|o{L+{3J1t~x9!{JrMnBUd3&y}FR0~-hh4fdw=nmg zbK7yE$o;d^SUsjmb2WXx>^pHUT^1oE75aJE>LP=H!NnOi)?&;^JXu)os1uHW{gdRz zr#>D7;nLf_@sjO!>L%(gBzsNl+#;g2OP!CChl}@lxf8M#Rq0yL!YK`ho{mfa65s60 zK?UJ!A$VSk4_bB-%BLN*YAWjnFe;x?X4gDr;8-e4_y7PP07*naRHFF#e$+E)g72-7 z%7Ds!^&LK)XL8KSVL!)_zB|)^-y(2$kTx#Trcdi4v5#!d4AiFqggT1$@oYg^Ydx%; zQCchUe3X|u$`trkD1n-%@wMP7iM5hV9Qd5Zlr*y4mcQ}aAV~sDJcG!6qSQN-AH3I} zUm`ekl-jAA(X;cYS`FgZ#UM=&v_Sf>Gcyn6S1Kw6p4M8z<~HHxx{0=~#L3RaCEyVy z`eSGR^^bp!Y;k|}T5k&S7@eote};uzEEpwOw7Gq0Var}fNWr-(u!*jFz>v)Mna zAg>kebdb$0?B^drcDImD(`De#BEdXpzwff*&m-Fr?4E_aZRG85ft4kA@Ihp27ybKx zNc`E)pl-eq6-M~q^i9qu^EZA2noaD|60&+2efTJ5V;3%8K$hnaJz7+WNP4z7`}lS{ zlngdbu(9*?%m65!cJR+ytWtFmmEQnUBhc6SQd?+I}+Ur>pXSEKX}w2E$O0 zW}5kWoV?B6Et$rGmA=2K?E}w@hAnY!t>ge`dft6rZjQw*!{BowKoH;iylHkZt>*FW zh4XmzS*mL%`>dqA)s(Or2v2OaSevbIp$jJ~oVIYs9&(R`FH#(mV3I(*THrbAV~i6% zW%D=)mC0k25FdA4=G{UXiD`Od2mFV6?+ln`_lc9K+G#ldEbq+c4SH@UIgUr|KpcoI}W2WfVOKDh7e z6txJmzNY3Wsvf4|=}WlrTm*DR38A9)SOabWe#NiVm%N#|`s`hApmOvi{?aNztxl4J zn6Trt9XP=!Le9L{kM^o0-B_eGNfOb$vQD_YN#})UF;V!8jiRTt?|&;`zWP&tKOVu) zv}3)Dt3?rAK;(0}Qj2Y;P3OW{;^r=@Qbl=QZ<8lL-BWBt39ocxp5AQHpvv`?3R_~| z<%#ux=Z5kgC-bI}xn;)3)ykuBU~^nP*NTTS^&NMw$N$XI62RQn=4Oy|I_R17I7mQg z7t2#J=qc8PGXQk8hCe@#^|UjAwpu6^phUZK-^tvN`it+LYl*Hy^$_OMpT*vFH+FLq zaeVa0$m3tee)`kM#>-e5P(9)NI-T*}SrTlDg{y%xg@+OH*dy@R=dnNg)5xDb0uS5^ zzww{3Z+#2)+zZ&>`ULX6_aJ}%=P1B_>JN~6@5SDKKmO}(#kRLe&OhC2qJCIC>HGBi zK6-Y}St*Qh!Q~}OXTiF-oNRqtfvy7~tVD+=~_nP(bv=@z*ThjN>9YY2y`S-_;%RKlTwGtS$ntfK_j3`C8afwRv z7)jW5n~tpMt;lq`3+z&qaG@RZ@@|*YL4Xyzs-0ibW4w0pu%^{WP6DH&Rv^<(EM+uo zf0Z=I%dm-N|LqaG0QZ5RX|-TLf2a2V+8Qoj#_{!+W_CXaASv~1)DRzR@6oOYS>5x> zz7l+TK!7!Yh$vAS(S5|9xA0l|&gNPvXEIb6Eiw!|hiM`o%kTbB-D1DSCdpfs_U`gm zRu?L($Ae($5Y^+?qZ@OG*2GbWwTX+}$&g2q(BGUR3Q>a69yW=H!VaCwuMlr<67O!u zHi>^7%bx>}gUtlzBr0PPEAwsvK(#y8$~g(DJ0^*PXk$G{cDGP!300p-!DoIE;IPVz zyB&^K6(JRT;Wh=&PT==i(zPz5l!c~bK7X0=b)=@JF}I+AU{l14jlu1Sv1xZzZY<$6 zj2UdPfOrZCd_=3BAxYdRJ}&TihC2sLAkO1Z0w0-az~%+mxP(0aywg6CTijcV#EE;; z(@4edd&{Q+#%4;#6q<VtLliq}uyCSoPuBmal#O!;At} z`v;Tdya-!Ldqi7Th?_f@Fick{^kRQ%0VRsfIOcLE=9OlMS_-ftOIqxmAi-CS?cCsE zOI<6Icad4M=-qMYi_AvT@RO%eWt8P}+`Tepv@-b=^1jaq(OUq@=tO-SI*FH&TCgnt zJkZP+k!k+=9)5$sw*Y!h3;xUW$!Qi5W%^dX4aQ`&Pcyx5ybrWTp1+Z8Z>?2=RR-gc zhGSuP)8bH}BH$@OE6{@R)I{)^=ch-9-uDp&78A7tuuCH9YZ3K+@%+1jxecO^m>3JHt1&>HNndaCPB`Bp)N{G40tISPASccLmFfODr!g@#d9=nF~B~v{5mORWDqs`rO-?V3M;m5n2v> zCNpMxBS@M%c(obSobLdE>1((Yf-msOUY9F#0igwroL1OlUrlU)5Z|C=k{N7TDkD3} z0?4V_c}gmqM;ZB8=Dm^Em8v_p0TGp$;Vh+RS?*DWfwV^X9;D#YSs{AHc`_v6aI7Ht z;yn+vM%KHqxq&@@9`3!jU#dt?h6`Yoa^Nn@!sh${1c=?jR+NVg799uS9z6Rjc5Vi_ z;iPkE+1|xI`&HO&LX@DqD(2-^kV}`atrk+PLQv^zI`d@vV^~!xcuNbQl{2Y#I*6xx zdrC3{nC-@Pt~cqVk-A*k#CRB!7i8nVXD*^g?(_6eiLjdNKmL07W?o;Kfs ze6k(924K4q)4ISLSg9w^Q0&Cida2ic1Ob<@;X|AT+;d^EB znqIi?-{QXic0PF#5FKCc_?6huAkO+e^v$f9gZ*IAk*lw;c(pnz2uPv`)7w;(({j>Nb~^pBn|!EZ^D`w-p;ds6@nwzxsr0tTvNhf-{Xs$P3CGouW!T6RZbvsUsLS+Kz^70 zaevdwt0J0ukuhbu*Fy92TJTVc&sV?dl+fB3>XnMq%o%!Gq~7wmFVI}q76nT8LnI-j z&UHhP>?~sXC`qy|mF^t3&pb==o1Z{`^EbQ2O9qgZm#{bAn3gM86lsul2R4MhmQ|6S zYzJZt=oxIIhWy%p!#?y`?8*XCS%U2@=98bn{_X!ByVpXWypH5gzJPiDMUp@IEZuW2 zU^ce!4xJ>?x+kd>I3Lb1MAzmCR@bQAb{nEJX0Ju`>LnLvRO=ofw7Bt}?s&l_F*fnQ z%0LLGX=&7McT3jhcAxwm@PquzF}hu=@iCasJ_Un}cw~p_I6Oy}Z-8NybjDDTmIxq3 z>r22h$gN2i5uAG>@UKsr|2ezXLmbXXj_h28>|E}(}4%X@;LBBX>QBY zv|7y9$_KQ}JEO|_tEHjU+n|4E-(h}mL(fRF`y?9KKEr3b51X4ITY&X#0fVtfGvie$ zkTBwa>ukagw=&5FBu?u~~arqpWpWguwtsj&iad3u$aSloA;Z z?^9%c?$vGiJ>Pc9B;g6H`F3w+{vNN^I9@q^J=LQp36@q-)hZTJ;F)STY|d<$TZL!l zM5Q$%iZ}|1_nIVoO**ffC+W1GBkG>R^8X?{hC4?+&+E9hANg$YZSSc9RZ;2(TCcot zgSUL-Oru&qF;}a4hZ|LOY^FN1Sn=i#)%??Q6;&1Ck!KS78G+7?x@Y1q(oBB^WL0VJ z?r8lY@yZdBu#?7AHtA7wy#AEyEat}H&>RpIm0l+X6DLjA>#UlLeP zA-=fHOr0jIUjP(VG-49W(@%nEz=Jr(T)aTCc?p{cHnB*())!K#Hq%BSW^)sLbQQI_ zg4AlnTU#WTFB4yS6`5Z^Jl}&d_NXX4+ngoOohTTFLQE8ZJ%7; z_u{mcwu8h6v^2vrs_07t&q-~T8{cVn&j*&z1XTu* zbAgll@29cv%DJBuEw+aFoivd1X+{BxGQy?*dlc_ES(lGwDF5%85(dHGx%NILX^BgvL_}st#@qb^~ z=Ee6$r?IvUECJtZ;%LFZf?ugp3j*c>kJ*aHY~UTKdm1I25Nt)m;~*DCe23vh{xbr% zD(w+%TqfSx!lb_S0M6gdqQspjw-Xy)?S!1$X_Ks0(26B3a*wst&l`(Rla z52NUyGIv@kQ~pHRaSh5iXgv!1OB}@ph!JH(yK&>-lBA&1y7APX;oTTB2_|-*O_T!9 z!`diKouwMOv^nc2Ky?l_x8arZu)dB}g4FA7?9R_SO=6`2Z3FE+s5N@E>1q2^Drb5o zZR`9{eT{AHK-faUCU*6-L(U}F^XH&G2TMns&*tt9$<`HEISSP})MvmQq=VbKquf|; z?%*A|6}7ws)hfx0FA{HTkZf+C7MBsvXFw44gkK6itplGXF{nxq69m)ulOdf-|J;sp zbKHo-{U-I zcAokY3lDr95>);__TD_muIoJP{GD@`xAyB5-3_1tf*=ThAV^UZ2~w0ubAe@9D`}5p z$yU6{Q=W`v&rI2lol;VE;<#LiBS)TcBHI%?HL{k@l1POjDH4RZfFuB7 zX*3$$ue)Ere#>3XH-Fsw)_z+zK*g!@R|WKa_nv#scb5B|?|duTbt4SJ%cWW&EhafnNAGQM(XUw zFn5LMWHXRAbvGEGe{J&r7~+RI5}Ci^)ETn?Ihxyx>*{G0Ob z3L!vY2=O#vl&UjvVIYJ?Fc_ppxWZ^+!%~T0X({>!QW>n#F@ylY)U1sfC-wS?G-7@t z&4q&DG)M_5AfNvN>dqfR?!GHJyrnac&Y*tzmyvIO8yUSe}wO=>G zW)C0TBx}vx(A3sI%u8;>+r4Q52a)6kXyu_)Q35}0ysB+{4+}u6rnXev28047KT6$a zgPnGmB9dly?ECn;?sI`{rn+{gvYfZt+1w4z_|%A<8zsGaKhD?|taKIvKMES(6sNg` zoJ+&zN}j(w4>-;f=D#EBOk}urM*?qTzNYqOHd|w{uzH z%~sL>k8FF>^#`Sr0ZM4?q2e@!@rn+`5K5GyuqF|OcwWn8f~9<9PLfVxkB!6<(g-BB z!4w^7;_FKB`nMC8)GpXr( z!CQp!5!ANbkV(RYMbznYptnSkF_gqMqcj<2HPfuvM4&E`ZIkkPRU{50mcI5{61#Sx zl%jh2H2#GP=-QaX%r#0y(qPM~6GAbDdQuDl!muKKwRXrGd=A%nyEo`w<9^e1tDdlL z^_Ku|#v1RW1p!*LXHETW3$u6$-tPT2=Z=in;v)~{^N&1uTqo0c6Zj=RKaZDRz*Nd8 z$B9vFpyDdUu%$VE($|=qzS8lxF$=2IvIA!5J=J83hSv~kagtQ+&uJ3nBHF-Z~GjnW@N z>z}vM*}aLW?YZ=>t4Zy=3TJczok$@;oUtU9U^J`MoBOEZXO?Ay2*&rR<}XrRm^0qR z^A)qUdJM06zvVc8eBx8TdG^E~{ARIfY&#O$4$zs_lX@2oud?)PBAA$b+7;?Rjn4$HcD&VR41( z#o0LEJT&a`PE85tK?ri5$+Fm>ESVhCqZ+YJs|=cNAdCWy0miG+C#USfkC%XRA9+ zjUf|2l#2e3WVzYg8Mx&Z*u5JP38cIT!CK?MDnTHP{X=W0XDf@D?l|OFl)MtP^^)NkG)#?QUA_9wA~oef#be(E1b2D{ZCjDr%tVXN zwKT3Jyto$dbiPRHwe#%1eu|W1-I#-e6;WTTh@1lQ9h%vQbZMh%=Rxc51cNN*OTlN* zcl(taM0DSFzt8EduIlM8q93fic8~z5U@1fl5(Lmh;2@TUsmR_iFoG`-#A+wU0$Y(r zb+u{U2wbY2SvTl+uy8@SQ6BP0r5qjmYerp-ms&@Do!Whn_O-U03UDeYFHf4am2|MW zL}JS{T3b=Um=RVeG8!xqURo*fL;et=$j!h9Lik!f3T)o8y9vCHP<{yH|4h#8BssO6 z+zq$kjE z^ts=dv@}Wc8W6OC4=T&vuY8Zp{6o_~sw8*j%R9mmQH5tfSelZT}gS#7b^ zfiIrPQ#2u0Ok~($$qfRfdDL0pZ=gj2e7T_)t?Bj+^}FBc+2w@I(CBVuI`$JR@Av0}waE(bsN^T<8#f;(@A@?yk<0tySk zf&cf^)a8 z`ZFKJzUBZbok3>Lv-J7TQdwBQ-m@2RY$P^1uxvXLblGmih!PD*oOHrNOy2l1Ym}++ z6qjKQH6Mh#somG{W0$hN27PCcZ>TTS=zA|veH;$!+*c3pm*vgaIn_TK36N+oBSLJiolgYsHZ5X{EO$v|B~os;`RbDgt6$rMxm7?wW8evyB|(;z^mIj=+%dA3~RqRY1C^ZNyLCg zc22sHhpwgquZ@4(^wdqM`n21MV-zHQUc$gLo=3P=jMCLLwN>*nPic(+=Sn`O*8;Yt zL%lC;rI!uw&HFO(uU{!V`puJPgO^@BmM*{Y{H-c~;qBU({dR7Y%+5U|Cb!|_Mx%h$ zVSq6v?u)EztKKbAlSn>jv14F^Usu#LO*3sNf?MHduUH60u{h458VWM*3 z3@O{j$&C^=tKI=yDKc7f!3%hOwaRnzMW!dy*p{A2!h1t_^n?*_w^kdM1`P&-^r_eW z(q3**8sDqzX7`GXu92?wL?)C{l8Euo1JlhK1m6gLP5K#&4%JYWu(XDE?kto_Si{4( zyLU%(ZGb90!?)UU|r>1Re zFVoI>xBTweZYRl5ztd~ILP3sd*S!VDG2Z;F_7>&{mKRBkj7JL%uLaK$OH&FAFRoNL zu@;iHEM^jD;4XzKzHa1O0%niyoAdn#aVp*{QG7Gn9Hh+U!ef0sEjr#VDv7R=xB=T( z|2#lzL zo91|b(Ev2O{X2WR_w3{PXIclqyab_Ve4nti)==?6Q(KCJRs{cgL3s_YuuNs{tdVLZFMjnk%eMazr11K`|IJdpU;XE<+u^$7SdAaPS4-e&<5g$0 zZRb=Xi9Ixeb`wz?(xwT}N?|F5r8NaFq!1WZ4XpWM8rS3K&6QGu9*w^=4 zpBsfi=<*|Vy{Ex9k^0@l z#|f3qVCK%_=NFLD8df%g9vX_i4I_vjBDPfzeBNv?+F*@p!I9!8=@Ddc2|05T{l=*% zu>8mf0BR_UWHZRm|2%x@tFTajrHjbuC|t1<*|P_-nMUt+%)sHh;NK*m7(&GZH;Jgm zK-8GbnhmC?26i?2EuKfXm`7`kyLBts+wXv6l3;O>)n}f?uX=F+d;(2&>C-dIO+(s%vy~btHU$$=(dn?zd1jf=9o1E`|7ax8PLK38~x1cR4^JPvB*(?1~CQTdE~nyecZ8 zBk5;csAhla8(0fr%?k-ag9|vCNei+AHo4JFv)dZj=tkFdE)=p=S$cwmgHENr02rebyc|pC$1Oe6AGX(pJSlQu7+AOAi=yjFCLQ#>Buby7u<$RIq-fc{# zt!bs0-k!2<+mXxQUv)L-QYmc9#&Qy*woFHvSCqo9l;W@`)S1n=<1KwuTBEhbb`tp2 zGG1ww(i^Yg=NB-=LWv;wv{L;2$xnasJ3ac?YwiY_`{sGxiRJ7H3iC6G=^2t+cVLfC zMQB&6jW^;=IH46|mWmvL0=Q5V=1blip^~w5a${v4la-Qq91EXF%=4xaZ$dFEHkGjLPZn`#I z?l+Z}Stasqoz4cPTA_UUHN3?Om`WMjO~gecRtpHOQjFM|lVy+ZuT*$uevQxw8rhYC zAGbwqdo`5o`gR8H#~{#6YPFI24V}kt&^iZg=TgdT!wrOdS!6k0*r zjx-r(OCArOUF7lEWxji%z=gGl8Oo%R3{6at9G$?)jX*6xdf1TG)zEA0oBmVdZ8J__OeD}k1N}LMJ1B6!SbT<=Fd?%dol`xr7c8h zY98=4hSyS1HNrFV1zuVyQB;aFYVQ!d^>`?UUJax@GQnoyQfSee)z;;}seQk@WH6{@ zLCvW+K>#R11RtR)f@dU>e#Yu^g+_;p)n}i@ziEAb_FU3+Nuv-8opkM5 zVUSo5)no&nN+Y9_NMRX{J`WE*7=4d4G+CH3aFHk``3$4z8x8DwX z_eP9mp@5Xj)V%KFXv?vbGiqL}Xx}ithgVpFkzq2250f}}9nRLRD5Y5Z%2y~n^;9$l z$t1Xu6SH8V8L=&JY?Nc8EQ^|C6%!(%LBgzaaC?*Bzxc0<#L9vQjbgdF~`${vrv-!5$hWjD?uBKDk=q zXp0w19;1aS&s{8W`)CqJtDUxDCJ^})k*!m)t=(Sgvi36F{&s_&65ggVz3}OUSNr`- z!K)K){od;}RvqhX_EYTS+1H*2c9Z#R+wrQY8@n!BTDI%6rPQploeE0f7nU%kHH_zBr!$0MSmzKWwq?v%iWNVk zSn?>$E^*aRigDK_<3zS!=|qz3SOU*P_G}V_aW3X)YmJW5we=LsY?}I}b)3uD82n-Z zZ}9^D@}dcr7mL6*l%>CT^3$JuuFsga-)|m=eq&UBZ~UHnwE!aFByg<~uu~Zl<5OtI ziRPv$Z?{s4&}*HCxYE(iy9?1)}(xL`E5PiD*q*nn*)3gF5vReE<7MDusH_d#E|>)TE#h z18PBT7;?j?s)wwsAoKIEWlJLj(c5o@V=qK1^wrf!(3DEl_m7%YejP`xkRZf(K7O%) zd(|#7cim0mz%}UMVZ<1g9)6g$=bnr3NhH8^k-)?bN(yCZl;fanCyMV|Q|p_!3{oQ zP24(ZOxrU9kbmUCJg_i+_})JcmKP71;_9vWZ+?}b>kct8vIXtBk!q-xsX;~lbGuxd zi)$7B^wl!Ehcg_^x%&E?t!EW~l2GbzfZu9sv)e}AiLvVTw;ODPiR_2Zz-kz}Gd!K% z*$AWBkLl@;XG<8R&d_=Sste`&ywwwj`fsru6r2{X0=}Q~iv@Hljb+&}>2BBsx%Y)f6_mHdT(X+H1^O4iSaF%phNg0r5JK7LJ`WL;k)@& zLcmp;jHPk4!qz&Hz(}+0RGdY=C0arRTE#)*wI&FCD)SfcmKLd;I|;t`G(qs}sZW3M z7ki9nuelrKo98q|GF)@uhJc_rvQdf%^ z6d6mi%hEitTw*aaR08;=edA(D41S`#&2fuq3jwx)U=pax;I27NZj^UI0PAm8I4 zIBk@+*6Z^nJZ=+tgDX)eG=YI~AQXrk(p+UoXoHJ|H8qKv7-Q+-hZ(;4X2N&8gRu{P zn9BFQNAbZ22^JR7$rM&9iKU|GGMbvLWyF*k45%nPLuhm)&J{tnU5%VP1J6H)eefXa z&>^_(?X7Vwn-97_{$udsOYr5d!rr}+L=s?l82!HYqqj^^{gqE3ri5Y$gB{_Z!H9}9 zR<@0I=5%B}6Oc= zt-Z}K&>MlS{cKrJEe=Obx7SJIE=~OqseRM}VOTOj6;oP6{Gdfr7R8GLTSHRAV%1~C z52=VE1v6>I*5kg69QS($o9{L!y2tbOGPU0ufiCr`w7^~yc&^e4XJjlQvbG&Lv`B1j z(8bZH;dRiFly>``8|zf5^B9>m)e1pjiJ-95Wb9L`I$}JVW2?Gak+ChZmPN|aSTS-Y zb^=o|PO2Hl8lG`|%FE&*q!>{4?34o zfy38&HwuN?=|KjZ~11UbtQH zQ<0;}apk(lk#IgNE>n8rHL432qUTmE99NVEQ7O<0hAmCW4|!^_$P3FJbESZkQaG9) zPg>mlk|$#?dD5I3wU=~gBZt^-Fvz#q?YkOu{x1LgZyeUGM+F51a|RYfQHf=ighr?u zp%eyGjlqv2cZgCDheIl#IKk34zX^bQ_0?n!AEsJdCJd^ebhL@6$evPkB>glJ+gzfe zYt`6n#L|e9gv1cxSHFV!*0M&-&o|19kHNtM7$=1Z z72#SXmQo7F7|iM_!BQUY;(3f$#@T%Z!yo$?>AUX2-M0^b!b1;Hc=%z8&pd<9=CFo_ zF=4}&)j%YjwQZE^qMZcVaij4OK};A$MG3<>G2tB1Sob^l)aHkHermm?`Lc5iYw38| z1vayW-%RMp#J2adUF|N72OVy9`P~EhedOKLi>B$HCR*!HSZ?xFJCpM&b7!c|zJWJ) z7G*h6KGsOoLCqT~l8Pvd5}ukb@WN7=3jrih6RvQB5iDq2{gHZowL0VZ#yiJ(z;e^@;7!1Cge2afAx`ZyBKn^K`}Uk@ts{%w!1r4%_! zQw~C&&ad(Pg2!ArBn2qs0~+oEMtJkodHtBxZp`hVxV)L)?xn)Ietu_ZsoA9gJ!I~=2XC!F=zE|W%w^5)6IEM- zaZvYoJ=Ph}8uOVP!hG#($P?d2UV5pn-H;|Gv>u8n_K4@?Nw~Pscs@3Y9JmJKq@qkq zrO3~x#x$DMRl?;Zg2fAnU&h(Bli{EINz!-TiMw|%BEssCBNUDtVePr+u(CPy&@h;Y zb{GYs1hkIAE4eP(abv-j6*Hd_spi9AUcz8*-^YJ$dEdu>u3MO;_W5arHU}crdh+fw z?U(HPFbHgPeGmSfG@;+wysJ(6*=};M0Zw4hP&9pE@sS5-#}D88RiI?KiQg@sJCU6G z%I9&n?Zg=#!yOvITV0_hMlnFzvdCDP<7JPPvw2=!De*53?O|gk}Z$WK=0&Vb{R zd&?oTo5XTmjMr{PwH{O-EL&*1QY73&>@N^dIClzf{v1JJDF}n*xRT9i7blluo1%EYVn@O*6MV1TS`VH<@=$bWkA zEQhw_C|=KlFVCtO*gQmvBQwi6M9 zCJOX!MSLrvX-GdUqQk4!IwB|OBw;3r75eyJIYRZp2T6VAk5O;C5pKF^9q#JdYvI5F zPDFfm z7&h$On{3_JgNpwjXhu5O7|tuL&*HlC;aYJdSi0!?`HLhbx1$nC@S4I2#nP5Y)mv*` z;?`BOAh3>e!zw_qv_>mM82ALGViddc!YpCActQgI6vF?9;uwvC!$uj;%ksU6=kEr& zG4QH(a$>7aZrzEM9ggUk-^7f^4pgBSJOfiHhatzt)rvJgEQP|HAjgq)rcE2bUoD{Y zD=2wPX?WezEbL@HkleF2`Pmkr69z! zB9*+Q6qap)rK7M*U;A1VcIoQ9jDF}tR9fa7QHGk1M8|%8NTi;O5RNk( zNc6dyOg8c$*B1Vlzl5GUk6y^5@3|9fClUlSsp7-@5;8xJJo60J%yw8UU`=g7-El`` zNMJcgE(@6qYB&c|+tJ&%VeP#NrNBRR3h$NUtbOA#$}hcyKYJc)WDF81BsL)sVzU8V z(~xK^JArnR=tKgYa8QmN(G(L9iiu(dD_$41;pi7_bJTP#vDCHka|175R(P|`3?pba zuj&NS<(hT-PEVYBdAqm2*p11l6Nbej56l6xRLBv z3fUtfKOA}$ZRdu`?B0iy8^Kg77%x^aHaTa60=^N(5;jAQMZ&U}FMCBJG8@8+@emDi zC|UP?FFx|%!ua9)UKV&nD}7V2vg8(DexA`=598VnPBw?vd_X{9DIsfHELTHLuT>~k z18$id#<47W%8~3U>LUutfqI;X(eK7EZe)$O!yx_b+V3uPZWNz>G_>FQ?XY1+*tVSj zII1vt1hh1mt+EMO3q#g|5HDe{h_ht44ibkcyZE)Qp>jD=`}Q;Xk&kfkbDzUIc9cdy zdFt7OB9*b!TQ?2%6ca})(E^gmpe!4u9D=|9BKqtsR(=J2`)y!ZfNt@EH~A&P7r&1= z_5$j|A3{}q?CB}Eb|2yv|Lp%ESY1T` zYu~j~in*y}sl6b+6p+(ewEK9%}ct-#u~cq;_xLP&+|Cg7K?5mHj6w znf|rq?;Ih>UqrkrW49ef#Es$y#!@R2s|dy&i=3tS%KQp16)PNDDDf+Aoo2$dcW<|4 z_nfaLj#cDK2b1dm9srliIXQ!t>DFeqg*OP(sR47bilhZqMnRN2j zExGx$t)IGjBy;*h+mgjT_-^Ke-neXg)HnrqF5mRlMnANs4*^i>sFlh-4;-tUe)V8^ zVv^+KG`Snzj;T}#1HXv@Q_Li67Rw%AI_q)Y?rE+}k=>ajdk*<^P~QL^>Vre4Iq4*I z=|&v-mFX$bG1ba1Dy{ZXYXXAH$z!vy~pPzrPsa6k9-1@`huDgls!M71s%NXCU z<&th!9pp!0S z_7I+YgW$Pm@xJtB^flLDz2yc}CWCq74b00g6F&KPw7x`eKl)MBjn|_0T@8*E#pFyR zK-o~PAge_x_x~-`myc6<`g^QC@->2TnLq@+eFxU`c1${j2_oktQMyUhUSpzdluBS{ zMsRW?*rQ{SDUxMjf{>t6AvEFHP{PN6m#tJHPiN>!x4ZF>b!`oUdA#>A3%!&zJjgfK zt-fyGW&OHWhNG5L$2}VAvmdn{#F}n4BhuW-Ud&T-8Je!=(dq>y)Q42m_>y51xBeq2~G#o9I`S$r$uFfU7W;990VvldQ>-mxdUdR`H zBl+8gbvHHqMo$*~PQ!zg>DFeqcKR~STR!lUt{^+Bh5Q{Fu5v~ucII4rWNRkrZqFu) zlS${T!wKu$ch}4j5q0WNRyBWg8)ZCO%5@Ji-^jbYKFIv0R1O`-Wbu&)4Z!$a?_U63 zCI}9Os|BhTW}`sD5P3*PjUysBO5ux83We`4uHud+*p^I^gm;Fp^lBh43e4`c*Qpf; z*(^KZ+0GncRLQ?$mbd+$a+G^>MC`eNENfiRtV7@poGb z-L6Z(vpSJ{ztVbFW$vu&&7Z^0=5QyrM#1jm@F(qISsKh}tbT909}+nlCN0g@bb^I7 zLq!OdegCWr-*QBr2TmxZiYGqxn}g2LAYz5Zmoz7IWahLI7+zbg@aWk*nH|H7 zB`iDVl3f*k3X5l+T#?5>UVHnn-l(nghH1?Pps(b9qp;;ie6!?h zz?y+#Ah?#01VR%K1cl1M`$jkYW#kwPpxGAmLw+tjA0n#!O=qp;CV z5-XiXr=!qPQDg@&z8{4;6O$LkcY)INzwzsX?8V*hw|jG|#@KZ&(*zyJa<{|sM&VM{ zdtV%S1(|Qe5^ht+UxI?OTYAlnY*y>aEFO7aZv60l&jDHOCf*sWEZM6oPcwYWouszz z#2p?Zs8oo8E=gS_SCfD)2O-ZD$~<QWStrC%!>(Y$?}0$b6&B072$2 zeS9oy9(a*3Bq*#`PMg9OR*LTC1W_cu*!rBH;g54l)6I+vnY8ymZ-hC z^VSOeB|(Y_;5JiU+he8D6RDlMNlfp+%8gCa0!lG0!hx__dABt*j5{$+cK=(@=?qv7QeC4l z5e-d%Z-ktqnMgP!EXAs4Sn&cXp*$;*P5egj>;+%8++j?L+c$E$@hYt?}LqZ#&Tt@pSpxduP06bD4e zE2YlT-BIsyZG=CF_j-UNfo;G)6%+0jk&%>RlXYxzu8kepB|il`O?S=7hQSz4=_ovL z{Ov?>EUSPvLNO3hKw5(lgHal#6;>+4+H=oSdiEKv`lCN0eeJcR4jkb8@BS{~+#JFD z9Er)Tm@tSXSv96Y0S2X_=oF!eGL~sYo%uu&1#nMiQ0XjY{sJt$j(O~rW$WN#`yp$Q0y!s!PP%M2Clyb_&ELc%355yNZ3Na86fR&Pr!WvHOU zMk^cJjhIg>lg3IVL0gCzLf^-DK1NI)#dnadsks1DK&!tu2W@KiMhdoWFZ30{ya{V~ z!*zBn-z&&`^gLcGJ=E@fyxm*c?dR>jQ4w)tV-PupQZHH~W7mbND>s?7;!PL+_Rkr* z?hxbed^d^7ZJ59(EUi)VOfY~OGoZtk=HUwkURWvd7CBM&6 z&6{c`wfjcZyWO-0?PZ$l*5h}7;HGdT|8A+2e=D*5N}btrEfaUYpTy`mC`C|-?e}6H zr?ydbrE#5A@tykB3qJ!C#j-z7;LlpN^@+j@PvaGqNo>Co?YgK$5>qL+wpsTus_&>V zE|ElI#W!4$wz(>sh2zPsn z7k);<@WZLy`x(CO5V>pLMq*-`(5qs~rAFUW%|T>=@_PsU$f^A4=Hr7fWUJ=o2gEVPE*PLV`O+tT$uh z9K<~3vcvd~{zMKqY<%zkl49Xjdu-B9j!lx9+D0OgAQZt5d?wQwMiU%LSsW}HISA_a zfUgdKYrpw?*%4-qA0Dx6YrnFr8Ka>p(IM?zIY3;65{snPxCo9VI9Ki>Ja>lR!W>V% z?Pg|v`4epWgr=Mp2GoNApPydvaW6zS9m?AMg1rRfw21_Ca(CEnFs7@-3iY1^l zQs^pR%VdmdO%~ZORu&ygD|cNLN!N{F0>7RbRBRh8jj}a%ENwLk!q^1Fm>{-3Rfy6N zgBoko3?ZOV;$o+U(U~mv_$c<439L*8Y!~qZLf?xV6@Bj^5%aK>Nw*OAv?#UjHVqs zX)|M|`H|Hsd~4afTn^0B3JQlO>`q}!-YjCa5yrC_I+ow|)4wuls@3VxtK6Yb_h`r6 zYmZLYscl!_PE2FjHp|rj-;@bLAC$ohl3X*A&;~hZv&e5a|sPRv-lw6gtspiB8)3~c?q@jKs}1{v{|7eA=AzEx$0 zbb8OVq;~Da9vY5QX|7jiH+!8nr#x$iHb$;jzuIxtb(4pC?tNL5&goPp9~4(|)eGnB z@|hE)c3g>-%GRZR&Fc3S)qCvtq=*C~l~AyiChJ&CWgJRI<}Ia9^V`4R0Tlb&rnW=B zgIp(OyK9-zcf4yN^!>@Ovi4D(&Ky*3!XDax1F4xSafU}D&-OSked~OvND3puRLUh| zYfy@XvKItKPK6?04@Jy>xot;3Cb?H%+xu(sk37iO;d}E6UR0Lz1Yx*WYrSXf<>!$g zz|Ib14-KQVCX_0e*qtNRG&yk`&`M}{W39s1=a#Yb5L?qOQ(0GM9d?H{ca;Jt2R!~r zKAgR0%sSl#w|=-cmuc=xw|U(NQ##Q2?fCewX&~tpmTwee_DT@kV-Jt+w9;8SeZ?N! zu?d`Hiq)#eYoX6##UkZcyk#QA_N?O$YuObdH=Yv7?~0_M?fCbztE)eMytriU$&7fw zH!LIzGNV<*5*nb0VO4~b5ynmQ4Qaq8L}jvAQ&Uvu&a?8wlUTVNQy=~?nVWBBi!ogM z%pYSaRmzL=Br`cI#|GO5Of2Q3?l%(K*4HKDHM&u|U;ibom$jIpf&xn;N)YALKQPf2 zMytsANf8CWSB(#_hDjqgeJ!B8LWvF9Mq5dACWDpDqO)0aGJ&$K=&xPGprsgq66dY+GdHB5_IL7LRlUE1n*e-PTRnKJ!A_sVe8fc7%2 zeO0REchB$gQgXX@YG551{@{t?02E@6?}812M=X zwfC{VI<wH~#Me{qU$ikJCPu#t+|nG+ZkjluB{3 zbmk=1@Mv946rH?lZAT1_s}yskDut@gkL{jfm%`m*iMyoKPbm>iEA!b4r(W~ijp1p& z?nnd#lAyMU?|noPsomDl2$_A?M~u!;4!=~wgkgiJYZiURy7!tL&bsNLh5ijP=NG z45*Qax0_1Zq#X+*!hG2e401x?h?1`KW>8wx@qYfu19>1ne)zseOc)x=3HKCVd=?1; z5>qqeMkfG4LO-(Ag^1Y@A)z&{)+~5FZxk!Mu~sFe;NWJ_hIKo&~Ad2YL#V_SRcj`NlV?y!;ZCGjCukD++n!CJ93? zmT)T2u?kfLrCTMQk*c0nuB-Mv*O*TPk*J<1yplpJ3llTXEkW%SnApg!#(0`oI}(*K z)M6NmfWk#97wx1Y#xs}2$_-&96S3F45LP|HYK5>`Mc_#^M>~vjulZR2tgfx;A~=!y zf3)n7&9a%!Hc=b-ru*$Dn=R9~-Chny&``U#LYr#7_5GgTmvVzCm z$!!mZYlWHe@#n|R{nZ~cbl`1_-Eue1&@d+O2`Z)7jx4Iw0)}nPknNK9eIA=%;n9mL zy#K-|2gWiSnjU5{rS^xy-a=LV!ipC@@U@HHH+&<136$P9mDory=Z!L?gD@g})$F@| z>9=0RP`|1z<4M>2KA9!3t`MP}DtwCxbAm5?x~ zOCOp&%A-Z zL_^gy@I*PLs|cP%+s}**Q&~OYXZ2JUoHjb<-RkK3&iK3TbAjJCzJIHN8%7V_OnUb| z(pOwXYU>r4Fd!@yG0hPN>OFGT3iiytn%b}U_f<5kQ@{x_1_cahw71+=K(8$FnCZ2}QWf#C~pEHZw6 zg@?{8@qsJ1uye@OSLEz;)=|G#4p@G4F+AZL^E-htFTQswabiH+HdAJ!5}%H+>sNlq z29jZ=^bryB4l%(;QqwzZD>I~%Ggsnn*@l(PVWrX#cu3%50cou%8^d3oSzsv$I6jf( z69=}SL~e2*3;e-=IQIerJnj3z{ee=IMAH3fOGkOoOTfGiDFZo`WI`;&XdD6%gHnd{ z4R6JtJI~UikMP`&zL%{({ZE+s=ttQ5-#*XUv(K{jz3*}E6Q6*KQDfP$8FVI%l}#gJ z;xw!V-A*!;w5Z@?Rb&g>6-NriSXLCtJ}^|@c%2~h2?=p_UKQnkPq+kuU$ZJDL{pP` z)`G_)1_>QdHd;B@LpfABg&xXbO^%_{DeR#ku&wA@T=l5t7cjnmJPiB?Q0i%&P0bCk zE;f2U?r&4i>kN4lXWp)+m;QBb61PFFFQv{)hIo|>RA(pVa}Yv5h?J;)PYE81f>Qdg zmF2wMN)O%XUp${KpL~TvI?M14x1t;uJCP#vD%6ZBVg(~w2`L=~qW2J9ER-o4Ln$=e zFp*-&v31&U+?=ZqghI07Gq&mnNAEvhp7p};xQHr!WJji%5$$&3xRi+)q)r2{`=9;$ zNeO}p34`l_z1nfERF<{dPGv@PGHp8((R$G@Q$!Gf;y~X#Nk&w({*{>*(=fbts8~lX}lux`wcGuNW zbG8$ChBw8QOz23hc&_a8!cvKxYxC~^pSgDrvh29)JU^LvUiVSAs;jE2s~>8$T5?O4 zW!aXEFt#xENC?jii&`+S!4AyCE-=7O?6AuOL9i@K#PG)~#LTk5npt3GnEf)bMz&=m%aSa~t#+%`>SuMm>(+goM?UtCJm=n9)%EIDo7hye>fUqmoO{kMGk^K} zeSfb*<1$pDHKsVS=J@YI!AqZAvCjh+zhj@YTs!x75*D^I<+4Q|rvK3oP7A>az25$> z!tts5gi=ZK#M?;@A0wVV;88Sdh9&N(OkrZ^<~amDH=4-Gw$VJa@%P!AS$jhtfk+XY z7D4!uGkU`IyT^MM&LZL((ad3l6o??g6!`{c^lCnMB*O2a3sRlwI7c{)^g2yq1&CJShnzGhr9UHciwr^nEQ5Z>B-0PsfQmu2mHSx zitomlqb}>uuD|>hOs|6sBZ6kDG{NU!?GT&>B!XB;8qTMSI@is3dTxzlortxp#%#S7 zgiNx}&wV;wvw-~vjfqo0WKD5WiXf39h>R2zK-W1|oF3>6X-~i&?@8-Zy|1|l93uNcdV_ta; z(pps12v5R6uHMal+?0rCp>ail&2uystOesxZ@C@SsKZ!;^z>`E zo(7ZPlE@36&cpw%{Lf3V5{E(rF+xSiC_#>mA?r27SOZzBA>$aN#1*cqlcvkg zm@`g_zY)%LzV)|${d)Ji(YCSw$iC*B8?aKx(4@XO1I)<9H|q1b7j$$lpKth{oA>ao z-0D2CIg0vj33BX7u-z%o=jg?I+FZBkXP5r^6Bf`@4?glARjtvX)_6~LXp9d0H{d(5`g557rl>8Vd#o_z4p zQ$p|sR}}9o7B16Q0`tI!eZAi>#^_@BoIp(qVySpNEwIZy)-%I9rdk|GM14AR^)}*X z!2P9zj_{GlH_Kmm%l<+z3w#$s{HUrmCX)k)7`x|Nh-VIxOdmjJX_-H-EW)ta_h=w^ zip{Cb{LaT=#rkdg}2W@XFLfC%R5G4$sGW&_W}H|C@d~)#aPShamGHUw8TaxYH*)QU zer4^F7VrS@ZNLx6FhbVq#0L%$O&&ls#!!uMg!3u0Y>_i?7!nXT5K=H11gvBQXF8Jk z+%Xo5W}=t|W}M%s-gMdC_3rvBjavP(F=AN?IVl8@3?wjj%u~&zwjK33-hdf=5Lt&?(ZhrKTUMoZ8YEgZrY#uEbYJf3@b0ZjOk?gN zCL(@Yv->q|H{^4><2#xaclf<|;P-&Pj1Cb~;T=EaYGgyvoEVDkPC63-sS z8G}x{pzYAHA5b{zLU1ez$(-YSFXz`@y~2Sw0+w-z$Q%aN+7z^_$)Yg4@$z7iFO>K79 zXg=F^yrJLP@i_(dGdP}&rVoCv?yR-ep1)8}KKGY2?|2){6K}_rg1W1G+wiU%x5gps z+Vb>Lhu+_v<=y*ReBjVN-aZ+$wBw&dij!Bm?lXV2sQ;!{6n_Ssd-Pzf5=3tlfs=qe z`jfvfi{PE6z4CJic}z$(JMpgf2jTPql3R`wwDuu{K$kwAo^)cwyk3fvVkp=-7z%lt z+bA@;^|S583IE!6b^Nvrqi3T12k+I3mu9=|#biEA*!S(glEh!hKXL3hRShp#U49S0j68;hr#0l#&%YtMdaAwRp47XJZw{s(VqT-@S0_V%pX zm}igw%&!E%{kq%vht8M>aPGbJse^%Rj0Mfx?;>pNBN!X^YtR@>+AkI1QK8>6Ve9c4 zA_+%Yb#i05)Jb`Ld94FH9!c>V43(MdMgDHY6g@cZ5dV{?H$JH9jh{3t%MW)?J)iW> zyu|Dy|BTwvJE+}u0-^d?UEqp}UwC&F0gNfhn38n0(~bu-@6*S7N~m($DrLVr?Q`?cKK&jE`+ar?w>g7-~nZ~b?F5Scum#Muv+ zJpWFtz02Y5i}ue3DoSKDK8b2gAd@<((PW_1Wj)LQ$r|NrC3@u?vG6ANSO~6m3sy5l zAO)+Q&+fLK_S&>A+^Q*xpA=2?;}UaHMh(Bt1pehdBIG|081`{0^Gm{s0Gm?q^9~eU5{kC zK#E^N$!Fgr-M48Q-N!bT*Bsr2w=%o$v9R$?Hh15Qc1@not=`0K5-_isBzp&?wu*M& zj-gkd*{08K$60#n6L#vMlRbR>=s!dS?~%2}1I6+}tAFk^YhldzyWfv$G*NL4OXeZ{ zDw%W1`K1tqIOD z>!+6&Q*Gz8b?v?}%eiwM<4FJAyAE!r$!_aO(dX0ceG={kg|6g_Ea!dx%q^dQ7 z_|UBctqE^3!+A6NNW${rSZ|DSuavOi-dJs%*HUVWysJAYi<{T&HS^rza)g)@Lj1W1 zudAQKf2hRTgmj<+}Qcd*wvmk%Q*61ymw}^Qcykn;Mm)L_bGtL_B%~yOx^W+ zM~gh0wMI{)i+2Q3a<_2qxQdfRHCw1gi*RBJ871D$#SGWr5X7xa?S9q=KolrqCFvKM zUY66#GMqJk34B#bwJe4Mvw5EE=KHyw5V|MjfBDJB(y50ZJqtW0qG-k$bJP{Zq4igu zLwDCf3Znf7eei}5r2y(Spt}NJ5C8{OKsz_QK~C=0X=}^=TF9Y#Bx^yC2q9!6lrmA_ z`;2wRQe)oQ$<3vYd}DRBTj;sW+C^<$CpE64t?T5@>EC$Ip}o+gIu2mp`TL(utTBnz zy6JQ_>5OSPV`iPPGqM&=gS}JM8Ye)^N~P*5siES8pfQGsYo+j0nS9+Qglq5#7_O~A zN*ZB6Jq(yn3j(2gN{HoJAeS93-{zTjdY^0h{2hh|9M<8^7;C@cU`A>4KBPn_fp*X{ z7AZ7~R^wEF2tr~R5SW0#gvcTw7@tPS0NYz9J$Ig!r=CJ34dNq*iI3hw{q1ijs!Cmk zfiIJ}yn=cCET-Sb^!wOu*JpGv#`}c|2~r}H1QErkI3{TAL++nK9Xv>M`*DKlDZ-f< zWWA11zT{S6pN#Dyuop}))i@#b&3iL_Wl^27wDaCsQ zx3=oLlPlGYf(+L*u}R3RT#h!$+HCQ4J78eLyS$lb_uUxeR@bof@xOh|Q7i*E8YmMyu^+LB0!tDGTN4&`g0BF z$%jtfi>t9913GwtS@&1E8&_(+>BLF9S{o=ZWLr65eVshoULUL?I|dIC&dP#XK27K2S;od?Ovj#dz1b5jD|0J#c>|oe+n9{ciKEZ z)_d(`qN)90Esa}G;KC53K$wEzd>B^OkvJmZt5AJ$VI6H9b3MZcZ>iA;#Y7_%6V|yq zGGjY<6Z|KEuL5U)7pa0}cNW}AGPnRg7PG*2;ECIdR275(03ZNKL_t(E!-)233`#-2{1-||JqTzZDxiq#UWoynV9C9TRn0aS)9~!K5~PFf)e2D^h2H^9b=Q z@B%OgoC7q@rTB~-*Y~c@)qx3cM}WJ5TOICx;2wmS6hRcoC_#l0VPg!H)R9qyiXx1~ z`_317D0~h~iPaB`8diM^lwd3lX~rRQJ&m@eZH=A(#e4UU2Dt3}+`IR&Pn(Vf&U_$O zPYWSz7})p8P=JEMIl9J>JDArwgc2D_#=;uHSOQ~_-4wYmMvYHn7A}*%af$V>y+H5F zUuFD*A7K1L-$DJJdk7C4Aefn<{*HGH1Z;EmHHxJrip52WD|6U9$7LDl0)hY;MyQE> z1g&w@zI`Nz4x&3J2AuxTGf%8;qT`K>!?owPWu9W>+^FB< zhKsK;MRR@o@6OM5?eXn+;a+I6q0f%d?$uh^1=lU3-M0lXM%!MK%-;xu+^sDm-0wN~ zcrY-()!b6>r>+|_zM zGq#sn*GaWW3+r@ltkuq;os*e!GS#+jj7^L&t-|P8qOd8AX{w|q1xO`?R8j^)N-0zT zVTh0lf^gt`t*!CCMjQNhOMja!tf#I-eWmjE39JEac>eqq3WT+Y#o4ji@3OZ_Dm%9g zi96lKkChBO+MP`&Zp`U=PffsIQcH4RRp$Ml=)U@r?4LhN*qS8VH%&A#MZUINBF95h znsPq5c4i%^b^P{gS2+*|9IHosaCRU2>k$VUF*Eh}J%w@aOttx;`F^H5g=zoN*XEb! z)BIdd+g?YT-dbi!jiqah>}UN+TjZ0X$Y)9W)3R0%gf%iba3qppBt=p~HCl);gdhZ? zu|>Y2JYyxw3s;%hVMOMkvI+{{Y2&83fe#M-)~=)Nrdd}4Ukc(Cr-EM)5$_9U4*lEp zSH42;^;a=j&cwUEjrhPpP)%%_dh~>$0BxN|(?Wdw`xlowd||1>-_EUZV!XzYddwXY zbsCXs?n}bvSQP$fzc4n{#xC^pylc$j&%ZFYyqM+}`-M&W#^xREY-)`xtd+gO)OArz zSfg8{=`n&ZlGa43F&-pJN-1R^Yc)g^Bf=QMxJ1A#HtP=QSQ#9uza`^!coaPlg7HR; zA}?6#beX?$0pZ*efi-{O;@T5JslD*cQQBW`Ak|*RuzVNyiz12Nsp9w%(e3_3e&s^z z${+s@{R^*Czx{4n@Ay{lYG4f}?c%f@ymvL>goBAPzoK!Dg-mlf)jYl2;Yb{^KMuKV zEa7M~p%n#8#37SOcnmmJINsOS+Gg6?PGM}P(4EYP&QCpialWtJYHnTHHzv)E)!I5+ zSVwN1)XvGiago-#<*aEsW2dotS~{C3Yo!!O34TmfAf*cY+EM}K8K3yyIr1#OMxfZp zTPsV$P#~2mKuSp>V7;Hx>2&z|+&rNQKNpALQ+pVX8#Svwt%P{KNPD*jF1}w{b&rZd zjC5#WdA+;Fn#ox#3hZRacpNbv#*9z2kj5a5B^YZG=f`omCV%4`D}VJFmj2=sT=}J6 zruMeCQM>mZCjaq=iI3hweCtuvvD;9$9wQl8+eQVf5e2OJC%s{QXrb|IC_noK`P@~~ zH!iUDch6GH&68i4BR=t7L=q!gO~lw3B8d=5;)PD7APhjMfvbbd%V4H{O1`v2vECtF zS-}+MKjYlrM2*@XI=7{N{+p$}f9uhJqY;qBjquwI+v5lW-l)v%+W!A#dfy~hZU{Kq zaD0c0_Ud%N?n&mW&zt+~1og7%^Ju?8TYBnoJN4irxd82?d`u|yZld@BR}^<;3v)sH zYk!AmG>N7T5Kqq{qu6iOMwcdmG95%IrTP4hKCaeDPlL=@=F(#8h4F?DT&mbEs*+Nc^B zFC@spVzp9Yg}~XN*=K`K=SUv4O2Vta{%Z4=E=Zl0g#wgPOw@J%TtyQ zC`#cWmXJ6>ZY)>&IbT{@XMZ>3U^n7G63IZyNR?@u0wJPWppuCwOlr#JwLs;GG-TG& z(^9T0>RN|&ore=94C@sG7b+}GT%rG0MzdE+)U~Y||LS|i$ttv&fnc=xvKwsI;qri7 zdh&4#*r|t3o_9jjg$kZP1@}3lr@N=0Cm0*UWPOq&$B;n?Qk4OOL-s7nHwnuzFwU`* z7o1)f%x9Wqt(l5LnxUc*29a<+hh`u}JwXNnS~iYasWLjVPB#imZWV>IbOM`Xp-Kv4 z5*?^XXKmoBV4-sD5Jotua7uZ8QVO4yo5O(S)xPWSV~JmXp^^krlBF4Gzekq#!0698 z$LA&PS)2Csi~r&u-6+zrmvP$bT9$xa`t;+ysfSOV2k}{<)KOG$w+y3u(+jWp2yY>1 zoVbUe(L_cGR(kZeQXB?5ji4;YD2Sx=X?h&=wPoHFq|ULFYsNywR2(uM1u{~SP|Ao> z2owlnB_k&P(YLdLjLs)dhLCO+W2nb)ijMI~|7cS7^3g z9HsHdXGXr?(Aa-2UDFRYCwstuan?$!T_S|MLzFvpE)45=jsxb?9vX+0k}#T++9k z2G-)N^F?9Gh&3Dn$0>Q3L%WV&?y8+ zKN!wfAMercqtguC?UA8@YZ^7-Xw+136{G26avU>)DESGrMnRdftwhdp4nh_W>>Y{m03N zA3ZJWb*b0Zj^~SWL3ZhN2m%^++)dCJBbu7=QHfc95SUTfiCpQY6qGMi3j&ODCl-8-c`*?Zd%=_al@Truvg`usgKx%9+ir+`ya51;%Iv$lG| z^*a+QfA<+|-Y48QMeWG#kY`@lGsEQC&N-Cy)moP!e+YM4f$6 z$Yc`wxgkZ=jDkra#AIeHiLt~|kXuWt6-l5dj3rNMWY*x5C`*hS)+^RpkEBuB=));S z>53bnaTQb~HpoPKiFUt{a= zQdf?`S_*5ahmh)!+*tA?!MKgJr5#`pn98r(U8*4$TP37S+il>s<|i~BvO!+d^gpWrCf6^%}Lr&SBjZ97A(2v|f(VnRm^`DmI7ixErO2~XjZc3;z|+tD zt4E*NOyeEK<+|Gwo#h<(_`}V~1Vl4*!5!5&6h^a-qi;2FFZL1fQqXADaVkQokf;H| zScI`ejXJI<5L%-z&ZFlq(|_ev+E0HPl}r%Srl^1WdkANyiDqVqjvVy$)0+)~)&xQc zgpyw9)EZY9^y(_6+rxBvWEU<`EO>K$@0nMyX&0mWL`QE&&CU?sdKfi1jtB#U3ZWK* zlAx4V3@Rld*B&g$GqUwAMXyiZ>5#6jVs$ZZwSL;+KK01UUmA6H_~xL78+?Jqmgjbg zcHbm|?c^eKJnp^M69X>%iecB$>Yp;f}?ZVss1Ilhh_+fKsY6C)P5 zXAnH68qLqEB>7Hk>xbIUeva;`=UMskXPN%Mhlvl~LVWl(!lZ`N8k6;L+Kg;$L-I)= zk&;-#IAuvL=eW?%IoEU8Rlf#8A*d-|@-LQxL<#~aQ3#|cU%cFatp9_tZXjS92fAd8 z1I7vHvd;kV8TjsPdhd|~qe5wQQmO!{{4nXPPk(6v-CiNRbRL`a=AAB1squaPS~z=N zjPKiAAdt+4*kHtAex>f zoSwz>+CGJmsREH4wyb5`P(GJmiMVjSoAZrsMkE9^DVT~w5-F(#l30m>plEERSoks5 z4hkFv(km+%Y+h_31a9=@96j#;Ka_%oX+9VcLaXE3q`Rst0o#**w_umeeKto^S8Wye zxCrBUqGkr_kvaMjHe-lSWt(ZV@i z>!!Tg>GS!eHg%;)lw>mWe?utxC0LLavJ1ZWBGl z#s!HG0u=_{)x}!+>uVI<4xPCR2zXKoK1~?^HbU%{M|eB>-mDFD4?I@cfg}{(pHxZVBdbgPTG=O@s{~6|D)pcp7+VRee!W>dFCJ(I zBRqB(xm%fyH}WJW{2NFm5T(Frt-%%r>Eayu!WHz|GWqg6Ncnq01y70b=|96=mEV)?^~7bD%X&R11iM zz@yaGBCI1gGK(wTiYp3SnnG6K(wy{-MfxwD$F+O7exJ&uE`rEEy(<4X0jA_TfrLOJ zr^XSDI;z#A@jVavprI&6)N6<+@X_xT!U;I%(NkwEIxk9rvmo#F(0NAD>(gIZrRev_ z*E=|CKaO)x#Y%h>w`JA7QTkucy4(KPw#;*&v9Q5JwL$h2yKQ~fYsJ{@ncr++(V)+c zU$S}gGYBC#q<%gjUhG3YErrKBn>5y)iRs{T})h!IEfUfWn zxz)AayM+oM8Tfv|=y&gfR|%w}eFkkrqN{vmD#Uh>SFJiPB|-`+VZ-#hUL#ytqF7$Q z^wv|8^ilaE;-oqXugv%<*$r5+bSa6h<1{WngdnoWxJHJT^xLB=sMiac^+s-U`x zARtS@&*8@*DBpA7vu7-8Ku6nw&t*xafks|E=;->Zt{;rWV9(gJ7E4iTLm*vcf|b&v zYI%-sub{i@6uk~k7oS3izZFV7L!PED{qzs+M$_%+yO;K6eZ#y7{>jJm)I%rRz(3*UBAT8hId~M+7(+;fhy$N&-&!z3myscI@7G0zC=Tm& zmoMwQQqa|g-1;$8LLf(YELH!J@f_v1{`d4+Fun@}Ku(E(V>15C~Bw zRWA>lw1@6?(ETp?{1tR(b=CBH%NX-Htb0lzUOM})9__Gw+iw56VFdh%?sEE_jR`9d zf8mT>wT@I4;$Eyr4mFy7?$^oH_BvT%=obYl2&l&~br&&KOHe9634w|u?=E32E-!pA zZ(bm3HC!*l^->>bR1sas;RdKgS(;Pgq<}yo0)-eKL)2n#vY%*qK{E_}W&tUD-FNVN zw6hqkaoYba(hOS^=qxAecF}1@(d&_RI@ls#)K;Gnj!%Pl@q1o+W+&S3mCn2Hx)EM` z4VuY@W2L&vHBig$n9KDdpVz~mcd}IP#_RWhjQVyBWk$BCJv`H(-AI!8>t%x1)qm;9 z$DW^h=;Ub#o(T8N9I{#OF4Ji@SO4yFL{kUIuU=;CTRuRt{~)#5BRDB=T4S>mtL*@- z@DZECX(5EKk6Tl6ARG-D8e|ok={7RF(M@h3{R_XYs!BR?q-p~+ID%?9 z4^zEJunVawCN(zn6l{1_W|cWA?v1syhqter7@7 zvpEO_rp)qSeHpx}w-bV)*?knHW569obn@Nk`DQh6mY;m=%+y0C=a8xsH03YZB0tnW z_jOFaL;unn1g!~bhi^r-nmAoRn)$yl2%@T9LkdA8AVLoKf91~7F&14`pmC0Y5>Uw& z5=w>5(?1a9I%H%Wj?jKcG{311?6B26r9>))k^wsFW70m|D;Lnc4z}MTh?CzDf>SU5 z{Exh{1$}Rp*?sh$Z{|LO4W`OA0{kCS4?p@I8jT;e>z$*;>PpnR^g6}bBDEvOX}#?} z8gIFmpfQF@8tAMCy1O;FZ0T62N8r{5OCJHH(y<2FYo8v@QABao$9m0Gn!#{ z>2MM!Mgz`ncH1=122cB_Y&8B6jmGzx_S(tL*PoZ2uRlk6=?!YPzJ>bjZzY=Ck2MCH zXSh7uQFuGB>a70S!yK zNu^4kzYtp#*es`a^)-ssC5p8bbZ70N5b}>zocxIpJny!yh_y4VhHX2G(N=wK=6yy! zyB9(Hf{5ck3FGL2V0`>X%+kWK&cfAT{kbnvJ8=)m!CPqD{x)j2-cC>-Bb=DT=zQRx zR|)llEF^GPz+J>5;yZ$x4Eh!Vv^ zQb)Kz;Q~op8+vJ{wub~&pB(pf^^SG z!i(pB^OrhoKhSSBGH!%6Zm>a9B6?L_-YOrUEML_J17LjyA$Pq9(Dk+r=x2GXJ@xRT zFM&%?!6Zf>!*Z7MqB}5r@UH*pC1vbwxoprLsIgjAyIYFa|YBUKaX9$`tk2HAuRkw-QWD z60|1Dlwko_gEa=RiL(ubnF^uYEOCzze(=$;W%Z{KsA-^bbXHWh7kL*;)f$eBD(zZK)z2mZ%`;7A9K^wX{ojmKD z3k0qvgm|Yz90hkGU$|1YSs&Z$qC0Cu6H~;~2a$~iLWQVsgvVOzk+RZkfcrJqW|9C1IX+yG>WZkA?sAp}?-y>9y*OxL5=`QjYK>Jqxw z$xW~Giqpj@j5#BudJe(G^S}MSZRJD1m+{>T3cZt3cuk)t)0OlCNi)Z}XPpfqC*7ho z`orK7oJ_C|V=Pu0+ESp6rk~{q9L;`0BT2}$A&DcBIH6gu69fTa5E4e=Fq6v2{v;}2 ziVZaPe|;7Kd=PNy!)c86ioG`IEX8VrDGIWFiq;yP=j8o9x-zx*OXM@nuz9wKH5YO2 zMR3nbIQPS+p54vVe!aBct)B&95dv#1)+dK8Clmv|>ti{*m8-JAXa|J>ZSCfJUhjOl z5drghz=Q2f^P}JWF>7&dJ?WUUrq1`m{y*Rk36Ho=sq>pdeo-<J~EM3L)x>oCARVwuf6^2h={^zXZQg|Oc=N!ff>kPKAPKzDye^c64_qIz5 zMlW2!3Cv{)%v$IweN z0vXWDG8%DAGmh!?`!te-Mp9#9Y>YUJh@*&Ftws<81Yt19Zz{`NsRN*d5?H~3^$3Hr z4x>i|&b+`FjnTyb?bL-P?WdSRql=uZ*T)ovM?6#i*%Ucgdr`orqA>Vma7k$Z03ZNK zL_t*d4px8c)K|7EO}pDVxZb^Q^nMy4v?w#mRGDdnWS|UWtn_as z8}0PW+krN3h8Jv}XFCbIIZk-^$e0S^-MH4EjB$Zbs)6fEX4t9X*EPp)6#3kWL2edU zuZQ4!Ij4c=z`cT0za<;Zdt{^eT~3>SqSx0ZSD*XaVC`#PB4|wzA2>q&_?_MyzyBc7 zk;t0toN_QaQ9Mzkrd7at4Dj z*tF;KbFQsWEYG9YSIMtlBwt;|^!wTt*}PD}$AwZ~5>h^iH$CiDC;4Uyde#ZI3Nm+2 zk}WMz%le)KDj4LdEO68VpVzN&mQHSaxpAwp6lp2Q-86LVI_~BBIrskvsh&W{Uyf#v ze#GY45wkcqJNKvmiFo<|$-!Gpnq^R2U9hf$yIXJx!QGwU5L^ZroB)A=;5xVmC%8j` zGq}6E6JYS*?(TB=PSv?}s`iilr)#a@5yo+-XszmKX&&Kj}|`tethbl7ZUrWp=H}~Vp*s#;g|NusugzK(TL`;g>t5< z<9;U2r9EY2;nPWM5$c|E_uLXV@xb~sD6`^SnfGg@E(UD8rRr4E4gAHJsrBG$ptbUS z1dqgiS_f}an^K=~ZabXcX~Zs^sfAVh$C#g`WAa8HaC|W$z5u2^ZVNWdcYpU0(qVs} z*``ha5h2V1HbmvTS4@x>EM!L@d{7StzxCsi#<|(2$u{DQ!y5zlaY6b%OL%XXd#H)` zT5ne)^5F31;f~Zp5}L$QsWFw1L+ZO_F2ya&$E?V5bi`V%`S$EK=@cjRkZ2YP&aBq= zJT{-*JjcaXC+_bK-P__bh{lVaZ?J?Y01@^Sc34p~9y#6SuC7`7%PP#C$ZHC~HT|Xd zCxDue(Skiz-cDpAJPbp31ytl{Q>5p5a@WHa#lrCKYYCRH7EV#-BhF z?D?v0H7krcp|?pZB~UYi6MGm*-f%6MS=)KZ40>KYkr3KsYt)=>X}!N?(t0dx-xg{$ zOYlOJ+bM1EzbHP>P79o1XLxI1V~W1#fwjpJbKeuz!-vWmswn4Qq=OrJLrS=TLH$N{ z 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 z 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≧iJc!veHw97;v0A#`8*=`dprpht7mI zg;id-fLybc7{dywD~;{=b7R&Vm1Xjq>>FUp43?1i=!WJuM2YvYtzSauTGAo^dkK-ac+ zCA1UPJRp;gCalha11@|`l}z=KVG{gocK1>FwwRo{bWCz z%ABS6qNA;9r*HJz9#7H<6lY9`)p3mMWprDum{z2K7R2uK?4(@ofK*-0@8)(jyztkK z$~t({Z{xrqSE#13m~4{7^{>vw*9T6Pg{ydiTu#k*U#mu2!VE4yh@$!%jrF z7WOl6LpmedPCRP1jIpap9{;-wuzQ?Du6YTWs<5^#jH&6YQ7UW7w;lK8Zj55z^i0`~Bz_Uv zID$lp{xt2 zK%7&w#7q|04lrDqNz-+9b^v#1_3TQzY3cM!+mL1WnkK_ipwX!rtNEdJ8JV5@%)@*( zfkIT+(p|yG^Q_hrdp?V0oBV$B>2*$tLAHS7Z|)aXE+8YX?w0vUXOIn=umId3SPo zlX*!aD^`LNP%~44li|&r_A$7 zSyK(=7Js%cgC9<}99Mqo+c{)nm2(U(*i}q6UTYuAD}wSX>Z+=C-Rd%P;s5`_Yq*t} z%)~6r;uph&t5%8{T4^T&)CI2e{(nUz2ESkwqI=s7OiQi>nmwIR8|9}h0MtB!&dm^w z=MQL|!mb>W(0`En*|=zv^!F%QBdJPvG~X)1{474F@9D^6D4JNhGyAWefxrypu17kd zOH@kF$u{=XI9yvb;Y1h~xBxOw`BO|^YyQ;PY^qfmESxg+DD*k}Z0!Iw{131HXVw=i a|JYam5Zv;)_tZfKAn +#endif // STBI_NO_STDIO + +#define STBI_VERSION 1 + +enum +{ + STBI_default = 0, // only used for desired_channels + + STBI_grey = 1, + STBI_grey_alpha = 2, + STBI_rgb = 3, + STBI_rgb_alpha = 4 +}; + +#include +typedef unsigned char stbi_uc; +typedef unsigned short stbi_us; + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef STBIDEF +#ifdef STB_IMAGE_STATIC +#define STBIDEF static +#else +#define STBIDEF extern +#endif +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// PRIMARY API - works on images of any type +// + +// +// load image by filename, open file, or memory buffer +// + +typedef struct +{ + int (*read) (void *user,char *data,int size); // fill 'data' with 'size' bytes. return number of bytes actually read + void (*skip) (void *user,int n); // skip the next 'n' bytes, or 'unget' the last -n bytes if negative + int (*eof) (void *user); // returns nonzero if we are at end of file/data +} stbi_io_callbacks; + +//////////////////////////////////// +// +// 8-bits-per-channel interface +// + +STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *channels_in_file, int desired_channels); + +#ifndef STBI_NO_STDIO +STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +// for stbi_load_from_file, file pointer is left pointing immediately after image +#endif + +#ifndef STBI_NO_GIF +STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp); +#endif + +#ifdef STBI_WINDOWS_UTF8 +STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input); +#endif + +//////////////////////////////////// +// +// 16-bits-per-channel interface +// + +STBIDEF stbi_us *stbi_load_16_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); + +#ifndef STBI_NO_STDIO +STBIDEF stbi_us *stbi_load_16 (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +#endif + +//////////////////////////////////// +// +// float-per-channel interface +// +#ifndef STBI_NO_LINEAR + STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); + + #ifndef STBI_NO_STDIO + STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); + #endif +#endif + +#ifndef STBI_NO_HDR + STBIDEF void stbi_hdr_to_ldr_gamma(float gamma); + STBIDEF void stbi_hdr_to_ldr_scale(float scale); +#endif // STBI_NO_HDR + +#ifndef STBI_NO_LINEAR + STBIDEF void stbi_ldr_to_hdr_gamma(float gamma); + STBIDEF void stbi_ldr_to_hdr_scale(float scale); +#endif // STBI_NO_LINEAR + +// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user); +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len); +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename); +STBIDEF int stbi_is_hdr_from_file(FILE *f); +#endif // STBI_NO_STDIO + + +// get a VERY brief reason for failure +// NOT THREADSAFE +STBIDEF const char *stbi_failure_reason (void); + +// free the loaded image -- this is just free() +STBIDEF void stbi_image_free (void *retval_from_stbi_load); + +// get image dimensions & components without fully decoding +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len); +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *clbk, void *user); + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_bit (char const *filename); +STBIDEF int stbi_is_16_bit_from_file(FILE *f); +#endif + + + +// for image formats that explicitly notate that they have premultiplied alpha, +// we just return the colors as stored in the file. set this flag to force +// unpremultiplication. results are undefined if the unpremultiply overflow. +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply); + +// indicate whether we should process iphone images back to canonical format, +// or just pass them through "as-is" +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert); + +// flip the image vertically, so the first pixel in the output array is the bottom left +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip); + +// ZLIB client - used by PNG, available for other purposes + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen); +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header); +STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + +STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + + +#ifdef __cplusplus +} +#endif + +// +// +//// end header file ///////////////////////////////////////////////////// +#endif // STBI_INCLUDE_STB_IMAGE_H + +#ifdef STB_IMAGE_IMPLEMENTATION + +#if defined(STBI_ONLY_JPEG) || defined(STBI_ONLY_PNG) || defined(STBI_ONLY_BMP) \ + || defined(STBI_ONLY_TGA) || defined(STBI_ONLY_GIF) || defined(STBI_ONLY_PSD) \ + || defined(STBI_ONLY_HDR) || defined(STBI_ONLY_PIC) || defined(STBI_ONLY_PNM) \ + || defined(STBI_ONLY_ZLIB) + #ifndef STBI_ONLY_JPEG + #define STBI_NO_JPEG + #endif + #ifndef STBI_ONLY_PNG + #define STBI_NO_PNG + #endif + #ifndef STBI_ONLY_BMP + #define STBI_NO_BMP + #endif + #ifndef STBI_ONLY_PSD + #define STBI_NO_PSD + #endif + #ifndef STBI_ONLY_TGA + #define STBI_NO_TGA + #endif + #ifndef STBI_ONLY_GIF + #define STBI_NO_GIF + #endif + #ifndef STBI_ONLY_HDR + #define STBI_NO_HDR + #endif + #ifndef STBI_ONLY_PIC + #define STBI_NO_PIC + #endif + #ifndef STBI_ONLY_PNM + #define STBI_NO_PNM + #endif +#endif + +#if defined(STBI_NO_PNG) && !defined(STBI_SUPPORT_ZLIB) && !defined(STBI_NO_ZLIB) +#define STBI_NO_ZLIB +#endif + + +#include +#include // ptrdiff_t on osx +#include +#include +#include + +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +#include // ldexp, pow +#endif + +#ifndef STBI_NO_STDIO +#include +#endif + +#ifndef STBI_ASSERT +#include +#define STBI_ASSERT(x) assert(x) +#endif + +#ifdef __cplusplus +#define STBI_EXTERN extern "C" +#else +#define STBI_EXTERN extern +#endif + + +#ifndef _MSC_VER + #ifdef __cplusplus + #define stbi_inline inline + #else + #define stbi_inline + #endif +#else + #define stbi_inline __forceinline +#endif + + +#ifdef _MSC_VER +typedef unsigned short stbi__uint16; +typedef signed short stbi__int16; +typedef unsigned int stbi__uint32; +typedef signed int stbi__int32; +#else +#include +typedef uint16_t stbi__uint16; +typedef int16_t stbi__int16; +typedef uint32_t stbi__uint32; +typedef int32_t stbi__int32; +#endif + +// should produce compiler error if size is wrong +typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; + +#ifdef _MSC_VER +#define STBI_NOTUSED(v) (void)(v) +#else +#define STBI_NOTUSED(v) (void)sizeof(v) +#endif + +#ifdef _MSC_VER +#define STBI_HAS_LROTL +#endif + +#ifdef STBI_HAS_LROTL + #define stbi_lrot(x,y) _lrotl(x,y) +#else + #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (32 - (y)))) +#endif + +#if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED)) +// ok +#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) && !defined(STBI_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC (or STBI_REALLOC_SIZED)." +#endif + +#ifndef STBI_MALLOC +#define STBI_MALLOC(sz) malloc(sz) +#define STBI_REALLOC(p,newsz) realloc(p,newsz) +#define STBI_FREE(p) free(p) +#endif + +#ifndef STBI_REALLOC_SIZED +#define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz) +#endif + +// x86/x64 detection +#if defined(__x86_64__) || defined(_M_X64) +#define STBI__X64_TARGET +#elif defined(__i386) || defined(_M_IX86) +#define STBI__X86_TARGET +#endif + +#if defined(__GNUC__) && defined(STBI__X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) +// gcc doesn't support sse2 intrinsics unless you compile with -msse2, +// which in turn means it gets to use SSE2 everywhere. This is unfortunate, +// but previous attempts to provide the SSE2 functions with runtime +// detection caused numerous issues. The way architecture extensions are +// exposed in GCC/Clang is, sadly, not really suited for one-file libs. +// New behavior: if compiled with -msse2, we use SSE2 without any +// detection; if not, we don't use it at all. +#define STBI_NO_SIMD +#endif + +#if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD) +// Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET +// +// 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the +// Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant. +// As a result, enabling SSE2 on 32-bit MinGW is dangerous when not +// simultaneously enabling "-mstackrealign". +// +// See https://github.com/nothings/stb/issues/81 for more information. +// +// So default to no SSE2 on 32-bit MinGW. If you've read this far and added +// -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2. +#define STBI_NO_SIMD +#endif + +#if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) +#define STBI_SSE2 +#include + +#ifdef _MSC_VER + +#if _MSC_VER >= 1400 // not VC6 +#include // __cpuid +static int stbi__cpuid3(void) +{ + int info[4]; + __cpuid(info,1); + return info[3]; +} +#else +static int stbi__cpuid3(void) +{ + int res; + __asm { + mov eax,1 + cpuid + mov res,edx + } + return res; +} +#endif + +#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name + +#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2) +static int stbi__sse2_available(void) +{ + int info3 = stbi__cpuid3(); + return ((info3 >> 26) & 1) != 0; +} +#endif + +#else // assume GCC-style if not VC++ +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) + +#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2) +static int stbi__sse2_available(void) +{ + // If we're even attempting to compile this on GCC/Clang, that means + // -msse2 is on, which means the compiler is allowed to use SSE2 + // instructions at will, and so are we. + return 1; +} +#endif + +#endif +#endif + +// ARM NEON +#if defined(STBI_NO_SIMD) && defined(STBI_NEON) +#undef STBI_NEON +#endif + +#ifdef STBI_NEON +#include +// assume GCC or Clang on ARM targets +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) +#endif + +#ifndef STBI_SIMD_ALIGN +#define STBI_SIMD_ALIGN(type, name) type name +#endif + +/////////////////////////////////////////////// +// +// stbi__context struct and start_xxx functions + +// stbi__context structure is our basic context used by all images, so it +// contains all the IO context, plus some basic image information +typedef struct +{ + stbi__uint32 img_x, img_y; + int img_n, img_out_n; + + stbi_io_callbacks io; + void *io_user_data; + + int read_from_callbacks; + int buflen; + stbi_uc buffer_start[128]; + + stbi_uc *img_buffer, *img_buffer_end; + stbi_uc *img_buffer_original, *img_buffer_original_end; +} stbi__context; + + +static void stbi__refill_buffer(stbi__context *s); + +// initialize a memory-decode context +static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len) +{ + s->io.read = NULL; + s->read_from_callbacks = 0; + s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer; + s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len; +} + +// initialize a callback-based context +static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user) +{ + s->io = *c; + s->io_user_data = user; + s->buflen = sizeof(s->buffer_start); + s->read_from_callbacks = 1; + s->img_buffer_original = s->buffer_start; + stbi__refill_buffer(s); + s->img_buffer_original_end = s->img_buffer_end; +} + +#ifndef STBI_NO_STDIO + +static int stbi__stdio_read(void *user, char *data, int size) +{ + return (int) fread(data,1,size,(FILE*) user); +} + +static void stbi__stdio_skip(void *user, int n) +{ + fseek((FILE*) user, n, SEEK_CUR); +} + +static int stbi__stdio_eof(void *user) +{ + return feof((FILE*) user); +} + +static stbi_io_callbacks stbi__stdio_callbacks = +{ + stbi__stdio_read, + stbi__stdio_skip, + stbi__stdio_eof, +}; + +static void stbi__start_file(stbi__context *s, FILE *f) +{ + stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *) f); +} + +//static void stop_file(stbi__context *s) { } + +#endif // !STBI_NO_STDIO + +static void stbi__rewind(stbi__context *s) +{ + // conceptually rewind SHOULD rewind to the beginning of the stream, + // but we just rewind to the beginning of the initial buffer, because + // we only use it after doing 'test', which only ever looks at at most 92 bytes + s->img_buffer = s->img_buffer_original; + s->img_buffer_end = s->img_buffer_original_end; +} + +enum +{ + STBI_ORDER_RGB, + STBI_ORDER_BGR +}; + +typedef struct +{ + int bits_per_channel; + int num_channels; + int channel_order; +} stbi__result_info; + +#ifndef STBI_NO_JPEG +static int stbi__jpeg_test(stbi__context *s); +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNG +static int stbi__png_test(stbi__context *s); +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__png_is16(stbi__context *s); +#endif + +#ifndef STBI_NO_BMP +static int stbi__bmp_test(stbi__context *s); +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_TGA +static int stbi__tga_test(stbi__context *s); +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s); +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc); +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__psd_is16(stbi__context *s); +#endif + +#ifndef STBI_NO_HDR +static int stbi__hdr_test(stbi__context *s); +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_test(stbi__context *s); +static void *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_GIF +static int stbi__gif_test(stbi__context *s); +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp); +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNM +static int stbi__pnm_test(stbi__context *s); +static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +// this is not threadsafe +static const char *stbi__g_failure_reason; + +STBIDEF const char *stbi_failure_reason(void) +{ + return stbi__g_failure_reason; +} + +static int stbi__err(const char *str) +{ + stbi__g_failure_reason = str; + return 0; +} + +static void *stbi__malloc(size_t size) +{ + return STBI_MALLOC(size); +} + +// stb_image uses ints pervasively, including for offset calculations. +// therefore the largest decoded image size we can support with the +// current code, even on 64-bit targets, is INT_MAX. this is not a +// significant limitation for the intended use case. +// +// we do, however, need to make sure our size calculations don't +// overflow. hence a few helper functions for size calculations that +// multiply integers together, making sure that they're non-negative +// and no overflow occurs. + +// return 1 if the sum is valid, 0 on overflow. +// negative terms are considered invalid. +static int stbi__addsizes_valid(int a, int b) +{ + if (b < 0) return 0; + // now 0 <= b <= INT_MAX, hence also + // 0 <= INT_MAX - b <= INTMAX. + // And "a + b <= INT_MAX" (which might overflow) is the + // same as a <= INT_MAX - b (no overflow) + return a <= INT_MAX - b; +} + +// returns 1 if the product is valid, 0 on overflow. +// negative factors are considered invalid. +static int stbi__mul2sizes_valid(int a, int b) +{ + if (a < 0 || b < 0) return 0; + if (b == 0) return 1; // mul-by-0 is always safe + // portable way to check for no overflows in a*b + return a <= INT_MAX/b; +} + +// returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow +static int stbi__mad2sizes_valid(int a, int b, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add); +} + +// returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow +static int stbi__mad3sizes_valid(int a, int b, int c, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__addsizes_valid(a*b*c, add); +} + +// returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, add); +} +#endif + +// mallocs with size overflow checking +static void *stbi__malloc_mad2(int a, int b, int add) +{ + if (!stbi__mad2sizes_valid(a, b, add)) return NULL; + return stbi__malloc(a*b + add); +} + +static void *stbi__malloc_mad3(int a, int b, int c, int add) +{ + if (!stbi__mad3sizes_valid(a, b, c, add)) return NULL; + return stbi__malloc(a*b*c + add); +} + +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +static void *stbi__malloc_mad4(int a, int b, int c, int d, int add) +{ + if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL; + return stbi__malloc(a*b*c*d + add); +} +#endif + +// stbi__err - error +// stbi__errpf - error returning pointer to float +// stbi__errpuc - error returning pointer to unsigned char + +#ifdef STBI_NO_FAILURE_STRINGS + #define stbi__err(x,y) 0 +#elif defined(STBI_FAILURE_USERMSG) + #define stbi__err(x,y) stbi__err(y) +#else + #define stbi__err(x,y) stbi__err(x) +#endif + +#define stbi__errpf(x,y) ((float *)(size_t) (stbi__err(x,y)?NULL:NULL)) +#define stbi__errpuc(x,y) ((unsigned char *)(size_t) (stbi__err(x,y)?NULL:NULL)) + +STBIDEF void stbi_image_free(void *retval_from_stbi_load) +{ + STBI_FREE(retval_from_stbi_load); +} + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp); +#endif + +#ifndef STBI_NO_HDR +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); +#endif + +static int stbi__vertically_flip_on_load = 0; + +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) +{ + stbi__vertically_flip_on_load = flag_true_if_should_flip; +} + +static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) +{ + memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields + ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed + ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order + ri->num_channels = 0; + + #ifndef STBI_NO_JPEG + if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PNG + if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_BMP + if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_GIF + if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PSD + if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc); + #endif + #ifndef STBI_NO_PIC + if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PNM + if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp, ri); + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + float *hdr = stbi__hdr_load(s, x,y,comp,req_comp, ri); + return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); + } + #endif + + #ifndef STBI_NO_TGA + // test tga last because it's a crappy test! + if (stbi__tga_test(s)) + return stbi__tga_load(s,x,y,comp,req_comp, ri); + #endif + + return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt"); +} + +static stbi_uc *stbi__convert_16_to_8(stbi__uint16 *orig, int w, int h, int channels) +{ + int i; + int img_len = w * h * channels; + stbi_uc *reduced; + + reduced = (stbi_uc *) stbi__malloc(img_len); + if (reduced == NULL) return stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is sufficient approx of 16->8 bit scaling + + STBI_FREE(orig); + return reduced; +} + +static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels) +{ + int i; + int img_len = w * h * channels; + stbi__uint16 *enlarged; + + enlarged = (stbi__uint16 *) stbi__malloc(img_len*2); + if (enlarged == NULL) return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + enlarged[i] = (stbi__uint16)((orig[i] << 8) + orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff + + STBI_FREE(orig); + return enlarged; +} + +static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel) +{ + int row; + size_t bytes_per_row = (size_t)w * bytes_per_pixel; + stbi_uc temp[2048]; + stbi_uc *bytes = (stbi_uc *)image; + + for (row = 0; row < (h>>1); row++) { + stbi_uc *row0 = bytes + row*bytes_per_row; + stbi_uc *row1 = bytes + (h - row - 1)*bytes_per_row; + // swap row0 with row1 + size_t bytes_left = bytes_per_row; + while (bytes_left) { + size_t bytes_copy = (bytes_left < sizeof(temp)) ? bytes_left : sizeof(temp); + memcpy(temp, row0, bytes_copy); + memcpy(row0, row1, bytes_copy); + memcpy(row1, temp, bytes_copy); + row0 += bytes_copy; + row1 += bytes_copy; + bytes_left -= bytes_copy; + } + } +} + +#ifndef STBI_NO_GIF +static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel) +{ + int slice; + int slice_size = w * h * bytes_per_pixel; + + stbi_uc *bytes = (stbi_uc *)image; + for (slice = 0; slice < z; ++slice) { + stbi__vertical_flip(bytes, w, h, bytes_per_pixel); + bytes += slice_size; + } +} +#endif + +static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8); + + if (result == NULL) + return NULL; + + if (ri.bits_per_channel != 8) { + STBI_ASSERT(ri.bits_per_channel == 16); + result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 8; + } + + // @TODO: move stbi__convert_format to here + + if (stbi__vertically_flip_on_load) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc)); + } + + return (unsigned char *) result; +} + +static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16); + + if (result == NULL) + return NULL; + + if (ri.bits_per_channel != 16) { + STBI_ASSERT(ri.bits_per_channel == 8); + result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 16; + } + + // @TODO: move stbi__convert_format16 to here + // @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision + + if (stbi__vertically_flip_on_load) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi__uint16)); + } + + return (stbi__uint16 *) result; +} + +#if !defined(STBI_NO_HDR) && !defined(STBI_NO_LINEAR) +static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp) +{ + if (stbi__vertically_flip_on_load && result != NULL) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(float)); + } +} +#endif + +#ifndef STBI_NO_STDIO + +#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) +STBI_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide); +STBI_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default); +#endif + +#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) +STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input) +{ + return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); +} +#endif + +static FILE *stbi__fopen(char const *filename, char const *mode) +{ + FILE *f; +#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8) + wchar_t wMode[64]; + wchar_t wFilename[1024]; + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename))) + return 0; + + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode))) + return 0; + +#if _MSC_VER >= 1400 + if (0 != _wfopen_s(&f, wFilename, wMode)) + f = 0; +#else + f = _wfopen(wFilename, wMode); +#endif + +#elif defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != fopen_s(&f, filename, mode)) + f=0; +#else + f = fopen(filename, mode); +#endif + return f; +} + + +STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + unsigned char *result; + if (!f) return stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} + +STBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__uint16 *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_and_postprocess_16bit(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} + +STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + stbi__uint16 *result; + if (!f) return (stbi_us *) stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file_16(f,x,y,comp,req_comp); + fclose(f); + return result; +} + + +#endif //!STBI_NO_STDIO + +STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + +STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); +} + +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_GIF +STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_mem(&s,buffer,len); + + result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp); + if (stbi__vertically_flip_on_load) { + stbi__vertical_flip_slices( result, *x, *y, *z, *comp ); + } + + return result; +} +#endif + +#ifndef STBI_NO_LINEAR +static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *data; + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + stbi__result_info ri; + float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp, &ri); + if (hdr_data) + stbi__float_postprocess(hdr_data,x,y,comp,req_comp); + return hdr_data; + } + #endif + data = stbi__load_and_postprocess_8bit(s, x, y, comp, req_comp); + if (data) + return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); + return stbi__errpf("unknown image type", "Image not of any known type, or corrupt"); +} + +STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_STDIO +STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + float *result; + FILE *f = stbi__fopen(filename, "rb"); + if (!f) return stbi__errpf("can't fopen", "Unable to open file"); + result = stbi_loadf_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_file(&s,f); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} +#endif // !STBI_NO_STDIO + +#endif // !STBI_NO_LINEAR + +// these is-hdr-or-not is defined independent of whether STBI_NO_LINEAR is +// defined, for API simplicity; if STBI_NO_LINEAR is defined, it always +// reports false! + +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(buffer); + STBI_NOTUSED(len); + return 0; + #endif +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result=0; + if (f) { + result = stbi_is_hdr_from_file(f); + fclose(f); + } + return result; +} + +STBIDEF int stbi_is_hdr_from_file(FILE *f) +{ + #ifndef STBI_NO_HDR + long pos = ftell(f); + int res; + stbi__context s; + stbi__start_file(&s,f); + res = stbi__hdr_test(&s); + fseek(f, pos, SEEK_SET); + return res; + #else + STBI_NOTUSED(f); + return 0; + #endif +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(clbk); + STBI_NOTUSED(user); + return 0; + #endif +} + +#ifndef STBI_NO_LINEAR +static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f; + +STBIDEF void stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; } +STBIDEF void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; } +#endif + +static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f; + +STBIDEF void stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; } +STBIDEF void stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; } + + +////////////////////////////////////////////////////////////////////////////// +// +// Common code used by all image loaders +// + +enum +{ + STBI__SCAN_load=0, + STBI__SCAN_type, + STBI__SCAN_header +}; + +static void stbi__refill_buffer(stbi__context *s) +{ + int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); + if (n == 0) { + // at end of file, treat same as if from memory, but need to handle case + // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file + s->read_from_callbacks = 0; + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start+1; + *s->img_buffer = 0; + } else { + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start + n; + } +} + +stbi_inline static stbi_uc stbi__get8(stbi__context *s) +{ + if (s->img_buffer < s->img_buffer_end) + return *s->img_buffer++; + if (s->read_from_callbacks) { + stbi__refill_buffer(s); + return *s->img_buffer++; + } + return 0; +} + +stbi_inline static int stbi__at_eof(stbi__context *s) +{ + if (s->io.read) { + if (!(s->io.eof)(s->io_user_data)) return 0; + // if feof() is true, check if buffer = end + // special case: we've only got the special 0 character at the end + if (s->read_from_callbacks == 0) return 1; + } + + return s->img_buffer >= s->img_buffer_end; +} + +static void stbi__skip(stbi__context *s, int n) +{ + if (n < 0) { + s->img_buffer = s->img_buffer_end; + return; + } + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + s->img_buffer = s->img_buffer_end; + (s->io.skip)(s->io_user_data, n - blen); + return; + } + } + s->img_buffer += n; +} + +static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) +{ + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + int res, count; + + memcpy(buffer, s->img_buffer, blen); + + count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen); + res = (count == (n-blen)); + s->img_buffer = s->img_buffer_end; + return res; + } + } + + if (s->img_buffer+n <= s->img_buffer_end) { + memcpy(buffer, s->img_buffer, n); + s->img_buffer += n; + return 1; + } else + return 0; +} + +static int stbi__get16be(stbi__context *s) +{ + int z = stbi__get8(s); + return (z << 8) + stbi__get8(s); +} + +static stbi__uint32 stbi__get32be(stbi__context *s) +{ + stbi__uint32 z = stbi__get16be(s); + return (z << 16) + stbi__get16be(s); +} + +#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) +// nothing +#else +static int stbi__get16le(stbi__context *s) +{ + int z = stbi__get8(s); + return z + (stbi__get8(s) << 8); +} +#endif + +#ifndef STBI_NO_BMP +static stbi__uint32 stbi__get32le(stbi__context *s) +{ + stbi__uint32 z = stbi__get16le(s); + return z + (stbi__get16le(s) << 16); +} +#endif + +#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings + + +////////////////////////////////////////////////////////////////////////////// +// +// generic converter from built-in img_n to req_comp +// individual types do this automatically as much as possible (e.g. jpeg +// does all cases internally since it needs to colorspace convert anyway, +// and it never has alpha, so very few cases ). png can automatically +// interleave an alpha=255 channel, but falls back to this for other cases +// +// assume data buffer is malloced, so malloc a new one and free that one +// only failure mode is malloc failing + +static stbi_uc stbi__compute_y(int r, int g, int b) +{ + return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8); +} + +static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + unsigned char *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0); + if (good == NULL) { + STBI_FREE(data); + return stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + unsigned char *src = data + j * x * img_n ; + unsigned char *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=255; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=255; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=255; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = 255; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; + default: STBI_ASSERT(0); + } + #undef STBI__CASE + } + + STBI_FREE(data); + return good; +} + +static stbi__uint16 stbi__compute_y_16(int r, int g, int b) +{ + return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8); +} + +static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + stbi__uint16 *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (stbi__uint16 *) stbi__malloc(req_comp * x * y * 2); + if (good == NULL) { + STBI_FREE(data); + return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + stbi__uint16 *src = data + j * x * img_n ; + stbi__uint16 *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=0xffff; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=0xffff; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=0xffff; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = 0xffff; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; + default: STBI_ASSERT(0); + } + #undef STBI__CASE + } + + STBI_FREE(data); + return good; +} + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) +{ + int i,k,n; + float *output; + if (!data) return NULL; + output = (float *) stbi__malloc_mad4(x, y, comp, sizeof(float), 0); + if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + output[i*comp + k] = (float) (pow(data[i*comp+k]/255.0f, stbi__l2h_gamma) * stbi__l2h_scale); + } + } + if (n < comp) { + for (i=0; i < x*y; ++i) { + output[i*comp + n] = data[i*comp + n]/255.0f; + } + } + STBI_FREE(data); + return output; +} +#endif + +#ifndef STBI_NO_HDR +#define stbi__float2int(x) ((int) (x)) +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp) +{ + int i,k,n; + stbi_uc *output; + if (!data) return NULL; + output = (stbi_uc *) stbi__malloc_mad3(x, y, comp, 0); + if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + float z = (float) pow(data[i*comp+k]*stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + if (k < comp) { + float z = data[i*comp+k] * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + } + STBI_FREE(data); + return output; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// "baseline" JPEG/JFIF decoder +// +// simple implementation +// - doesn't support delayed output of y-dimension +// - simple interface (only one output format: 8-bit interleaved RGB) +// - doesn't try to recover corrupt jpegs +// - doesn't allow partial loading, loading multiple at once +// - still fast on x86 (copying globals into locals doesn't help x86) +// - allocates lots of intermediate memory (full size of all components) +// - non-interleaved case requires this anyway +// - allows good upsampling (see next) +// high-quality +// - upsampled channels are bilinearly interpolated, even across blocks +// - quality integer IDCT derived from IJG's 'slow' +// performance +// - fast huffman; reasonable integer IDCT +// - some SIMD kernels for common paths on targets with SSE2/NEON +// - uses a lot of intermediate memory, could cache poorly + +#ifndef STBI_NO_JPEG + +// huffman decoding acceleration +#define FAST_BITS 9 // larger handles more cases; smaller stomps less cache + +typedef struct +{ + stbi_uc fast[1 << FAST_BITS]; + // weirdly, repacking this into AoS is a 10% speed loss, instead of a win + stbi__uint16 code[256]; + stbi_uc values[256]; + stbi_uc size[257]; + unsigned int maxcode[18]; + int delta[17]; // old 'firstsymbol' - old 'firstcode' +} stbi__huffman; + +typedef struct +{ + stbi__context *s; + stbi__huffman huff_dc[4]; + stbi__huffman huff_ac[4]; + stbi__uint16 dequant[4][64]; + stbi__int16 fast_ac[4][1 << FAST_BITS]; + +// sizes for components, interleaved MCUs + int img_h_max, img_v_max; + int img_mcu_x, img_mcu_y; + int img_mcu_w, img_mcu_h; + +// definition of jpeg image component + struct + { + int id; + int h,v; + int tq; + int hd,ha; + int dc_pred; + + int x,y,w2,h2; + stbi_uc *data; + void *raw_data, *raw_coeff; + stbi_uc *linebuf; + short *coeff; // progressive only + int coeff_w, coeff_h; // number of 8x8 coefficient blocks + } img_comp[4]; + + stbi__uint32 code_buffer; // jpeg entropy-coded buffer + int code_bits; // number of valid bits + unsigned char marker; // marker seen while filling entropy buffer + int nomore; // flag if we saw a marker so must stop + + int progressive; + int spec_start; + int spec_end; + int succ_high; + int succ_low; + int eob_run; + int jfif; + int app14_color_transform; // Adobe APP14 tag + int rgb; + + int scan_n, order[4]; + int restart_interval, todo; + +// kernels + void (*idct_block_kernel)(stbi_uc *out, int out_stride, short data[64]); + void (*YCbCr_to_RGB_kernel)(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step); + stbi_uc *(*resample_row_hv_2_kernel)(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs); +} stbi__jpeg; + +static int stbi__build_huffman(stbi__huffman *h, int *count) +{ + int i,j,k=0; + unsigned int code; + // build size list for each symbol (from JPEG spec) + for (i=0; i < 16; ++i) + for (j=0; j < count[i]; ++j) + h->size[k++] = (stbi_uc) (i+1); + h->size[k] = 0; + + // compute actual symbols (from jpeg spec) + code = 0; + k = 0; + for(j=1; j <= 16; ++j) { + // compute delta to add to code to compute symbol id + h->delta[j] = k - code; + if (h->size[k] == j) { + while (h->size[k] == j) + h->code[k++] = (stbi__uint16) (code++); + if (code-1 >= (1u << j)) return stbi__err("bad code lengths","Corrupt JPEG"); + } + // compute largest code + 1 for this size, preshifted as needed later + h->maxcode[j] = code << (16-j); + code <<= 1; + } + h->maxcode[j] = 0xffffffff; + + // build non-spec acceleration table; 255 is flag for not-accelerated + memset(h->fast, 255, 1 << FAST_BITS); + for (i=0; i < k; ++i) { + int s = h->size[i]; + if (s <= FAST_BITS) { + int c = h->code[i] << (FAST_BITS-s); + int m = 1 << (FAST_BITS-s); + for (j=0; j < m; ++j) { + h->fast[c+j] = (stbi_uc) i; + } + } + } + return 1; +} + +// build a table that decodes both magnitude and value of small ACs in +// one go. +static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h) +{ + int i; + for (i=0; i < (1 << FAST_BITS); ++i) { + stbi_uc fast = h->fast[i]; + fast_ac[i] = 0; + if (fast < 255) { + int rs = h->values[fast]; + int run = (rs >> 4) & 15; + int magbits = rs & 15; + int len = h->size[fast]; + + if (magbits && len + magbits <= FAST_BITS) { + // magnitude code followed by receive_extend code + int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits); + int m = 1 << (magbits - 1); + if (k < m) k += (~0U << magbits) + 1; + // if the result is small enough, we can fit it in fast_ac table + if (k >= -128 && k <= 127) + fast_ac[i] = (stbi__int16) ((k * 256) + (run * 16) + (len + magbits)); + } + } + } +} + +static void stbi__grow_buffer_unsafe(stbi__jpeg *j) +{ + do { + unsigned int b = j->nomore ? 0 : stbi__get8(j->s); + if (b == 0xff) { + int c = stbi__get8(j->s); + while (c == 0xff) c = stbi__get8(j->s); // consume fill bytes + if (c != 0) { + j->marker = (unsigned char) c; + j->nomore = 1; + return; + } + } + j->code_buffer |= b << (24 - j->code_bits); + j->code_bits += 8; + } while (j->code_bits <= 24); +} + +// (1 << n) - 1 +static const stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; + +// decode a jpeg huffman value from the bitstream +stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) +{ + unsigned int temp; + int c,k; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + // look at the top FAST_BITS and determine what symbol ID it is, + // if the code is <= FAST_BITS + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + k = h->fast[c]; + if (k < 255) { + int s = h->size[k]; + if (s > j->code_bits) + return -1; + j->code_buffer <<= s; + j->code_bits -= s; + return h->values[k]; + } + + // naive test is to shift the code_buffer down so k bits are + // valid, then test against maxcode. To speed this up, we've + // preshifted maxcode left so that it has (16-k) 0s at the + // end; in other words, regardless of the number of bits, it + // wants to be compared against something shifted to have 16; + // that way we don't need to shift inside the loop. + temp = j->code_buffer >> 16; + for (k=FAST_BITS+1 ; ; ++k) + if (temp < h->maxcode[k]) + break; + if (k == 17) { + // error! code not found + j->code_bits -= 16; + return -1; + } + + if (k > j->code_bits) + return -1; + + // convert the huffman code to the symbol id + c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k]; + STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]); + + // convert the id to a symbol + j->code_bits -= k; + j->code_buffer <<= k; + return h->values[c]; +} + +// bias[n] = (-1<code_bits < n) stbi__grow_buffer_unsafe(j); + + sgn = (stbi__int32)j->code_buffer >> 31; // sign bit is always in MSB + k = stbi_lrot(j->code_buffer, n); + STBI_ASSERT(n >= 0 && n < (int) (sizeof(stbi__bmask)/sizeof(*stbi__bmask))); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k + (stbi__jbias[n] & ~sgn); +} + +// get some unsigned bits +stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n) +{ + unsigned int k; + if (j->code_bits < n) stbi__grow_buffer_unsafe(j); + k = stbi_lrot(j->code_buffer, n); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k; +} + +stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j) +{ + unsigned int k; + if (j->code_bits < 1) stbi__grow_buffer_unsafe(j); + k = j->code_buffer; + j->code_buffer <<= 1; + --j->code_bits; + return k & 0x80000000; +} + +// given a value that's at position X in the zigzag stream, +// where does it appear in the 8x8 matrix coded as row-major? +static const stbi_uc stbi__jpeg_dezigzag[64+15] = +{ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + // let corrupt input sample past end + 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63 +}; + +// decode one 64-entry block-- +static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi__uint16 *dequant) +{ + int diff,dc,k; + int t; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + t = stbi__jpeg_huff_decode(j, hdc); + if (t < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + + // 0 all the ac values now so we can do it 32-bits at a time + memset(data,0,64*sizeof(data[0])); + + diff = t ? stbi__extend_receive(j, t) : 0; + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + data[0] = (short) (dc * dequant[0]); + + // decode AC components, see JPEG spec + k = 1; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + j->code_buffer <<= s; + j->code_bits -= s; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) * dequant[zig]); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (rs != 0xf0) break; // end block + k += 16; + } else { + k += r; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) * dequant[zig]); + } + } + } while (k < 64); + return 1; +} + +static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__huffman *hdc, int b) +{ + int diff,dc; + int t; + if (j->spec_end != 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + if (j->succ_high == 0) { + // first scan for DC coefficient, must be first + memset(data,0,64*sizeof(data[0])); // 0 all the ac values now + t = stbi__jpeg_huff_decode(j, hdc); + diff = t ? stbi__extend_receive(j, t) : 0; + + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + data[0] = (short) (dc << j->succ_low); + } else { + // refinement scan for DC coefficient + if (stbi__jpeg_get_bit(j)) + data[0] += (short) (1 << j->succ_low); + } + return 1; +} + +// @OPTIMIZE: store non-zigzagged during the decode passes, +// and only de-zigzag when dequantizing +static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__huffman *hac, stbi__int16 *fac) +{ + int k; + if (j->spec_start == 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->succ_high == 0) { + int shift = j->succ_low; + + if (j->eob_run) { + --j->eob_run; + return 1; + } + + k = j->spec_start; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + j->code_buffer <<= s; + j->code_bits -= s; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) << shift); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r); + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + --j->eob_run; + break; + } + k += 16; + } else { + k += r; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) << shift); + } + } + } while (k <= j->spec_end); + } else { + // refinement scan for these AC coefficients + + short bit = (short) (1 << j->succ_low); + + if (j->eob_run) { + --j->eob_run; + for (k = j->spec_start; k <= j->spec_end; ++k) { + short *p = &data[stbi__jpeg_dezigzag[k]]; + if (*p != 0) + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } + } else { + k = j->spec_start; + do { + int r,s; + int rs = stbi__jpeg_huff_decode(j, hac); // @OPTIMIZE see if we can use the fast path here, advance-by-r is so slow, eh + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r) - 1; + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + r = 64; // force end of block + } else { + // r=15 s=0 should write 16 0s, so we just do + // a run of 15 0s and then write s (which is 0), + // so we don't have to do anything special here + } + } else { + if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG"); + // sign bit + if (stbi__jpeg_get_bit(j)) + s = bit; + else + s = -bit; + } + + // advance by r + while (k <= j->spec_end) { + short *p = &data[stbi__jpeg_dezigzag[k++]]; + if (*p != 0) { + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } else { + if (r == 0) { + *p = (short) s; + break; + } + --r; + } + } + } while (k <= j->spec_end); + } + } + return 1; +} + +// take a -128..127 value and stbi__clamp it and convert to 0..255 +stbi_inline static stbi_uc stbi__clamp(int x) +{ + // trick to use a single test to catch both cases + if ((unsigned int) x > 255) { + if (x < 0) return 0; + if (x > 255) return 255; + } + return (stbi_uc) x; +} + +#define stbi__f2f(x) ((int) (((x) * 4096 + 0.5))) +#define stbi__fsh(x) ((x) * 4096) + +// derived from jidctint -- DCT_ISLOW +#define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ + int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \ + p2 = s2; \ + p3 = s6; \ + p1 = (p2+p3) * stbi__f2f(0.5411961f); \ + t2 = p1 + p3*stbi__f2f(-1.847759065f); \ + t3 = p1 + p2*stbi__f2f( 0.765366865f); \ + p2 = s0; \ + p3 = s4; \ + t0 = stbi__fsh(p2+p3); \ + t1 = stbi__fsh(p2-p3); \ + x0 = t0+t3; \ + x3 = t0-t3; \ + x1 = t1+t2; \ + x2 = t1-t2; \ + t0 = s7; \ + t1 = s5; \ + t2 = s3; \ + t3 = s1; \ + p3 = t0+t2; \ + p4 = t1+t3; \ + p1 = t0+t3; \ + p2 = t1+t2; \ + p5 = (p3+p4)*stbi__f2f( 1.175875602f); \ + t0 = t0*stbi__f2f( 0.298631336f); \ + t1 = t1*stbi__f2f( 2.053119869f); \ + t2 = t2*stbi__f2f( 3.072711026f); \ + t3 = t3*stbi__f2f( 1.501321110f); \ + p1 = p5 + p1*stbi__f2f(-0.899976223f); \ + p2 = p5 + p2*stbi__f2f(-2.562915447f); \ + p3 = p3*stbi__f2f(-1.961570560f); \ + p4 = p4*stbi__f2f(-0.390180644f); \ + t3 += p1+p4; \ + t2 += p2+p3; \ + t1 += p2+p4; \ + t0 += p1+p3; + +static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64]) +{ + int i,val[64],*v=val; + stbi_uc *o; + short *d = data; + + // columns + for (i=0; i < 8; ++i,++d, ++v) { + // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing + if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 + && d[40]==0 && d[48]==0 && d[56]==0) { + // no shortcut 0 seconds + // (1|2|3|4|5|6|7)==0 0 seconds + // all separate -0.047 seconds + // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds + int dcterm = d[0]*4; + v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; + } else { + STBI__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56]) + // constants scaled things up by 1<<12; let's bring them back + // down, but keep 2 extra bits of precision + x0 += 512; x1 += 512; x2 += 512; x3 += 512; + v[ 0] = (x0+t3) >> 10; + v[56] = (x0-t3) >> 10; + v[ 8] = (x1+t2) >> 10; + v[48] = (x1-t2) >> 10; + v[16] = (x2+t1) >> 10; + v[40] = (x2-t1) >> 10; + v[24] = (x3+t0) >> 10; + v[32] = (x3-t0) >> 10; + } + } + + for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { + // no fast case since the first 1D IDCT spread components out + STBI__IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) + // constants scaled things up by 1<<12, plus we had 1<<2 from first + // loop, plus horizontal and vertical each scale by sqrt(8) so together + // we've got an extra 1<<3, so 1<<17 total we need to remove. + // so we want to round that, which means adding 0.5 * 1<<17, + // aka 65536. Also, we'll end up with -128 to 127 that we want + // to encode as 0..255 by adding 128, so we'll add that before the shift + x0 += 65536 + (128<<17); + x1 += 65536 + (128<<17); + x2 += 65536 + (128<<17); + x3 += 65536 + (128<<17); + // tried computing the shifts into temps, or'ing the temps to see + // if any were out of range, but that was slower + o[0] = stbi__clamp((x0+t3) >> 17); + o[7] = stbi__clamp((x0-t3) >> 17); + o[1] = stbi__clamp((x1+t2) >> 17); + o[6] = stbi__clamp((x1-t2) >> 17); + o[2] = stbi__clamp((x2+t1) >> 17); + o[5] = stbi__clamp((x2-t1) >> 17); + o[3] = stbi__clamp((x3+t0) >> 17); + o[4] = stbi__clamp((x3-t0) >> 17); + } +} + +#ifdef STBI_SSE2 +// sse2 integer IDCT. not the fastest possible implementation but it +// produces bit-identical results to the generic C version so it's +// fully "transparent". +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + // This is constructed to match our regular (generic) integer IDCT exactly. + __m128i row0, row1, row2, row3, row4, row5, row6, row7; + __m128i tmp; + + // dot product constant: even elems=x, odd elems=y + #define dct_const(x,y) _mm_setr_epi16((x),(y),(x),(y),(x),(y),(x),(y)) + + // out(0) = c0[even]*x + c0[odd]*y (c0, x, y 16-bit, out 32-bit) + // out(1) = c1[even]*x + c1[odd]*y + #define dct_rot(out0,out1, x,y,c0,c1) \ + __m128i c0##lo = _mm_unpacklo_epi16((x),(y)); \ + __m128i c0##hi = _mm_unpackhi_epi16((x),(y)); \ + __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \ + __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \ + __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \ + __m128i out1##_h = _mm_madd_epi16(c0##hi, c1) + + // out = in << 12 (in 16-bit, out 32-bit) + #define dct_widen(out, in) \ + __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \ + __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4) + + // wide add + #define dct_wadd(out, a, b) \ + __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_add_epi32(a##_h, b##_h) + + // wide sub + #define dct_wsub(out, a, b) \ + __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_sub_epi32(a##_h, b##_h) + + // butterfly a/b, add bias, then shift by "s" and pack + #define dct_bfly32o(out0, out1, a,b,bias,s) \ + { \ + __m128i abiased_l = _mm_add_epi32(a##_l, bias); \ + __m128i abiased_h = _mm_add_epi32(a##_h, bias); \ + dct_wadd(sum, abiased, b); \ + dct_wsub(dif, abiased, b); \ + out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \ + out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \ + } + + // 8-bit interleave step (for transposes) + #define dct_interleave8(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi8(a, b); \ + b = _mm_unpackhi_epi8(tmp, b) + + // 16-bit interleave step (for transposes) + #define dct_interleave16(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi16(a, b); \ + b = _mm_unpackhi_epi16(tmp, b) + + #define dct_pass(bias,shift) \ + { \ + /* even part */ \ + dct_rot(t2e,t3e, row2,row6, rot0_0,rot0_1); \ + __m128i sum04 = _mm_add_epi16(row0, row4); \ + __m128i dif04 = _mm_sub_epi16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + dct_rot(y0o,y2o, row7,row3, rot2_0,rot2_1); \ + dct_rot(y1o,y3o, row5,row1, rot3_0,rot3_1); \ + __m128i sum17 = _mm_add_epi16(row1, row7); \ + __m128i sum35 = _mm_add_epi16(row3, row5); \ + dct_rot(y4o,y5o, sum17,sum35, rot1_0,rot1_1); \ + dct_wadd(x4, y0o, y4o); \ + dct_wadd(x5, y1o, y5o); \ + dct_wadd(x6, y2o, y5o); \ + dct_wadd(x7, y3o, y4o); \ + dct_bfly32o(row0,row7, x0,x7,bias,shift); \ + dct_bfly32o(row1,row6, x1,x6,bias,shift); \ + dct_bfly32o(row2,row5, x2,x5,bias,shift); \ + dct_bfly32o(row3,row4, x3,x4,bias,shift); \ + } + + __m128i rot0_0 = dct_const(stbi__f2f(0.5411961f), stbi__f2f(0.5411961f) + stbi__f2f(-1.847759065f)); + __m128i rot0_1 = dct_const(stbi__f2f(0.5411961f) + stbi__f2f( 0.765366865f), stbi__f2f(0.5411961f)); + __m128i rot1_0 = dct_const(stbi__f2f(1.175875602f) + stbi__f2f(-0.899976223f), stbi__f2f(1.175875602f)); + __m128i rot1_1 = dct_const(stbi__f2f(1.175875602f), stbi__f2f(1.175875602f) + stbi__f2f(-2.562915447f)); + __m128i rot2_0 = dct_const(stbi__f2f(-1.961570560f) + stbi__f2f( 0.298631336f), stbi__f2f(-1.961570560f)); + __m128i rot2_1 = dct_const(stbi__f2f(-1.961570560f), stbi__f2f(-1.961570560f) + stbi__f2f( 3.072711026f)); + __m128i rot3_0 = dct_const(stbi__f2f(-0.390180644f) + stbi__f2f( 2.053119869f), stbi__f2f(-0.390180644f)); + __m128i rot3_1 = dct_const(stbi__f2f(-0.390180644f), stbi__f2f(-0.390180644f) + stbi__f2f( 1.501321110f)); + + // rounding biases in column/row passes, see stbi__idct_block for explanation. + __m128i bias_0 = _mm_set1_epi32(512); + __m128i bias_1 = _mm_set1_epi32(65536 + (128<<17)); + + // load + row0 = _mm_load_si128((const __m128i *) (data + 0*8)); + row1 = _mm_load_si128((const __m128i *) (data + 1*8)); + row2 = _mm_load_si128((const __m128i *) (data + 2*8)); + row3 = _mm_load_si128((const __m128i *) (data + 3*8)); + row4 = _mm_load_si128((const __m128i *) (data + 4*8)); + row5 = _mm_load_si128((const __m128i *) (data + 5*8)); + row6 = _mm_load_si128((const __m128i *) (data + 6*8)); + row7 = _mm_load_si128((const __m128i *) (data + 7*8)); + + // column pass + dct_pass(bias_0, 10); + + { + // 16bit 8x8 transpose pass 1 + dct_interleave16(row0, row4); + dct_interleave16(row1, row5); + dct_interleave16(row2, row6); + dct_interleave16(row3, row7); + + // transpose pass 2 + dct_interleave16(row0, row2); + dct_interleave16(row1, row3); + dct_interleave16(row4, row6); + dct_interleave16(row5, row7); + + // transpose pass 3 + dct_interleave16(row0, row1); + dct_interleave16(row2, row3); + dct_interleave16(row4, row5); + dct_interleave16(row6, row7); + } + + // row pass + dct_pass(bias_1, 17); + + { + // pack + __m128i p0 = _mm_packus_epi16(row0, row1); // a0a1a2a3...a7b0b1b2b3...b7 + __m128i p1 = _mm_packus_epi16(row2, row3); + __m128i p2 = _mm_packus_epi16(row4, row5); + __m128i p3 = _mm_packus_epi16(row6, row7); + + // 8bit 8x8 transpose pass 1 + dct_interleave8(p0, p2); // a0e0a1e1... + dct_interleave8(p1, p3); // c0g0c1g1... + + // transpose pass 2 + dct_interleave8(p0, p1); // a0c0e0g0... + dct_interleave8(p2, p3); // b0d0f0h0... + + // transpose pass 3 + dct_interleave8(p0, p2); // a0b0c0d0... + dct_interleave8(p1, p3); // a4b4c4d4... + + // store + _mm_storel_epi64((__m128i *) out, p0); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p0, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p2); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p2, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p1); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p1, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p3); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p3, 0x4e)); + } + +#undef dct_const +#undef dct_rot +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_interleave8 +#undef dct_interleave16 +#undef dct_pass +} + +#endif // STBI_SSE2 + +#ifdef STBI_NEON + +// NEON integer IDCT. should produce bit-identical +// results to the generic C version. +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + int16x8_t row0, row1, row2, row3, row4, row5, row6, row7; + + int16x4_t rot0_0 = vdup_n_s16(stbi__f2f(0.5411961f)); + int16x4_t rot0_1 = vdup_n_s16(stbi__f2f(-1.847759065f)); + int16x4_t rot0_2 = vdup_n_s16(stbi__f2f( 0.765366865f)); + int16x4_t rot1_0 = vdup_n_s16(stbi__f2f( 1.175875602f)); + int16x4_t rot1_1 = vdup_n_s16(stbi__f2f(-0.899976223f)); + int16x4_t rot1_2 = vdup_n_s16(stbi__f2f(-2.562915447f)); + int16x4_t rot2_0 = vdup_n_s16(stbi__f2f(-1.961570560f)); + int16x4_t rot2_1 = vdup_n_s16(stbi__f2f(-0.390180644f)); + int16x4_t rot3_0 = vdup_n_s16(stbi__f2f( 0.298631336f)); + int16x4_t rot3_1 = vdup_n_s16(stbi__f2f( 2.053119869f)); + int16x4_t rot3_2 = vdup_n_s16(stbi__f2f( 3.072711026f)); + int16x4_t rot3_3 = vdup_n_s16(stbi__f2f( 1.501321110f)); + +#define dct_long_mul(out, inq, coeff) \ + int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff) + +#define dct_long_mac(out, acc, inq, coeff) \ + int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff) + +#define dct_widen(out, inq) \ + int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \ + int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12) + +// wide add +#define dct_wadd(out, a, b) \ + int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vaddq_s32(a##_h, b##_h) + +// wide sub +#define dct_wsub(out, a, b) \ + int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vsubq_s32(a##_h, b##_h) + +// butterfly a/b, then shift using "shiftop" by "s" and pack +#define dct_bfly32o(out0,out1, a,b,shiftop,s) \ + { \ + dct_wadd(sum, a, b); \ + dct_wsub(dif, a, b); \ + out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \ + out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \ + } + +#define dct_pass(shiftop, shift) \ + { \ + /* even part */ \ + int16x8_t sum26 = vaddq_s16(row2, row6); \ + dct_long_mul(p1e, sum26, rot0_0); \ + dct_long_mac(t2e, p1e, row6, rot0_1); \ + dct_long_mac(t3e, p1e, row2, rot0_2); \ + int16x8_t sum04 = vaddq_s16(row0, row4); \ + int16x8_t dif04 = vsubq_s16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + int16x8_t sum15 = vaddq_s16(row1, row5); \ + int16x8_t sum17 = vaddq_s16(row1, row7); \ + int16x8_t sum35 = vaddq_s16(row3, row5); \ + int16x8_t sum37 = vaddq_s16(row3, row7); \ + int16x8_t sumodd = vaddq_s16(sum17, sum35); \ + dct_long_mul(p5o, sumodd, rot1_0); \ + dct_long_mac(p1o, p5o, sum17, rot1_1); \ + dct_long_mac(p2o, p5o, sum35, rot1_2); \ + dct_long_mul(p3o, sum37, rot2_0); \ + dct_long_mul(p4o, sum15, rot2_1); \ + dct_wadd(sump13o, p1o, p3o); \ + dct_wadd(sump24o, p2o, p4o); \ + dct_wadd(sump23o, p2o, p3o); \ + dct_wadd(sump14o, p1o, p4o); \ + dct_long_mac(x4, sump13o, row7, rot3_0); \ + dct_long_mac(x5, sump24o, row5, rot3_1); \ + dct_long_mac(x6, sump23o, row3, rot3_2); \ + dct_long_mac(x7, sump14o, row1, rot3_3); \ + dct_bfly32o(row0,row7, x0,x7,shiftop,shift); \ + dct_bfly32o(row1,row6, x1,x6,shiftop,shift); \ + dct_bfly32o(row2,row5, x2,x5,shiftop,shift); \ + dct_bfly32o(row3,row4, x3,x4,shiftop,shift); \ + } + + // load + row0 = vld1q_s16(data + 0*8); + row1 = vld1q_s16(data + 1*8); + row2 = vld1q_s16(data + 2*8); + row3 = vld1q_s16(data + 3*8); + row4 = vld1q_s16(data + 4*8); + row5 = vld1q_s16(data + 5*8); + row6 = vld1q_s16(data + 6*8); + row7 = vld1q_s16(data + 7*8); + + // add DC bias + row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0)); + + // column pass + dct_pass(vrshrn_n_s32, 10); + + // 16bit 8x8 transpose + { +// these three map to a single VTRN.16, VTRN.32, and VSWP, respectively. +// whether compilers actually get this is another story, sadly. +#define dct_trn16(x, y) { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn32(x, y) { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); } +#define dct_trn64(x, y) { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); } + + // pass 1 + dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6 + dct_trn16(row2, row3); + dct_trn16(row4, row5); + dct_trn16(row6, row7); + + // pass 2 + dct_trn32(row0, row2); // a0b0c0d0a4b4c4d4 + dct_trn32(row1, row3); + dct_trn32(row4, row6); + dct_trn32(row5, row7); + + // pass 3 + dct_trn64(row0, row4); // a0b0c0d0e0f0g0h0 + dct_trn64(row1, row5); + dct_trn64(row2, row6); + dct_trn64(row3, row7); + +#undef dct_trn16 +#undef dct_trn32 +#undef dct_trn64 + } + + // row pass + // vrshrn_n_s32 only supports shifts up to 16, we need + // 17. so do a non-rounding shift of 16 first then follow + // up with a rounding shift by 1. + dct_pass(vshrn_n_s32, 16); + + { + // pack and round + uint8x8_t p0 = vqrshrun_n_s16(row0, 1); + uint8x8_t p1 = vqrshrun_n_s16(row1, 1); + uint8x8_t p2 = vqrshrun_n_s16(row2, 1); + uint8x8_t p3 = vqrshrun_n_s16(row3, 1); + uint8x8_t p4 = vqrshrun_n_s16(row4, 1); + uint8x8_t p5 = vqrshrun_n_s16(row5, 1); + uint8x8_t p6 = vqrshrun_n_s16(row6, 1); + uint8x8_t p7 = vqrshrun_n_s16(row7, 1); + + // again, these can translate into one instruction, but often don't. +#define dct_trn8_8(x, y) { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn8_16(x, y) { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); } +#define dct_trn8_32(x, y) { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); } + + // sadly can't use interleaved stores here since we only write + // 8 bytes to each scan line! + + // 8x8 8-bit transpose pass 1 + dct_trn8_8(p0, p1); + dct_trn8_8(p2, p3); + dct_trn8_8(p4, p5); + dct_trn8_8(p6, p7); + + // pass 2 + dct_trn8_16(p0, p2); + dct_trn8_16(p1, p3); + dct_trn8_16(p4, p6); + dct_trn8_16(p5, p7); + + // pass 3 + dct_trn8_32(p0, p4); + dct_trn8_32(p1, p5); + dct_trn8_32(p2, p6); + dct_trn8_32(p3, p7); + + // store + vst1_u8(out, p0); out += out_stride; + vst1_u8(out, p1); out += out_stride; + vst1_u8(out, p2); out += out_stride; + vst1_u8(out, p3); out += out_stride; + vst1_u8(out, p4); out += out_stride; + vst1_u8(out, p5); out += out_stride; + vst1_u8(out, p6); out += out_stride; + vst1_u8(out, p7); + +#undef dct_trn8_8 +#undef dct_trn8_16 +#undef dct_trn8_32 + } + +#undef dct_long_mul +#undef dct_long_mac +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_pass +} + +#endif // STBI_NEON + +#define STBI__MARKER_none 0xff +// if there's a pending marker from the entropy stream, return that +// otherwise, fetch from the stream and get a marker. if there's no +// marker, return 0xff, which is never a valid marker value +static stbi_uc stbi__get_marker(stbi__jpeg *j) +{ + stbi_uc x; + if (j->marker != STBI__MARKER_none) { x = j->marker; j->marker = STBI__MARKER_none; return x; } + x = stbi__get8(j->s); + if (x != 0xff) return STBI__MARKER_none; + while (x == 0xff) + x = stbi__get8(j->s); // consume repeated 0xff fill bytes + return x; +} + +// in each scan, we'll have scan_n components, and the order +// of the components is specified by order[] +#define STBI__RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7) + +// after a restart interval, stbi__jpeg_reset the entropy decoder and +// the dc prediction +static void stbi__jpeg_reset(stbi__jpeg *j) +{ + j->code_bits = 0; + j->code_buffer = 0; + j->nomore = 0; + j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = j->img_comp[3].dc_pred = 0; + j->marker = STBI__MARKER_none; + j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; + j->eob_run = 0; + // no more than 1<<31 MCUs if no restart_interal? that's plenty safe, + // since we don't even allow 1<<30 pixels +} + +static int stbi__parse_entropy_coded_data(stbi__jpeg *z) +{ + stbi__jpeg_reset(z); + if (!z->progressive) { + if (z->scan_n == 1) { + int i,j; + STBI_SIMD_ALIGN(short, data[64]); + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + // if it's NOT a restart, then just bail, so we get corrupt data + // rather than no data + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + STBI_SIMD_ALIGN(short, data[64]); + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x)*8; + int y2 = (j*z->img_comp[n].v + y)*8; + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data); + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } else { + if (z->scan_n == 1) { + int i,j; + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + if (z->spec_start == 0) { + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } else { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block_prog_ac(z, data, &z->huff_ac[ha], z->fast_ac[ha])) + return 0; + } + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x); + int y2 = (j*z->img_comp[n].v + y); + short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w); + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } +} + +static void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant) +{ + int i; + for (i=0; i < 64; ++i) + data[i] *= dequant[i]; +} + +static void stbi__jpeg_finish(stbi__jpeg *z) +{ + if (z->progressive) { + // dequantize and idct the data + int i,j,n; + for (n=0; n < z->s->img_n; ++n) { + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + stbi__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]); + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + } + } + } + } +} + +static int stbi__process_marker(stbi__jpeg *z, int m) +{ + int L; + switch (m) { + case STBI__MARKER_none: // no marker found + return stbi__err("expected marker","Corrupt JPEG"); + + case 0xDD: // DRI - specify restart interval + if (stbi__get16be(z->s) != 4) return stbi__err("bad DRI len","Corrupt JPEG"); + z->restart_interval = stbi__get16be(z->s); + return 1; + + case 0xDB: // DQT - define quantization table + L = stbi__get16be(z->s)-2; + while (L > 0) { + int q = stbi__get8(z->s); + int p = q >> 4, sixteen = (p != 0); + int t = q & 15,i; + if (p != 0 && p != 1) return stbi__err("bad DQT type","Corrupt JPEG"); + if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG"); + + for (i=0; i < 64; ++i) + z->dequant[t][stbi__jpeg_dezigzag[i]] = (stbi__uint16)(sixteen ? stbi__get16be(z->s) : stbi__get8(z->s)); + L -= (sixteen ? 129 : 65); + } + return L==0; + + case 0xC4: // DHT - define huffman table + L = stbi__get16be(z->s)-2; + while (L > 0) { + stbi_uc *v; + int sizes[16],i,n=0; + int q = stbi__get8(z->s); + int tc = q >> 4; + int th = q & 15; + if (tc > 1 || th > 3) return stbi__err("bad DHT header","Corrupt JPEG"); + for (i=0; i < 16; ++i) { + sizes[i] = stbi__get8(z->s); + n += sizes[i]; + } + L -= 17; + if (tc == 0) { + if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0; + v = z->huff_dc[th].values; + } else { + if (!stbi__build_huffman(z->huff_ac+th, sizes)) return 0; + v = z->huff_ac[th].values; + } + for (i=0; i < n; ++i) + v[i] = stbi__get8(z->s); + if (tc != 0) + stbi__build_fast_ac(z->fast_ac[th], z->huff_ac + th); + L -= n; + } + return L==0; + } + + // check for comment block or APP blocks + if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { + L = stbi__get16be(z->s); + if (L < 2) { + if (m == 0xFE) + return stbi__err("bad COM len","Corrupt JPEG"); + else + return stbi__err("bad APP len","Corrupt JPEG"); + } + L -= 2; + + if (m == 0xE0 && L >= 5) { // JFIF APP0 segment + static const unsigned char tag[5] = {'J','F','I','F','\0'}; + int ok = 1; + int i; + for (i=0; i < 5; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 5; + if (ok) + z->jfif = 1; + } else if (m == 0xEE && L >= 12) { // Adobe APP14 segment + static const unsigned char tag[6] = {'A','d','o','b','e','\0'}; + int ok = 1; + int i; + for (i=0; i < 6; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 6; + if (ok) { + stbi__get8(z->s); // version + stbi__get16be(z->s); // flags0 + stbi__get16be(z->s); // flags1 + z->app14_color_transform = stbi__get8(z->s); // color transform + L -= 6; + } + } + + stbi__skip(z->s, L); + return 1; + } + + return stbi__err("unknown marker","Corrupt JPEG"); +} + +// after we see SOS +static int stbi__process_scan_header(stbi__jpeg *z) +{ + int i; + int Ls = stbi__get16be(z->s); + z->scan_n = stbi__get8(z->s); + if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return stbi__err("bad SOS component count","Corrupt JPEG"); + if (Ls != 6+2*z->scan_n) return stbi__err("bad SOS len","Corrupt JPEG"); + for (i=0; i < z->scan_n; ++i) { + int id = stbi__get8(z->s), which; + int q = stbi__get8(z->s); + for (which = 0; which < z->s->img_n; ++which) + if (z->img_comp[which].id == id) + break; + if (which == z->s->img_n) return 0; // no match + z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return stbi__err("bad DC huff","Corrupt JPEG"); + z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return stbi__err("bad AC huff","Corrupt JPEG"); + z->order[i] = which; + } + + { + int aa; + z->spec_start = stbi__get8(z->s); + z->spec_end = stbi__get8(z->s); // should be 63, but might be 0 + aa = stbi__get8(z->s); + z->succ_high = (aa >> 4); + z->succ_low = (aa & 15); + if (z->progressive) { + if (z->spec_start > 63 || z->spec_end > 63 || z->spec_start > z->spec_end || z->succ_high > 13 || z->succ_low > 13) + return stbi__err("bad SOS", "Corrupt JPEG"); + } else { + if (z->spec_start != 0) return stbi__err("bad SOS","Corrupt JPEG"); + if (z->succ_high != 0 || z->succ_low != 0) return stbi__err("bad SOS","Corrupt JPEG"); + z->spec_end = 63; + } + } + + return 1; +} + +static int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why) +{ + int i; + for (i=0; i < ncomp; ++i) { + if (z->img_comp[i].raw_data) { + STBI_FREE(z->img_comp[i].raw_data); + z->img_comp[i].raw_data = NULL; + z->img_comp[i].data = NULL; + } + if (z->img_comp[i].raw_coeff) { + STBI_FREE(z->img_comp[i].raw_coeff); + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].coeff = 0; + } + if (z->img_comp[i].linebuf) { + STBI_FREE(z->img_comp[i].linebuf); + z->img_comp[i].linebuf = NULL; + } + } + return why; +} + +static int stbi__process_frame_header(stbi__jpeg *z, int scan) +{ + stbi__context *s = z->s; + int Lf,p,i,q, h_max=1,v_max=1,c; + Lf = stbi__get16be(s); if (Lf < 11) return stbi__err("bad SOF len","Corrupt JPEG"); // JPEG + p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline + s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG + s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires + c = stbi__get8(s); + if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG"); + s->img_n = c; + for (i=0; i < c; ++i) { + z->img_comp[i].data = NULL; + z->img_comp[i].linebuf = NULL; + } + + if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG"); + + z->rgb = 0; + for (i=0; i < s->img_n; ++i) { + static const unsigned char rgb[3] = { 'R', 'G', 'B' }; + z->img_comp[i].id = stbi__get8(s); + if (s->img_n == 3 && z->img_comp[i].id == rgb[i]) + ++z->rgb; + q = stbi__get8(s); + z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG"); + z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG"); + z->img_comp[i].tq = stbi__get8(s); if (z->img_comp[i].tq > 3) return stbi__err("bad TQ","Corrupt JPEG"); + } + + if (scan != STBI__SCAN_load) return 1; + + if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0)) return stbi__err("too large", "Image too large to decode"); + + for (i=0; i < s->img_n; ++i) { + if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; + if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; + } + + // compute interleaved mcu info + z->img_h_max = h_max; + z->img_v_max = v_max; + z->img_mcu_w = h_max * 8; + z->img_mcu_h = v_max * 8; + // these sizes can't be more than 17 bits + z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; + z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; + + for (i=0; i < s->img_n; ++i) { + // number of effective pixels (e.g. for non-interleaved MCU) + z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max; + z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max; + // to simplify generation, we'll allocate enough memory to decode + // the bogus oversized data from using interleaved MCUs and their + // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't + // discard the extra data until colorspace conversion + // + // img_mcu_x, img_mcu_y: <=17 bits; comp[i].h and .v are <=4 (checked earlier) + // so these muls can't overflow with 32-bit ints (which we require) + z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; + z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; + z->img_comp[i].coeff = 0; + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].linebuf = NULL; + z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15); + if (z->img_comp[i].raw_data == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); + // align blocks for idct using mmx/sse + z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); + if (z->progressive) { + // w2, h2 are multiples of 8 (see above) + z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8; + z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8; + z->img_comp[i].raw_coeff = stbi__malloc_mad3(z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15); + if (z->img_comp[i].raw_coeff == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); + z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15); + } + } + + return 1; +} + +// use comparisons since in some cases we handle more than one case (e.g. SOF) +#define stbi__DNL(x) ((x) == 0xdc) +#define stbi__SOI(x) ((x) == 0xd8) +#define stbi__EOI(x) ((x) == 0xd9) +#define stbi__SOF(x) ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2) +#define stbi__SOS(x) ((x) == 0xda) + +#define stbi__SOF_progressive(x) ((x) == 0xc2) + +static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) +{ + int m; + z->jfif = 0; + z->app14_color_transform = -1; // valid values are 0,1,2 + z->marker = STBI__MARKER_none; // initialize cached marker to empty + m = stbi__get_marker(z); + if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG"); + if (scan == STBI__SCAN_type) return 1; + m = stbi__get_marker(z); + while (!stbi__SOF(m)) { + if (!stbi__process_marker(z,m)) return 0; + m = stbi__get_marker(z); + while (m == STBI__MARKER_none) { + // some files have extra padding after their blocks, so ok, we'll scan + if (stbi__at_eof(z->s)) return stbi__err("no SOF", "Corrupt JPEG"); + m = stbi__get_marker(z); + } + } + z->progressive = stbi__SOF_progressive(m); + if (!stbi__process_frame_header(z, scan)) return 0; + return 1; +} + +// decode image to YCbCr format +static int stbi__decode_jpeg_image(stbi__jpeg *j) +{ + int m; + for (m = 0; m < 4; m++) { + j->img_comp[m].raw_data = NULL; + j->img_comp[m].raw_coeff = NULL; + } + j->restart_interval = 0; + if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) return 0; + m = stbi__get_marker(j); + while (!stbi__EOI(m)) { + if (stbi__SOS(m)) { + if (!stbi__process_scan_header(j)) return 0; + if (!stbi__parse_entropy_coded_data(j)) return 0; + if (j->marker == STBI__MARKER_none ) { + // handle 0s at the end of image data from IP Kamera 9060 + while (!stbi__at_eof(j->s)) { + int x = stbi__get8(j->s); + if (x == 255) { + j->marker = stbi__get8(j->s); + break; + } + } + // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 + } + } else if (stbi__DNL(m)) { + int Ld = stbi__get16be(j->s); + stbi__uint32 NL = stbi__get16be(j->s); + if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG"); + if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG"); + } else { + if (!stbi__process_marker(j, m)) return 0; + } + m = stbi__get_marker(j); + } + if (j->progressive) + stbi__jpeg_finish(j); + return 1; +} + +// static jfif-centered resampling (across block boundaries) + +typedef stbi_uc *(*resample_row_func)(stbi_uc *out, stbi_uc *in0, stbi_uc *in1, + int w, int hs); + +#define stbi__div4(x) ((stbi_uc) ((x) >> 2)) + +static stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + STBI_NOTUSED(out); + STBI_NOTUSED(in_far); + STBI_NOTUSED(w); + STBI_NOTUSED(hs); + return in_near; +} + +static stbi_uc* stbi__resample_row_v_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples vertically for every one in input + int i; + STBI_NOTUSED(hs); + for (i=0; i < w; ++i) + out[i] = stbi__div4(3*in_near[i] + in_far[i] + 2); + return out; +} + +static stbi_uc* stbi__resample_row_h_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples horizontally for every one in input + int i; + stbi_uc *input = in_near; + + if (w == 1) { + // if only one sample, can't do any interpolation + out[0] = out[1] = input[0]; + return out; + } + + out[0] = input[0]; + out[1] = stbi__div4(input[0]*3 + input[1] + 2); + for (i=1; i < w-1; ++i) { + int n = 3*input[i]+2; + out[i*2+0] = stbi__div4(n+input[i-1]); + out[i*2+1] = stbi__div4(n+input[i+1]); + } + out[i*2+0] = stbi__div4(input[w-2]*3 + input[w-1] + 2); + out[i*2+1] = input[w-1]; + + STBI_NOTUSED(in_far); + STBI_NOTUSED(hs); + + return out; +} + +#define stbi__div16(x) ((stbi_uc) ((x) >> 4)) + +static stbi_uc *stbi__resample_row_hv_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i,t0,t1; + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + out[0] = stbi__div4(t1+2); + for (i=1; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static stbi_uc *stbi__resample_row_hv_2_simd(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i=0,t0,t1; + + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + // process groups of 8 pixels for as long as we can. + // note we can't handle the last pixel in a row in this loop + // because we need to handle the filter boundary conditions. + for (; i < ((w-1) & ~7); i += 8) { +#if defined(STBI_SSE2) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + __m128i zero = _mm_setzero_si128(); + __m128i farb = _mm_loadl_epi64((__m128i *) (in_far + i)); + __m128i nearb = _mm_loadl_epi64((__m128i *) (in_near + i)); + __m128i farw = _mm_unpacklo_epi8(farb, zero); + __m128i nearw = _mm_unpacklo_epi8(nearb, zero); + __m128i diff = _mm_sub_epi16(farw, nearw); + __m128i nears = _mm_slli_epi16(nearw, 2); + __m128i curr = _mm_add_epi16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + __m128i prv0 = _mm_slli_si128(curr, 2); + __m128i nxt0 = _mm_srli_si128(curr, 2); + __m128i prev = _mm_insert_epi16(prv0, t1, 0); + __m128i next = _mm_insert_epi16(nxt0, 3*in_near[i+8] + in_far[i+8], 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + __m128i bias = _mm_set1_epi16(8); + __m128i curs = _mm_slli_epi16(curr, 2); + __m128i prvd = _mm_sub_epi16(prev, curr); + __m128i nxtd = _mm_sub_epi16(next, curr); + __m128i curb = _mm_add_epi16(curs, bias); + __m128i even = _mm_add_epi16(prvd, curb); + __m128i odd = _mm_add_epi16(nxtd, curb); + + // interleave even and odd pixels, then undo scaling. + __m128i int0 = _mm_unpacklo_epi16(even, odd); + __m128i int1 = _mm_unpackhi_epi16(even, odd); + __m128i de0 = _mm_srli_epi16(int0, 4); + __m128i de1 = _mm_srli_epi16(int1, 4); + + // pack and write output + __m128i outv = _mm_packus_epi16(de0, de1); + _mm_storeu_si128((__m128i *) (out + i*2), outv); +#elif defined(STBI_NEON) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + uint8x8_t farb = vld1_u8(in_far + i); + uint8x8_t nearb = vld1_u8(in_near + i); + int16x8_t diff = vreinterpretq_s16_u16(vsubl_u8(farb, nearb)); + int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2)); + int16x8_t curr = vaddq_s16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + int16x8_t prv0 = vextq_s16(curr, curr, 7); + int16x8_t nxt0 = vextq_s16(curr, curr, 1); + int16x8_t prev = vsetq_lane_s16(t1, prv0, 0); + int16x8_t next = vsetq_lane_s16(3*in_near[i+8] + in_far[i+8], nxt0, 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + int16x8_t curs = vshlq_n_s16(curr, 2); + int16x8_t prvd = vsubq_s16(prev, curr); + int16x8_t nxtd = vsubq_s16(next, curr); + int16x8_t even = vaddq_s16(curs, prvd); + int16x8_t odd = vaddq_s16(curs, nxtd); + + // undo scaling and round, then store with even/odd phases interleaved + uint8x8x2_t o; + o.val[0] = vqrshrun_n_s16(even, 4); + o.val[1] = vqrshrun_n_s16(odd, 4); + vst2_u8(out + i*2, o); +#endif + + // "previous" value for next iter + t1 = 3*in_near[i+7] + in_far[i+7]; + } + + t0 = t1; + t1 = 3*in_near[i] + in_far[i]; + out[i*2] = stbi__div16(3*t1 + t0 + 8); + + for (++i; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} +#endif + +static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // resample with nearest-neighbor + int i,j; + STBI_NOTUSED(in_far); + for (i=0; i < w; ++i) + for (j=0; j < hs; ++j) + out[i*hs+j] = in_near[i]; + return out; +} + +// this is a reduced-precision calculation of YCbCr-to-RGB introduced +// to make sure the code produces the same results in both SIMD and scalar +#define stbi__float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8) +static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) +{ + int i; + for (i=0; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + (cr*-stbi__float2fixed(0.71414f)) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step) +{ + int i = 0; + +#ifdef STBI_SSE2 + // step == 3 is pretty ugly on the final interleave, and i'm not convinced + // it's useful in practice (you wouldn't use it for textures, for example). + // so just accelerate step == 4 case. + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + __m128i signflip = _mm_set1_epi8(-0x80); + __m128i cr_const0 = _mm_set1_epi16( (short) ( 1.40200f*4096.0f+0.5f)); + __m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f)); + __m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f)); + __m128i cb_const1 = _mm_set1_epi16( (short) ( 1.77200f*4096.0f+0.5f)); + __m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128); + __m128i xw = _mm_set1_epi16(255); // alpha channel + + for (; i+7 < count; i += 8) { + // load + __m128i y_bytes = _mm_loadl_epi64((__m128i *) (y+i)); + __m128i cr_bytes = _mm_loadl_epi64((__m128i *) (pcr+i)); + __m128i cb_bytes = _mm_loadl_epi64((__m128i *) (pcb+i)); + __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); // -128 + __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); // -128 + + // unpack to short (and left-shift cr, cb by 8) + __m128i yw = _mm_unpacklo_epi8(y_bias, y_bytes); + __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased); + __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased); + + // color transform + __m128i yws = _mm_srli_epi16(yw, 4); + __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw); + __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw); + __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1); + __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1); + __m128i rws = _mm_add_epi16(cr0, yws); + __m128i gwt = _mm_add_epi16(cb0, yws); + __m128i bws = _mm_add_epi16(yws, cb1); + __m128i gws = _mm_add_epi16(gwt, cr1); + + // descale + __m128i rw = _mm_srai_epi16(rws, 4); + __m128i bw = _mm_srai_epi16(bws, 4); + __m128i gw = _mm_srai_epi16(gws, 4); + + // back to byte, set up for transpose + __m128i brb = _mm_packus_epi16(rw, bw); + __m128i gxb = _mm_packus_epi16(gw, xw); + + // transpose to interleave channels + __m128i t0 = _mm_unpacklo_epi8(brb, gxb); + __m128i t1 = _mm_unpackhi_epi8(brb, gxb); + __m128i o0 = _mm_unpacklo_epi16(t0, t1); + __m128i o1 = _mm_unpackhi_epi16(t0, t1); + + // store + _mm_storeu_si128((__m128i *) (out + 0), o0); + _mm_storeu_si128((__m128i *) (out + 16), o1); + out += 32; + } + } +#endif + +#ifdef STBI_NEON + // in this version, step=3 support would be easy to add. but is there demand? + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + uint8x8_t signflip = vdup_n_u8(0x80); + int16x8_t cr_const0 = vdupq_n_s16( (short) ( 1.40200f*4096.0f+0.5f)); + int16x8_t cr_const1 = vdupq_n_s16( - (short) ( 0.71414f*4096.0f+0.5f)); + int16x8_t cb_const0 = vdupq_n_s16( - (short) ( 0.34414f*4096.0f+0.5f)); + int16x8_t cb_const1 = vdupq_n_s16( (short) ( 1.77200f*4096.0f+0.5f)); + + for (; i+7 < count; i += 8) { + // load + uint8x8_t y_bytes = vld1_u8(y + i); + uint8x8_t cr_bytes = vld1_u8(pcr + i); + uint8x8_t cb_bytes = vld1_u8(pcb + i); + int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip)); + int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip)); + + // expand to s16 + int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4)); + int16x8_t crw = vshll_n_s8(cr_biased, 7); + int16x8_t cbw = vshll_n_s8(cb_biased, 7); + + // color transform + int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0); + int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0); + int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1); + int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1); + int16x8_t rws = vaddq_s16(yws, cr0); + int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1); + int16x8_t bws = vaddq_s16(yws, cb1); + + // undo scaling, round, convert to byte + uint8x8x4_t o; + o.val[0] = vqrshrun_n_s16(rws, 4); + o.val[1] = vqrshrun_n_s16(gws, 4); + o.val[2] = vqrshrun_n_s16(bws, 4); + o.val[3] = vdup_n_u8(255); + + // store, interleaving r/g/b/a + vst4_u8(out, o); + out += 8*4; + } + } +#endif + + for (; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + cr*-stbi__float2fixed(0.71414f) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} +#endif + +// set up the kernels +static void stbi__setup_jpeg(stbi__jpeg *j) +{ + j->idct_block_kernel = stbi__idct_block; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_row; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2; + +#ifdef STBI_SSE2 + if (stbi__sse2_available()) { + j->idct_block_kernel = stbi__idct_simd; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; + } +#endif + +#ifdef STBI_NEON + j->idct_block_kernel = stbi__idct_simd; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; +#endif +} + +// clean up the temporary component buffers +static void stbi__cleanup_jpeg(stbi__jpeg *j) +{ + stbi__free_jpeg_components(j, j->s->img_n, 0); +} + +typedef struct +{ + resample_row_func resample; + stbi_uc *line0,*line1; + int hs,vs; // expansion factor in each axis + int w_lores; // horizontal pixels pre-expansion + int ystep; // how far through vertical expansion we are + int ypos; // which pre-expansion row we're on +} stbi__resample; + +// fast 0..255 * 0..255 => 0..255 rounded multiplication +static stbi_uc stbi__blinn_8x8(stbi_uc x, stbi_uc y) +{ + unsigned int t = x*y + 128; + return (stbi_uc) ((t + (t >>8)) >> 8); +} + +static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) +{ + int n, decode_n, is_rgb; + z->s->img_n = 0; // make stbi__cleanup_jpeg safe + + // validate req_comp + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + + // load a jpeg image from whichever source, but leave in YCbCr format + if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; } + + // determine actual number of components to generate + n = req_comp ? req_comp : z->s->img_n >= 3 ? 3 : 1; + + is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif)); + + if (z->s->img_n == 3 && n < 3 && !is_rgb) + decode_n = 1; + else + decode_n = z->s->img_n; + + // resample and color-convert + { + int k; + unsigned int i,j; + stbi_uc *output; + stbi_uc *coutput[4] = { NULL, NULL, NULL, NULL }; + + stbi__resample res_comp[4]; + + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + + // allocate line buffer big enough for upsampling off the edges + // with upsample factor of 4 + z->img_comp[k].linebuf = (stbi_uc *) stbi__malloc(z->s->img_x + 3); + if (!z->img_comp[k].linebuf) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + r->hs = z->img_h_max / z->img_comp[k].h; + r->vs = z->img_v_max / z->img_comp[k].v; + r->ystep = r->vs >> 1; + r->w_lores = (z->s->img_x + r->hs-1) / r->hs; + r->ypos = 0; + r->line0 = r->line1 = z->img_comp[k].data; + + if (r->hs == 1 && r->vs == 1) r->resample = resample_row_1; + else if (r->hs == 1 && r->vs == 2) r->resample = stbi__resample_row_v_2; + else if (r->hs == 2 && r->vs == 1) r->resample = stbi__resample_row_h_2; + else if (r->hs == 2 && r->vs == 2) r->resample = z->resample_row_hv_2_kernel; + else r->resample = stbi__resample_row_generic; + } + + // can't error after this so, this is safe + output = (stbi_uc *) stbi__malloc_mad3(n, z->s->img_x, z->s->img_y, 1); + if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + // now go ahead and resample + for (j=0; j < z->s->img_y; ++j) { + stbi_uc *out = output + n * z->s->img_x * j; + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + int y_bot = r->ystep >= (r->vs >> 1); + coutput[k] = r->resample(z->img_comp[k].linebuf, + y_bot ? r->line1 : r->line0, + y_bot ? r->line0 : r->line1, + r->w_lores, r->hs); + if (++r->ystep >= r->vs) { + r->ystep = 0; + r->line0 = r->line1; + if (++r->ypos < z->img_comp[k].y) + r->line1 += z->img_comp[k].w2; + } + } + if (n >= 3) { + stbi_uc *y = coutput[0]; + if (z->s->img_n == 3) { + if (is_rgb) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = y[i]; + out[1] = coutput[1][i]; + out[2] = coutput[2][i]; + out[3] = 255; + out += n; + } + } else { + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } + } else if (z->s->img_n == 4) { + if (z->app14_color_transform == 0) { // CMYK + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(coutput[0][i], m); + out[1] = stbi__blinn_8x8(coutput[1][i], m); + out[2] = stbi__blinn_8x8(coutput[2][i], m); + out[3] = 255; + out += n; + } + } else if (z->app14_color_transform == 2) { // YCCK + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(255 - out[0], m); + out[1] = stbi__blinn_8x8(255 - out[1], m); + out[2] = stbi__blinn_8x8(255 - out[2], m); + out += n; + } + } else { // YCbCr + alpha? Ignore the fourth channel for now + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } + } else + for (i=0; i < z->s->img_x; ++i) { + out[0] = out[1] = out[2] = y[i]; + out[3] = 255; // not used if n==3 + out += n; + } + } else { + if (is_rgb) { + if (n == 1) + for (i=0; i < z->s->img_x; ++i) + *out++ = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + else { + for (i=0; i < z->s->img_x; ++i, out += 2) { + out[0] = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + out[1] = 255; + } + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 0) { + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + stbi_uc r = stbi__blinn_8x8(coutput[0][i], m); + stbi_uc g = stbi__blinn_8x8(coutput[1][i], m); + stbi_uc b = stbi__blinn_8x8(coutput[2][i], m); + out[0] = stbi__compute_y(r, g, b); + out[1] = 255; + out += n; + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 2) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = stbi__blinn_8x8(255 - coutput[0][i], coutput[3][i]); + out[1] = 255; + out += n; + } + } else { + stbi_uc *y = coutput[0]; + if (n == 1) + for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; + else + for (i=0; i < z->s->img_x; ++i) { *out++ = y[i]; *out++ = 255; } + } + } + } + stbi__cleanup_jpeg(z); + *out_x = z->s->img_x; + *out_y = z->s->img_y; + if (comp) *comp = z->s->img_n >= 3 ? 3 : 1; // report original components, not output + return output; + } +} + +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + unsigned char* result; + stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg)); + STBI_NOTUSED(ri); + j->s = s; + stbi__setup_jpeg(j); + result = load_jpeg_image(j, x,y,comp,req_comp); + STBI_FREE(j); + return result; +} + +static int stbi__jpeg_test(stbi__context *s) +{ + int r; + stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg)); + j->s = s; + stbi__setup_jpeg(j); + r = stbi__decode_jpeg_header(j, STBI__SCAN_type); + stbi__rewind(s); + STBI_FREE(j); + return r; +} + +static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) +{ + if (!stbi__decode_jpeg_header(j, STBI__SCAN_header)) { + stbi__rewind( j->s ); + return 0; + } + if (x) *x = j->s->img_x; + if (y) *y = j->s->img_y; + if (comp) *comp = j->s->img_n >= 3 ? 3 : 1; + return 1; +} + +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) +{ + int result; + stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg))); + j->s = s; + result = stbi__jpeg_info_raw(j, x, y, comp); + STBI_FREE(j); + return result; +} +#endif + +// public domain zlib decode v0.2 Sean Barrett 2006-11-18 +// simple implementation +// - all input must be provided in an upfront buffer +// - all output is written to a single output buffer (can malloc/realloc) +// performance +// - fast huffman + +#ifndef STBI_NO_ZLIB + +// fast-way is faster to check than jpeg huffman, but slow way is slower +#define STBI__ZFAST_BITS 9 // accelerate all cases in default tables +#define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1) + +// zlib-style huffman encoding +// (jpegs packs from left, zlib from right, so can't share code) +typedef struct +{ + stbi__uint16 fast[1 << STBI__ZFAST_BITS]; + stbi__uint16 firstcode[16]; + int maxcode[17]; + stbi__uint16 firstsymbol[16]; + stbi_uc size[288]; + stbi__uint16 value[288]; +} stbi__zhuffman; + +stbi_inline static int stbi__bitreverse16(int n) +{ + n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); + n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); + n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); + n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); + return n; +} + +stbi_inline static int stbi__bit_reverse(int v, int bits) +{ + STBI_ASSERT(bits <= 16); + // to bit reverse n bits, reverse 16 and shift + // e.g. 11 bits, bit reverse and shift away 5 + return stbi__bitreverse16(v) >> (16-bits); +} + +static int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int num) +{ + int i,k=0; + int code, next_code[16], sizes[17]; + + // DEFLATE spec for generating codes + memset(sizes, 0, sizeof(sizes)); + memset(z->fast, 0, sizeof(z->fast)); + for (i=0; i < num; ++i) + ++sizes[sizelist[i]]; + sizes[0] = 0; + for (i=1; i < 16; ++i) + if (sizes[i] > (1 << i)) + return stbi__err("bad sizes", "Corrupt PNG"); + code = 0; + for (i=1; i < 16; ++i) { + next_code[i] = code; + z->firstcode[i] = (stbi__uint16) code; + z->firstsymbol[i] = (stbi__uint16) k; + code = (code + sizes[i]); + if (sizes[i]) + if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG"); + z->maxcode[i] = code << (16-i); // preshift for inner loop + code <<= 1; + k += sizes[i]; + } + z->maxcode[16] = 0x10000; // sentinel + for (i=0; i < num; ++i) { + int s = sizelist[i]; + if (s) { + int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; + stbi__uint16 fastv = (stbi__uint16) ((s << 9) | i); + z->size [c] = (stbi_uc ) s; + z->value[c] = (stbi__uint16) i; + if (s <= STBI__ZFAST_BITS) { + int j = stbi__bit_reverse(next_code[s],s); + while (j < (1 << STBI__ZFAST_BITS)) { + z->fast[j] = fastv; + j += (1 << s); + } + } + ++next_code[s]; + } + } + return 1; +} + +// zlib-from-memory implementation for PNG reading +// because PNG allows splitting the zlib stream arbitrarily, +// and it's annoying structurally to have PNG call ZLIB call PNG, +// we require PNG read all the IDATs and combine them into a single +// memory buffer + +typedef struct +{ + stbi_uc *zbuffer, *zbuffer_end; + int num_bits; + stbi__uint32 code_buffer; + + char *zout; + char *zout_start; + char *zout_end; + int z_expandable; + + stbi__zhuffman z_length, z_distance; +} stbi__zbuf; + +stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z) +{ + if (z->zbuffer >= z->zbuffer_end) return 0; + return *z->zbuffer++; +} + +static void stbi__fill_bits(stbi__zbuf *z) +{ + do { + STBI_ASSERT(z->code_buffer < (1U << z->num_bits)); + z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits; + z->num_bits += 8; + } while (z->num_bits <= 24); +} + +stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n) +{ + unsigned int k; + if (z->num_bits < n) stbi__fill_bits(z); + k = z->code_buffer & ((1 << n) - 1); + z->code_buffer >>= n; + z->num_bits -= n; + return k; +} + +static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s,k; + // not resolved by fast table, so compute it the slow way + // use jpeg approach, which requires MSbits at top + k = stbi__bit_reverse(a->code_buffer, 16); + for (s=STBI__ZFAST_BITS+1; ; ++s) + if (k < z->maxcode[s]) + break; + if (s == 16) return -1; // invalid code! + // code size is s, so: + b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; + STBI_ASSERT(z->size[b] == s); + a->code_buffer >>= s; + a->num_bits -= s; + return z->value[b]; +} + +stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s; + if (a->num_bits < 16) stbi__fill_bits(a); + b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; + if (b) { + s = b >> 9; + a->code_buffer >>= s; + a->num_bits -= s; + return b & 511; + } + return stbi__zhuffman_decode_slowpath(a, z); +} + +static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes +{ + char *q; + int cur, limit, old_limit; + z->zout = zout; + if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG"); + cur = (int) (z->zout - z->zout_start); + limit = old_limit = (int) (z->zout_end - z->zout_start); + while (cur + n > limit) + limit *= 2; + q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit); + STBI_NOTUSED(old_limit); + if (q == NULL) return stbi__err("outofmem", "Out of memory"); + z->zout_start = q; + z->zout = q + cur; + z->zout_end = q + limit; + return 1; +} + +static const int stbi__zlength_base[31] = { + 3,4,5,6,7,8,9,10,11,13, + 15,17,19,23,27,31,35,43,51,59, + 67,83,99,115,131,163,195,227,258,0,0 }; + +static const int stbi__zlength_extra[31]= +{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; + +static const int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, +257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; + +static const int stbi__zdist_extra[32] = +{ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +static int stbi__parse_huffman_block(stbi__zbuf *a) +{ + char *zout = a->zout; + for(;;) { + int z = stbi__zhuffman_decode(a, &a->z_length); + if (z < 256) { + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); // error in huffman codes + if (zout >= a->zout_end) { + if (!stbi__zexpand(a, zout, 1)) return 0; + zout = a->zout; + } + *zout++ = (char) z; + } else { + stbi_uc *p; + int len,dist; + if (z == 256) { + a->zout = zout; + return 1; + } + z -= 257; + len = stbi__zlength_base[z]; + if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]); + z = stbi__zhuffman_decode(a, &a->z_distance); + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); + dist = stbi__zdist_base[z]; + if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); + if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); + if (zout + len > a->zout_end) { + if (!stbi__zexpand(a, zout, len)) return 0; + zout = a->zout; + } + p = (stbi_uc *) (zout - dist); + if (dist == 1) { // run of one byte; common in images. + stbi_uc v = *p; + if (len) { do *zout++ = v; while (--len); } + } else { + if (len) { do *zout++ = *p++; while (--len); } + } + } + } +} + +static int stbi__compute_huffman_codes(stbi__zbuf *a) +{ + static const stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + stbi__zhuffman z_codelength; + stbi_uc lencodes[286+32+137];//padding for maximum single op + stbi_uc codelength_sizes[19]; + int i,n; + + int hlit = stbi__zreceive(a,5) + 257; + int hdist = stbi__zreceive(a,5) + 1; + int hclen = stbi__zreceive(a,4) + 4; + int ntot = hlit + hdist; + + memset(codelength_sizes, 0, sizeof(codelength_sizes)); + for (i=0; i < hclen; ++i) { + int s = stbi__zreceive(a,3); + codelength_sizes[length_dezigzag[i]] = (stbi_uc) s; + } + if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; + + n = 0; + while (n < ntot) { + int c = stbi__zhuffman_decode(a, &z_codelength); + if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG"); + if (c < 16) + lencodes[n++] = (stbi_uc) c; + else { + stbi_uc fill = 0; + if (c == 16) { + c = stbi__zreceive(a,2)+3; + if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG"); + fill = lencodes[n-1]; + } else if (c == 17) + c = stbi__zreceive(a,3)+3; + else { + STBI_ASSERT(c == 18); + c = stbi__zreceive(a,7)+11; + } + if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG"); + memset(lencodes+n, fill, c); + n += c; + } + } + if (n != ntot) return stbi__err("bad codelengths","Corrupt PNG"); + if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; + return 1; +} + +static int stbi__parse_uncompressed_block(stbi__zbuf *a) +{ + stbi_uc header[4]; + int len,nlen,k; + if (a->num_bits & 7) + stbi__zreceive(a, a->num_bits & 7); // discard + // drain the bit-packed data into header + k = 0; + while (a->num_bits > 0) { + header[k++] = (stbi_uc) (a->code_buffer & 255); // suppress MSVC run-time check + a->code_buffer >>= 8; + a->num_bits -= 8; + } + STBI_ASSERT(a->num_bits == 0); + // now fill header the normal way + while (k < 4) + header[k++] = stbi__zget8(a); + len = header[1] * 256 + header[0]; + nlen = header[3] * 256 + header[2]; + if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG"); + if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG"); + if (a->zout + len > a->zout_end) + if (!stbi__zexpand(a, a->zout, len)) return 0; + memcpy(a->zout, a->zbuffer, len); + a->zbuffer += len; + a->zout += len; + return 1; +} + +static int stbi__parse_zlib_header(stbi__zbuf *a) +{ + int cmf = stbi__zget8(a); + int cm = cmf & 15; + /* int cinfo = cmf >> 4; */ + int flg = stbi__zget8(a); + if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec + if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png + if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png + // window = 1 << (8 + cinfo)... but who cares, we fully buffer output + return 1; +} + +static const stbi_uc stbi__zdefault_length[288] = +{ + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8 +}; +static const stbi_uc stbi__zdefault_distance[32] = +{ + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5 +}; +/* +Init algorithm: +{ + int i; // use <= to match clearly with spec + for (i=0; i <= 143; ++i) stbi__zdefault_length[i] = 8; + for ( ; i <= 255; ++i) stbi__zdefault_length[i] = 9; + for ( ; i <= 279; ++i) stbi__zdefault_length[i] = 7; + for ( ; i <= 287; ++i) stbi__zdefault_length[i] = 8; + + for (i=0; i <= 31; ++i) stbi__zdefault_distance[i] = 5; +} +*/ + +static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) +{ + int final, type; + if (parse_header) + if (!stbi__parse_zlib_header(a)) return 0; + a->num_bits = 0; + a->code_buffer = 0; + do { + final = stbi__zreceive(a,1); + type = stbi__zreceive(a,2); + if (type == 0) { + if (!stbi__parse_uncompressed_block(a)) return 0; + } else if (type == 3) { + return 0; + } else { + if (type == 1) { + // use fixed code lengths + if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , 288)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0; + } else { + if (!stbi__compute_huffman_codes(a)) return 0; + } + if (!stbi__parse_huffman_block(a)) return 0; + } + } while (!final); + return 1; +} + +static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header) +{ + a->zout_start = obuf; + a->zout = obuf; + a->zout_end = obuf + olen; + a->z_expandable = exp; + + return stbi__parse_zlib(a, parse_header); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, 1)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) +{ + return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 1)) + return (int) (a.zout - a.zout_start); + else + return -1; +} + +STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(16384); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer+len; + if (stbi__do_zlib(&a, p, 16384, 1, 0)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 0)) + return (int) (a.zout - a.zout_start); + else + return -1; +} +#endif + +// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18 +// simple implementation +// - only 8-bit samples +// - no CRC checking +// - allocates lots of intermediate memory +// - avoids problem of streaming data between subsystems +// - avoids explicit window management +// performance +// - uses stb_zlib, a PD zlib implementation with fast huffman decoding + +#ifndef STBI_NO_PNG +typedef struct +{ + stbi__uint32 length; + stbi__uint32 type; +} stbi__pngchunk; + +static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) +{ + stbi__pngchunk c; + c.length = stbi__get32be(s); + c.type = stbi__get32be(s); + return c; +} + +static int stbi__check_png_header(stbi__context *s) +{ + static const stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 }; + int i; + for (i=0; i < 8; ++i) + if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG"); + return 1; +} + +typedef struct +{ + stbi__context *s; + stbi_uc *idata, *expanded, *out; + int depth; +} stbi__png; + + +enum { + STBI__F_none=0, + STBI__F_sub=1, + STBI__F_up=2, + STBI__F_avg=3, + STBI__F_paeth=4, + // synthetic filters used for first scanline to avoid needing a dummy row of 0s + STBI__F_avg_first, + STBI__F_paeth_first +}; + +static stbi_uc first_row_filter[5] = +{ + STBI__F_none, + STBI__F_sub, + STBI__F_none, + STBI__F_avg_first, + STBI__F_paeth_first +}; + +static int stbi__paeth(int a, int b, int c) +{ + int p = a + b - c; + int pa = abs(p-a); + int pb = abs(p-b); + int pc = abs(p-c); + if (pa <= pb && pa <= pc) return a; + if (pb <= pc) return b; + return c; +} + +static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; + +// create the png data from post-deflated data +static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) +{ + int bytes = (depth == 16? 2 : 1); + stbi__context *s = a->s; + stbi__uint32 i,j,stride = x*out_n*bytes; + stbi__uint32 img_len, img_width_bytes; + int k; + int img_n = s->img_n; // copy it into a local for later + + int output_bytes = out_n*bytes; + int filter_bytes = img_n*bytes; + int width = x; + + STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); + a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into + if (!a->out) return stbi__err("outofmem", "Out of memory"); + + if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG"); + img_width_bytes = (((img_n * x * depth) + 7) >> 3); + img_len = (img_width_bytes + 1) * y; + + // we used to check for exact match between raw_len and img_len on non-interlaced PNGs, + // but issue #276 reported a PNG in the wild that had extra data at the end (all zeros), + // so just check for raw_len < img_len always. + if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); + + for (j=0; j < y; ++j) { + stbi_uc *cur = a->out + stride*j; + stbi_uc *prior; + int filter = *raw++; + + if (filter > 4) + return stbi__err("invalid filter","Corrupt PNG"); + + if (depth < 8) { + STBI_ASSERT(img_width_bytes <= x); + cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place + filter_bytes = 1; + width = img_width_bytes; + } + prior = cur - stride; // bugfix: need to compute this after 'cur +=' computation above + + // if first row, use special filter that doesn't sample previous row + if (j == 0) filter = first_row_filter[filter]; + + // handle first byte explicitly + for (k=0; k < filter_bytes; ++k) { + switch (filter) { + case STBI__F_none : cur[k] = raw[k]; break; + case STBI__F_sub : cur[k] = raw[k]; break; + case STBI__F_up : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; + case STBI__F_avg : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break; + case STBI__F_paeth : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break; + case STBI__F_avg_first : cur[k] = raw[k]; break; + case STBI__F_paeth_first: cur[k] = raw[k]; break; + } + } + + if (depth == 8) { + if (img_n != out_n) + cur[img_n] = 255; // first pixel + raw += img_n; + cur += out_n; + prior += out_n; + } else if (depth == 16) { + if (img_n != out_n) { + cur[filter_bytes] = 255; // first pixel top byte + cur[filter_bytes+1] = 255; // first pixel bottom byte + } + raw += filter_bytes; + cur += output_bytes; + prior += output_bytes; + } else { + raw += 1; + cur += 1; + prior += 1; + } + + // this is a little gross, so that we don't switch per-pixel or per-component + if (depth < 8 || img_n == out_n) { + int nk = (width - 1)*filter_bytes; + #define STBI__CASE(f) \ + case f: \ + for (k=0; k < nk; ++k) + switch (filter) { + // "none" filter turns into a memcpy here; make that explicit. + case STBI__F_none: memcpy(cur, raw, nk); break; + STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); } break; + STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; + STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); } break; + STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break; + STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); } break; + STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); } break; + } + #undef STBI__CASE + raw += nk; + } else { + STBI_ASSERT(img_n+1 == out_n); + #define STBI__CASE(f) \ + case f: \ + for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \ + for (k=0; k < filter_bytes; ++k) + switch (filter) { + STBI__CASE(STBI__F_none) { cur[k] = raw[k]; } break; + STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); } break; + STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; + STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); } break; + STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break; + STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); } break; + STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); } break; + } + #undef STBI__CASE + + // the loop above sets the high byte of the pixels' alpha, but for + // 16 bit png files we also need the low byte set. we'll do that here. + if (depth == 16) { + cur = a->out + stride*j; // start at the beginning of the row again + for (i=0; i < x; ++i,cur+=output_bytes) { + cur[filter_bytes+1] = 255; + } + } + } + } + + // we make a separate pass to expand bits to pixels; for performance, + // this could run two scanlines behind the above code, so it won't + // intefere with filtering but will still be in the cache. + if (depth < 8) { + for (j=0; j < y; ++j) { + stbi_uc *cur = a->out + stride*j; + stbi_uc *in = a->out + stride*j + x*out_n - img_width_bytes; + // unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit + // png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop + stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range + + // note that the final byte might overshoot and write more data than desired. + // we can allocate enough data that this never writes out of memory, but it + // could also overwrite the next scanline. can it overwrite non-empty data + // on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel. + // so we need to explicitly clamp the final ones + + if (depth == 4) { + for (k=x*img_n; k >= 2; k-=2, ++in) { + *cur++ = scale * ((*in >> 4) ); + *cur++ = scale * ((*in ) & 0x0f); + } + if (k > 0) *cur++ = scale * ((*in >> 4) ); + } else if (depth == 2) { + for (k=x*img_n; k >= 4; k-=4, ++in) { + *cur++ = scale * ((*in >> 6) ); + *cur++ = scale * ((*in >> 4) & 0x03); + *cur++ = scale * ((*in >> 2) & 0x03); + *cur++ = scale * ((*in ) & 0x03); + } + if (k > 0) *cur++ = scale * ((*in >> 6) ); + if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03); + if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03); + } else if (depth == 1) { + for (k=x*img_n; k >= 8; k-=8, ++in) { + *cur++ = scale * ((*in >> 7) ); + *cur++ = scale * ((*in >> 6) & 0x01); + *cur++ = scale * ((*in >> 5) & 0x01); + *cur++ = scale * ((*in >> 4) & 0x01); + *cur++ = scale * ((*in >> 3) & 0x01); + *cur++ = scale * ((*in >> 2) & 0x01); + *cur++ = scale * ((*in >> 1) & 0x01); + *cur++ = scale * ((*in ) & 0x01); + } + if (k > 0) *cur++ = scale * ((*in >> 7) ); + if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01); + if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01); + if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01); + if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01); + if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01); + if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01); + } + if (img_n != out_n) { + int q; + // insert alpha = 255 + cur = a->out + stride*j; + if (img_n == 1) { + for (q=x-1; q >= 0; --q) { + cur[q*2+1] = 255; + cur[q*2+0] = cur[q]; + } + } else { + STBI_ASSERT(img_n == 3); + for (q=x-1; q >= 0; --q) { + cur[q*4+3] = 255; + cur[q*4+2] = cur[q*3+2]; + cur[q*4+1] = cur[q*3+1]; + cur[q*4+0] = cur[q*3+0]; + } + } + } + } + } else if (depth == 16) { + // force the image data from big-endian to platform-native. + // this is done in a separate pass due to the decoding relying + // on the data being untouched, but could probably be done + // per-line during decode if care is taken. + stbi_uc *cur = a->out; + stbi__uint16 *cur16 = (stbi__uint16*)cur; + + for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) { + *cur16 = (cur[0] << 8) | cur[1]; + } + } + + return 1; +} + +static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced) +{ + int bytes = (depth == 16 ? 2 : 1); + int out_bytes = out_n * bytes; + stbi_uc *final; + int p; + if (!interlaced) + return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color); + + // de-interlacing + final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0); + for (p=0; p < 7; ++p) { + int xorig[] = { 0,4,0,2,0,1,0 }; + int yorig[] = { 0,0,4,0,2,0,1 }; + int xspc[] = { 8,8,4,4,2,2,1 }; + int yspc[] = { 8,8,8,4,4,2,2 }; + int i,j,x,y; + // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1 + x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p]; + y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p]; + if (x && y) { + stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y; + if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) { + STBI_FREE(final); + return 0; + } + for (j=0; j < y; ++j) { + for (i=0; i < x; ++i) { + int out_y = j*yspc[p]+yorig[p]; + int out_x = i*xspc[p]+xorig[p]; + memcpy(final + out_y*a->s->img_x*out_bytes + out_x*out_bytes, + a->out + (j*x+i)*out_bytes, out_bytes); + } + } + STBI_FREE(a->out); + image_data += img_len; + image_data_len -= img_len; + } + } + a->out = final; + + return 1; +} + +static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + // compute color-based transparency, assuming we've + // already got 255 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i=0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 255); + p += 2; + } + } else { + for (i=0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi__uint16 *p = (stbi__uint16*) z->out; + + // compute color-based transparency, assuming we've + // already got 65535 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i = 0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 65535); + p += 2; + } + } else { + for (i = 0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n) +{ + stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; + stbi_uc *p, *temp_out, *orig = a->out; + + p = (stbi_uc *) stbi__malloc_mad2(pixel_count, pal_img_n, 0); + if (p == NULL) return stbi__err("outofmem", "Out of memory"); + + // between here and free(out) below, exitting would leak + temp_out = p; + + if (pal_img_n == 3) { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p += 3; + } + } else { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p[3] = palette[n+3]; + p += 4; + } + } + STBI_FREE(a->out); + a->out = temp_out; + + STBI_NOTUSED(len); + + return 1; +} + +static int stbi__unpremultiply_on_load = 0; +static int stbi__de_iphone_flag = 0; + +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) +{ + stbi__unpremultiply_on_load = flag_true_if_should_unpremultiply; +} + +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) +{ + stbi__de_iphone_flag = flag_true_if_should_convert; +} + +static void stbi__de_iphone(stbi__png *z) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + if (s->img_out_n == 3) { // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 3; + } + } else { + STBI_ASSERT(s->img_out_n == 4); + if (stbi__unpremultiply_on_load) { + // convert bgr to rgb and unpremultiply + for (i=0; i < pixel_count; ++i) { + stbi_uc a = p[3]; + stbi_uc t = p[0]; + if (a) { + stbi_uc half = a / 2; + p[0] = (p[2] * 255 + half) / a; + p[1] = (p[1] * 255 + half) / a; + p[2] = ( t * 255 + half) / a; + } else { + p[0] = p[2]; + p[2] = t; + } + p += 4; + } + } else { + // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 4; + } + } + } +} + +#define STBI__PNG_TYPE(a,b,c,d) (((unsigned) (a) << 24) + ((unsigned) (b) << 16) + ((unsigned) (c) << 8) + (unsigned) (d)) + +static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) +{ + stbi_uc palette[1024], pal_img_n=0; + stbi_uc has_trans=0, tc[3]={0}; + stbi__uint16 tc16[3]; + stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; + int first=1,k,interlace=0, color=0, is_iphone=0; + stbi__context *s = z->s; + + z->expanded = NULL; + z->idata = NULL; + z->out = NULL; + + if (!stbi__check_png_header(s)) return 0; + + if (scan == STBI__SCAN_type) return 1; + + for (;;) { + stbi__pngchunk c = stbi__get_chunk_header(s); + switch (c.type) { + case STBI__PNG_TYPE('C','g','B','I'): + is_iphone = 1; + stbi__skip(s, c.length); + break; + case STBI__PNG_TYPE('I','H','D','R'): { + int comp,filter; + if (!first) return stbi__err("multiple IHDR","Corrupt PNG"); + first = 0; + if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG"); + s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); + s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); + z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only"); + color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG"); + comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG"); + filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG"); + interlace = stbi__get8(s); if (interlace>1) return stbi__err("bad interlace method","Corrupt PNG"); + if (!s->img_x || !s->img_y) return stbi__err("0-pixel image","Corrupt PNG"); + if (!pal_img_n) { + s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); + if (scan == STBI__SCAN_header) return 1; + } else { + // if paletted, then pal_n is our final components, and + // img_n is # components to decompress/filter. + s->img_n = 1; + if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG"); + // if SCAN_header, have to scan to see if we have a tRNS + } + break; + } + + case STBI__PNG_TYPE('P','L','T','E'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG"); + pal_len = c.length / 3; + if (pal_len * 3 != c.length) return stbi__err("invalid PLTE","Corrupt PNG"); + for (i=0; i < pal_len; ++i) { + palette[i*4+0] = stbi__get8(s); + palette[i*4+1] = stbi__get8(s); + palette[i*4+2] = stbi__get8(s); + palette[i*4+3] = 255; + } + break; + } + + case STBI__PNG_TYPE('t','R','N','S'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG"); + if (pal_img_n) { + if (scan == STBI__SCAN_header) { s->img_n = 4; return 1; } + if (pal_len == 0) return stbi__err("tRNS before PLTE","Corrupt PNG"); + if (c.length > pal_len) return stbi__err("bad tRNS len","Corrupt PNG"); + pal_img_n = 4; + for (i=0; i < c.length; ++i) + palette[i*4+3] = stbi__get8(s); + } else { + if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG"); + if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); + has_trans = 1; + if (z->depth == 16) { + for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is + } else { + for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger + } + } + break; + } + + case STBI__PNG_TYPE('I','D','A','T'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG"); + if (scan == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; } + if ((int)(ioff + c.length) < (int)ioff) return 0; + if (ioff + c.length > idata_limit) { + stbi__uint32 idata_limit_old = idata_limit; + stbi_uc *p; + if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; + while (ioff + c.length > idata_limit) + idata_limit *= 2; + STBI_NOTUSED(idata_limit_old); + p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory"); + z->idata = p; + } + if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG"); + ioff += c.length; + break; + } + + case STBI__PNG_TYPE('I','E','N','D'): { + stbi__uint32 raw_len, bpl; + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (scan != STBI__SCAN_load) return 1; + if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG"); + // initial guess for decoded data size to avoid unnecessary reallocs + bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component + raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */; + z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone); + if (z->expanded == NULL) return 0; // zlib should set error + STBI_FREE(z->idata); z->idata = NULL; + if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) + s->img_out_n = s->img_n+1; + else + s->img_out_n = s->img_n; + if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0; + if (has_trans) { + if (z->depth == 16) { + if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0; + } else { + if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0; + } + } + if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2) + stbi__de_iphone(z); + if (pal_img_n) { + // pal_img_n == 3 or 4 + s->img_n = pal_img_n; // record the actual colors we had + s->img_out_n = pal_img_n; + if (req_comp >= 3) s->img_out_n = req_comp; + if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n)) + return 0; + } else if (has_trans) { + // non-paletted image with tRNS -> source image has (constant) alpha + ++s->img_n; + } + STBI_FREE(z->expanded); z->expanded = NULL; + return 1; + } + + default: + // if critical, fail + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if ((c.type & (1 << 29)) == 0) { + #ifndef STBI_NO_FAILURE_STRINGS + // not threadsafe + static char invalid_chunk[] = "XXXX PNG chunk not known"; + invalid_chunk[0] = STBI__BYTECAST(c.type >> 24); + invalid_chunk[1] = STBI__BYTECAST(c.type >> 16); + invalid_chunk[2] = STBI__BYTECAST(c.type >> 8); + invalid_chunk[3] = STBI__BYTECAST(c.type >> 0); + #endif + return stbi__err(invalid_chunk, "PNG not supported: unknown PNG chunk type"); + } + stbi__skip(s, c.length); + break; + } + // end of PNG chunk, read and skip CRC + stbi__get32be(s); + } +} + +static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri) +{ + void *result=NULL; + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { + if (p->depth < 8) + ri->bits_per_channel = 8; + else + ri->bits_per_channel = p->depth; + result = p->out; + p->out = NULL; + if (req_comp && req_comp != p->s->img_out_n) { + if (ri->bits_per_channel == 8) + result = stbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + else + result = stbi__convert_format16((stbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + p->s->img_out_n = req_comp; + if (result == NULL) return result; + } + *x = p->s->img_x; + *y = p->s->img_y; + if (n) *n = p->s->img_n; + } + STBI_FREE(p->out); p->out = NULL; + STBI_FREE(p->expanded); p->expanded = NULL; + STBI_FREE(p->idata); p->idata = NULL; + + return result; +} + +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi__png p; + p.s = s; + return stbi__do_png(&p, x,y,comp,req_comp, ri); +} + +static int stbi__png_test(stbi__context *s) +{ + int r; + r = stbi__check_png_header(s); + stbi__rewind(s); + return r; +} + +static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp) +{ + if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) { + stbi__rewind( p->s ); + return 0; + } + if (x) *x = p->s->img_x; + if (y) *y = p->s->img_y; + if (comp) *comp = p->s->img_n; + return 1; +} + +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__png p; + p.s = s; + return stbi__png_info_raw(&p, x, y, comp); +} + +static int stbi__png_is16(stbi__context *s) +{ + stbi__png p; + p.s = s; + if (!stbi__png_info_raw(&p, NULL, NULL, NULL)) + return 0; + if (p.depth != 16) { + stbi__rewind(p.s); + return 0; + } + return 1; +} +#endif + +// Microsoft/Windows BMP image + +#ifndef STBI_NO_BMP +static int stbi__bmp_test_raw(stbi__context *s) +{ + int r; + int sz; + if (stbi__get8(s) != 'B') return 0; + if (stbi__get8(s) != 'M') return 0; + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + stbi__get32le(s); // discard data offset + sz = stbi__get32le(s); + r = (sz == 12 || sz == 40 || sz == 56 || sz == 108 || sz == 124); + return r; +} + +static int stbi__bmp_test(stbi__context *s) +{ + int r = stbi__bmp_test_raw(s); + stbi__rewind(s); + return r; +} + + +// returns 0..31 for the highest set bit +static int stbi__high_bit(unsigned int z) +{ + int n=0; + if (z == 0) return -1; + if (z >= 0x10000) { n += 16; z >>= 16; } + if (z >= 0x00100) { n += 8; z >>= 8; } + if (z >= 0x00010) { n += 4; z >>= 4; } + if (z >= 0x00004) { n += 2; z >>= 2; } + if (z >= 0x00002) { n += 1; z >>= 1; } + return n; +} + +static int stbi__bitcount(unsigned int a) +{ + a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2 + a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4 + a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits + a = (a + (a >> 8)); // max 16 per 8 bits + a = (a + (a >> 16)); // max 32 per 8 bits + return a & 0xff; +} + +// extract an arbitrarily-aligned N-bit value (N=bits) +// from v, and then make it 8-bits long and fractionally +// extend it to full full range. +static int stbi__shiftsigned(unsigned int v, int shift, int bits) +{ + static unsigned int mul_table[9] = { + 0, + 0xff/*0b11111111*/, 0x55/*0b01010101*/, 0x49/*0b01001001*/, 0x11/*0b00010001*/, + 0x21/*0b00100001*/, 0x41/*0b01000001*/, 0x81/*0b10000001*/, 0x01/*0b00000001*/, + }; + static unsigned int shift_table[9] = { + 0, 0,0,1,0,2,4,6,0, + }; + if (shift < 0) + v <<= -shift; + else + v >>= shift; + STBI_ASSERT(v >= 0 && v < 256); + v >>= (8-bits); + STBI_ASSERT(bits >= 0 && bits <= 8); + return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits]; +} + +typedef struct +{ + int bpp, offset, hsz; + unsigned int mr,mg,mb,ma, all_a; +} stbi__bmp_data; + +static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) +{ + int hsz; + if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP"); + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + info->offset = stbi__get32le(s); + info->hsz = hsz = stbi__get32le(s); + info->mr = info->mg = info->mb = info->ma = 0; + + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); + if (hsz == 12) { + s->img_x = stbi__get16le(s); + s->img_y = stbi__get16le(s); + } else { + s->img_x = stbi__get32le(s); + s->img_y = stbi__get32le(s); + } + if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP"); + info->bpp = stbi__get16le(s); + if (hsz != 12) { + int compress = stbi__get32le(s); + if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE"); + stbi__get32le(s); // discard sizeof + stbi__get32le(s); // discard hres + stbi__get32le(s); // discard vres + stbi__get32le(s); // discard colorsused + stbi__get32le(s); // discard max important + if (hsz == 40 || hsz == 56) { + if (hsz == 56) { + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + } + if (info->bpp == 16 || info->bpp == 32) { + if (compress == 0) { + if (info->bpp == 32) { + info->mr = 0xffu << 16; + info->mg = 0xffu << 8; + info->mb = 0xffu << 0; + info->ma = 0xffu << 24; + info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0 + } else { + info->mr = 31u << 10; + info->mg = 31u << 5; + info->mb = 31u << 0; + } + } else if (compress == 3) { + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + // not documented, but generated by photoshop and handled by mspaint + if (info->mr == info->mg && info->mg == info->mb) { + // ?!?!? + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else { + int i; + if (hsz != 108 && hsz != 124) + return stbi__errpuc("bad BMP", "bad BMP"); + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + info->ma = stbi__get32le(s); + stbi__get32le(s); // discard color space + for (i=0; i < 12; ++i) + stbi__get32le(s); // discard color space parameters + if (hsz == 124) { + stbi__get32le(s); // discard rendering intent + stbi__get32le(s); // discard offset of profile data + stbi__get32le(s); // discard size of profile data + stbi__get32le(s); // discard reserved + } + } + } + return (void *) 1; +} + + +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *out; + unsigned int mr=0,mg=0,mb=0,ma=0, all_a; + stbi_uc pal[256][4]; + int psize=0,i,j,width; + int flip_vertically, pad, target; + stbi__bmp_data info; + STBI_NOTUSED(ri); + + info.all_a = 255; + if (stbi__bmp_parse_header(s, &info) == NULL) + return NULL; // error code already set + + flip_vertically = ((int) s->img_y) > 0; + s->img_y = abs((int) s->img_y); + + mr = info.mr; + mg = info.mg; + mb = info.mb; + ma = info.ma; + all_a = info.all_a; + + if (info.hsz == 12) { + if (info.bpp < 24) + psize = (info.offset - 14 - 24) / 3; + } else { + if (info.bpp < 16) + psize = (info.offset - 14 - info.hsz) >> 2; + } + + s->img_n = ma ? 4 : 3; + if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 + target = req_comp; + else + target = s->img_n; // if they want monochrome, we'll post-convert + + // sanity-check size + if (!stbi__mad3sizes_valid(target, s->img_x, s->img_y, 0)) + return stbi__errpuc("too large", "Corrupt BMP"); + + out = (stbi_uc *) stbi__malloc_mad3(target, s->img_x, s->img_y, 0); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + if (info.bpp < 16) { + int z=0; + if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); } + for (i=0; i < psize; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + if (info.hsz != 12) stbi__get8(s); + pal[i][3] = 255; + } + stbi__skip(s, info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); + if (info.bpp == 1) width = (s->img_x + 7) >> 3; + else if (info.bpp == 4) width = (s->img_x + 1) >> 1; + else if (info.bpp == 8) width = s->img_x; + else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); } + pad = (-width)&3; + if (info.bpp == 1) { + for (j=0; j < (int) s->img_y; ++j) { + int bit_offset = 7, v = stbi__get8(s); + for (i=0; i < (int) s->img_x; ++i) { + int color = (v>>bit_offset)&0x1; + out[z++] = pal[color][0]; + out[z++] = pal[color][1]; + out[z++] = pal[color][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + if((--bit_offset) < 0) { + bit_offset = 7; + v = stbi__get8(s); + } + } + stbi__skip(s, pad); + } + } else { + for (j=0; j < (int) s->img_y; ++j) { + for (i=0; i < (int) s->img_x; i += 2) { + int v=stbi__get8(s),v2=0; + if (info.bpp == 4) { + v2 = v & 15; + v >>= 4; + } + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + v = (info.bpp == 8) ? stbi__get8(s) : v2; + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + } + stbi__skip(s, pad); + } + } + } else { + int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; + int z = 0; + int easy=0; + stbi__skip(s, info.offset - 14 - info.hsz); + if (info.bpp == 24) width = 3 * s->img_x; + else if (info.bpp == 16) width = 2*s->img_x; + else /* bpp = 32 and pad = 0 */ width=0; + pad = (-width) & 3; + if (info.bpp == 24) { + easy = 1; + } else if (info.bpp == 32) { + if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) + easy = 2; + } + if (!easy) { + if (!mr || !mg || !mb) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } + // right shift amt to put high bit in position #7 + rshift = stbi__high_bit(mr)-7; rcount = stbi__bitcount(mr); + gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg); + bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb); + ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma); + } + for (j=0; j < (int) s->img_y; ++j) { + if (easy) { + for (i=0; i < (int) s->img_x; ++i) { + unsigned char a; + out[z+2] = stbi__get8(s); + out[z+1] = stbi__get8(s); + out[z+0] = stbi__get8(s); + z += 3; + a = (easy == 2 ? stbi__get8(s) : 255); + all_a |= a; + if (target == 4) out[z++] = a; + } + } else { + int bpp = info.bpp; + for (i=0; i < (int) s->img_x; ++i) { + stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s)); + unsigned int a; + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount)); + a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255); + all_a |= a; + if (target == 4) out[z++] = STBI__BYTECAST(a); + } + } + stbi__skip(s, pad); + } + } + + // if alpha channel is all 0s, replace with all 255s + if (target == 4 && all_a == 0) + for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4) + out[i] = 255; + + if (flip_vertically) { + stbi_uc t; + for (j=0; j < (int) s->img_y>>1; ++j) { + stbi_uc *p1 = out + j *s->img_x*target; + stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target; + for (i=0; i < (int) s->img_x*target; ++i) { + t = p1[i]; p1[i] = p2[i]; p2[i] = t; + } + } + } + + if (req_comp && req_comp != target) { + out = stbi__convert_format(out, target, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + return out; +} +#endif + +// Targa Truevision - TGA +// by Jonathan Dummer +#ifndef STBI_NO_TGA +// returns STBI_rgb or whatever, 0 on error +static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16) +{ + // only RGB or RGBA (incl. 16bit) or grey allowed + if (is_rgb16) *is_rgb16 = 0; + switch(bits_per_pixel) { + case 8: return STBI_grey; + case 16: if(is_grey) return STBI_grey_alpha; + // fallthrough + case 15: if(is_rgb16) *is_rgb16 = 1; + return STBI_rgb; + case 24: // fallthrough + case 32: return bits_per_pixel/8; + default: return 0; + } +} + +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) +{ + int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp; + int sz, tga_colormap_type; + stbi__get8(s); // discard Offset + tga_colormap_type = stbi__get8(s); // colormap type + if( tga_colormap_type > 1 ) { + stbi__rewind(s); + return 0; // only RGB or indexed allowed + } + tga_image_type = stbi__get8(s); // image type + if ( tga_colormap_type == 1 ) { // colormapped (paletted) image + if (tga_image_type != 1 && tga_image_type != 9) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip image x and y origin + tga_colormap_bpp = sz; + } else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE + if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) { + stbi__rewind(s); + return 0; // only RGB or grey allowed, +/- RLE + } + stbi__skip(s,9); // skip colormap specification and image x/y origin + tga_colormap_bpp = 0; + } + tga_w = stbi__get16le(s); + if( tga_w < 1 ) { + stbi__rewind(s); + return 0; // test width + } + tga_h = stbi__get16le(s); + if( tga_h < 1 ) { + stbi__rewind(s); + return 0; // test height + } + tga_bits_per_pixel = stbi__get8(s); // bits per pixel + stbi__get8(s); // ignore alpha bits + if (tga_colormap_bpp != 0) { + if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) { + // when using a colormap, tga_bits_per_pixel is the size of the indexes + // I don't think anything but 8 or 16bit indexes makes sense + stbi__rewind(s); + return 0; + } + tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL); + } else { + tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL); + } + if(!tga_comp) { + stbi__rewind(s); + return 0; + } + if (x) *x = tga_w; + if (y) *y = tga_h; + if (comp) *comp = tga_comp; + return 1; // seems to have passed everything +} + +static int stbi__tga_test(stbi__context *s) +{ + int res = 0; + int sz, tga_color_type; + stbi__get8(s); // discard Offset + tga_color_type = stbi__get8(s); // color type + if ( tga_color_type > 1 ) goto errorEnd; // only RGB or indexed allowed + sz = stbi__get8(s); // image type + if ( tga_color_type == 1 ) { // colormapped (paletted) image + if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9 + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + stbi__skip(s,4); // skip image x and y origin + } else { // "normal" image w/o colormap + if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE + stbi__skip(s,9); // skip colormap specification and image x/y origin + } + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test width + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test height + sz = stbi__get8(s); // bits per pixel + if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + + res = 1; // if we got this far, everything's good and we can return 1 instead of 0 + +errorEnd: + stbi__rewind(s); + return res; +} + +// read 16bit value and convert to 24bit RGB +static void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out) +{ + stbi__uint16 px = (stbi__uint16)stbi__get16le(s); + stbi__uint16 fiveBitMask = 31; + // we have 3 channels with 5bits each + int r = (px >> 10) & fiveBitMask; + int g = (px >> 5) & fiveBitMask; + int b = px & fiveBitMask; + // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later + out[0] = (stbi_uc)((r * 255)/31); + out[1] = (stbi_uc)((g * 255)/31); + out[2] = (stbi_uc)((b * 255)/31); + + // some people claim that the most significant bit might be used for alpha + // (possibly if an alpha-bit is set in the "image descriptor byte") + // but that only made 16bit test images completely translucent.. + // so let's treat all 15 and 16bit TGAs as RGB with no alpha. +} + +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + // read in the TGA header stuff + int tga_offset = stbi__get8(s); + int tga_indexed = stbi__get8(s); + int tga_image_type = stbi__get8(s); + int tga_is_RLE = 0; + int tga_palette_start = stbi__get16le(s); + int tga_palette_len = stbi__get16le(s); + int tga_palette_bits = stbi__get8(s); + int tga_x_origin = stbi__get16le(s); + int tga_y_origin = stbi__get16le(s); + int tga_width = stbi__get16le(s); + int tga_height = stbi__get16le(s); + int tga_bits_per_pixel = stbi__get8(s); + int tga_comp, tga_rgb16=0; + int tga_inverted = stbi__get8(s); + // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?) + // image data + unsigned char *tga_data; + unsigned char *tga_palette = NULL; + int i, j; + unsigned char raw_data[4] = {0}; + int RLE_count = 0; + int RLE_repeating = 0; + int read_next_pixel = 1; + STBI_NOTUSED(ri); + + // do a tiny bit of precessing + if ( tga_image_type >= 8 ) + { + tga_image_type -= 8; + tga_is_RLE = 1; + } + tga_inverted = 1 - ((tga_inverted >> 5) & 1); + + // If I'm paletted, then I'll use the number of bits from the palette + if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16); + else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16); + + if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency + return stbi__errpuc("bad format", "Can't find out TGA pixelformat"); + + // tga info + *x = tga_width; + *y = tga_height; + if (comp) *comp = tga_comp; + + if (!stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0)) + return stbi__errpuc("too large", "Corrupt TGA"); + + tga_data = (unsigned char*)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0); + if (!tga_data) return stbi__errpuc("outofmem", "Out of memory"); + + // skip to the data's starting position (offset usually = 0) + stbi__skip(s, tga_offset ); + + if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) { + for (i=0; i < tga_height; ++i) { + int row = tga_inverted ? tga_height -i - 1 : i; + stbi_uc *tga_row = tga_data + row*tga_width*tga_comp; + stbi__getn(s, tga_row, tga_width * tga_comp); + } + } else { + // do I need to load a palette? + if ( tga_indexed) + { + // any data to skip? (offset usually = 0) + stbi__skip(s, tga_palette_start ); + // load the palette + tga_palette = (unsigned char*)stbi__malloc_mad2(tga_palette_len, tga_comp, 0); + if (!tga_palette) { + STBI_FREE(tga_data); + return stbi__errpuc("outofmem", "Out of memory"); + } + if (tga_rgb16) { + stbi_uc *pal_entry = tga_palette; + STBI_ASSERT(tga_comp == STBI_rgb); + for (i=0; i < tga_palette_len; ++i) { + stbi__tga_read_rgb16(s, pal_entry); + pal_entry += tga_comp; + } + } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) { + STBI_FREE(tga_data); + STBI_FREE(tga_palette); + return stbi__errpuc("bad palette", "Corrupt TGA"); + } + } + // load the data + for (i=0; i < tga_width * tga_height; ++i) + { + // if I'm in RLE mode, do I need to get a RLE stbi__pngchunk? + if ( tga_is_RLE ) + { + if ( RLE_count == 0 ) + { + // yep, get the next byte as a RLE command + int RLE_cmd = stbi__get8(s); + RLE_count = 1 + (RLE_cmd & 127); + RLE_repeating = RLE_cmd >> 7; + read_next_pixel = 1; + } else if ( !RLE_repeating ) + { + read_next_pixel = 1; + } + } else + { + read_next_pixel = 1; + } + // OK, if I need to read a pixel, do it now + if ( read_next_pixel ) + { + // load however much data we did have + if ( tga_indexed ) + { + // read in index, then perform the lookup + int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s); + if ( pal_idx >= tga_palette_len ) { + // invalid index + pal_idx = 0; + } + pal_idx *= tga_comp; + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = tga_palette[pal_idx+j]; + } + } else if(tga_rgb16) { + STBI_ASSERT(tga_comp == STBI_rgb); + stbi__tga_read_rgb16(s, raw_data); + } else { + // read in the data raw + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = stbi__get8(s); + } + } + // clear the reading flag for the next pixel + read_next_pixel = 0; + } // end of reading a pixel + + // copy data + for (j = 0; j < tga_comp; ++j) + tga_data[i*tga_comp+j] = raw_data[j]; + + // in case we're in RLE mode, keep counting down + --RLE_count; + } + // do I need to invert the image? + if ( tga_inverted ) + { + for (j = 0; j*2 < tga_height; ++j) + { + int index1 = j * tga_width * tga_comp; + int index2 = (tga_height - 1 - j) * tga_width * tga_comp; + for (i = tga_width * tga_comp; i > 0; --i) + { + unsigned char temp = tga_data[index1]; + tga_data[index1] = tga_data[index2]; + tga_data[index2] = temp; + ++index1; + ++index2; + } + } + } + // clear my palette, if I had one + if ( tga_palette != NULL ) + { + STBI_FREE( tga_palette ); + } + } + + // swap RGB - if the source data was RGB16, it already is in the right order + if (tga_comp >= 3 && !tga_rgb16) + { + unsigned char* tga_pixel = tga_data; + for (i=0; i < tga_width * tga_height; ++i) + { + unsigned char temp = tga_pixel[0]; + tga_pixel[0] = tga_pixel[2]; + tga_pixel[2] = temp; + tga_pixel += tga_comp; + } + } + + // convert to target component count + if (req_comp && req_comp != tga_comp) + tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height); + + // the things I do to get rid of an error message, and yet keep + // Microsoft's C compilers happy... [8^( + tga_palette_start = tga_palette_len = tga_palette_bits = + tga_x_origin = tga_y_origin = 0; + // OK, done + return tga_data; +} +#endif + +// ************************************************************************************************* +// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s) +{ + int r = (stbi__get32be(s) == 0x38425053); + stbi__rewind(s); + return r; +} + +static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount) +{ + int count, nleft, len; + + count = 0; + while ((nleft = pixelCount - count) > 0) { + len = stbi__get8(s); + if (len == 128) { + // No-op. + } else if (len < 128) { + // Copy next len+1 bytes literally. + len++; + if (len > nleft) return 0; // corrupt data + count += len; + while (len) { + *p = stbi__get8(s); + p += 4; + len--; + } + } else if (len > 128) { + stbi_uc val; + // Next -len+1 bytes in the dest are replicated from next source byte. + // (Interpret len as a negative 8-bit int.) + len = 257 - len; + if (len > nleft) return 0; // corrupt data + val = stbi__get8(s); + count += len; + while (len) { + *p = val; + p += 4; + len--; + } + } + } + + return 1; +} + +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) +{ + int pixelCount; + int channelCount, compression; + int channel, i; + int bitdepth; + int w,h; + stbi_uc *out; + STBI_NOTUSED(ri); + + // Check identifier + if (stbi__get32be(s) != 0x38425053) // "8BPS" + return stbi__errpuc("not PSD", "Corrupt PSD image"); + + // Check file type version. + if (stbi__get16be(s) != 1) + return stbi__errpuc("wrong version", "Unsupported version of PSD image"); + + // Skip 6 reserved bytes. + stbi__skip(s, 6 ); + + // Read the number of channels (R, G, B, A, etc). + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) + return stbi__errpuc("wrong channel count", "Unsupported number of channels in PSD image"); + + // Read the rows and columns of the image. + h = stbi__get32be(s); + w = stbi__get32be(s); + + // Make sure the depth is 8 bits. + bitdepth = stbi__get16be(s); + if (bitdepth != 8 && bitdepth != 16) + return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit"); + + // Make sure the color mode is RGB. + // Valid options are: + // 0: Bitmap + // 1: Grayscale + // 2: Indexed color + // 3: RGB color + // 4: CMYK color + // 7: Multichannel + // 8: Duotone + // 9: Lab color + if (stbi__get16be(s) != 3) + return stbi__errpuc("wrong color format", "PSD is not in RGB color format"); + + // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.) + stbi__skip(s,stbi__get32be(s) ); + + // Skip the image resources. (resolution, pen tool paths, etc) + stbi__skip(s, stbi__get32be(s) ); + + // Skip the reserved data. + stbi__skip(s, stbi__get32be(s) ); + + // Find out if the data is compressed. + // Known values: + // 0: no compression + // 1: RLE compressed + compression = stbi__get16be(s); + if (compression > 1) + return stbi__errpuc("bad compression", "PSD has an unknown compression format"); + + // Check size + if (!stbi__mad3sizes_valid(4, w, h, 0)) + return stbi__errpuc("too large", "Corrupt PSD"); + + // Create the destination image. + + if (!compression && bitdepth == 16 && bpc == 16) { + out = (stbi_uc *) stbi__malloc_mad3(8, w, h, 0); + ri->bits_per_channel = 16; + } else + out = (stbi_uc *) stbi__malloc(4 * w*h); + + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + pixelCount = w*h; + + // Initialize the data to zero. + //memset( out, 0, pixelCount * 4 ); + + // Finally, the image data. + if (compression) { + // RLE as used by .PSD and .TIFF + // Loop until you get the number of unpacked bytes you are expecting: + // Read the next source byte into n. + // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. + // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times. + // Else if n is 128, noop. + // Endloop + + // The RLE-compressed data is preceded by a 2-byte data count for each row in the data, + // which we're going to just skip. + stbi__skip(s, h * channelCount * 2 ); + + // Read the RLE data by channel. + for (channel = 0; channel < 4; channel++) { + stbi_uc *p; + + p = out+channel; + if (channel >= channelCount) { + // Fill this channel with default data. + for (i = 0; i < pixelCount; i++, p += 4) + *p = (channel == 3 ? 255 : 0); + } else { + // Read the RLE data. + if (!stbi__psd_decode_rle(s, p, pixelCount)) { + STBI_FREE(out); + return stbi__errpuc("corrupt", "bad RLE data"); + } + } + } + + } else { + // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) + // where each channel consists of an 8-bit (or 16-bit) value for each pixel in the image. + + // Read the data by channel. + for (channel = 0; channel < 4; channel++) { + if (channel >= channelCount) { + // Fill this channel with default data. + if (bitdepth == 16 && bpc == 16) { + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + stbi__uint16 val = channel == 3 ? 65535 : 0; + for (i = 0; i < pixelCount; i++, q += 4) + *q = val; + } else { + stbi_uc *p = out+channel; + stbi_uc val = channel == 3 ? 255 : 0; + for (i = 0; i < pixelCount; i++, p += 4) + *p = val; + } + } else { + if (ri->bits_per_channel == 16) { // output bpc + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + for (i = 0; i < pixelCount; i++, q += 4) + *q = (stbi__uint16) stbi__get16be(s); + } else { + stbi_uc *p = out+channel; + if (bitdepth == 16) { // input bpc + for (i = 0; i < pixelCount; i++, p += 4) + *p = (stbi_uc) (stbi__get16be(s) >> 8); + } else { + for (i = 0; i < pixelCount; i++, p += 4) + *p = stbi__get8(s); + } + } + } + } + } + + // remove weird white matte from PSD + if (channelCount >= 4) { + if (ri->bits_per_channel == 16) { + for (i=0; i < w*h; ++i) { + stbi__uint16 *pixel = (stbi__uint16 *) out + 4*i; + if (pixel[3] != 0 && pixel[3] != 65535) { + float a = pixel[3] / 65535.0f; + float ra = 1.0f / a; + float inv_a = 65535.0f * (1 - ra); + pixel[0] = (stbi__uint16) (pixel[0]*ra + inv_a); + pixel[1] = (stbi__uint16) (pixel[1]*ra + inv_a); + pixel[2] = (stbi__uint16) (pixel[2]*ra + inv_a); + } + } + } else { + for (i=0; i < w*h; ++i) { + unsigned char *pixel = out + 4*i; + if (pixel[3] != 0 && pixel[3] != 255) { + float a = pixel[3] / 255.0f; + float ra = 1.0f / a; + float inv_a = 255.0f * (1 - ra); + pixel[0] = (unsigned char) (pixel[0]*ra + inv_a); + pixel[1] = (unsigned char) (pixel[1]*ra + inv_a); + pixel[2] = (unsigned char) (pixel[2]*ra + inv_a); + } + } + } + } + + // convert to desired output format + if (req_comp && req_comp != 4) { + if (ri->bits_per_channel == 16) + out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, 4, req_comp, w, h); + else + out = stbi__convert_format(out, 4, req_comp, w, h); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + if (comp) *comp = 4; + *y = h; + *x = w; + + return out; +} +#endif + +// ************************************************************************************************* +// Softimage PIC loader +// by Tom Seddon +// +// See http://softimage.wiki.softimage.com/index.php/INFO:_PIC_file_format +// See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/ + +#ifndef STBI_NO_PIC +static int stbi__pic_is4(stbi__context *s,const char *str) +{ + int i; + for (i=0; i<4; ++i) + if (stbi__get8(s) != (stbi_uc)str[i]) + return 0; + + return 1; +} + +static int stbi__pic_test_core(stbi__context *s) +{ + int i; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) + return 0; + + for(i=0;i<84;++i) + stbi__get8(s); + + if (!stbi__pic_is4(s,"PICT")) + return 0; + + return 1; +} + +typedef struct +{ + stbi_uc size,type,channel; +} stbi__pic_packet; + +static stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest) +{ + int mask=0x80, i; + + for (i=0; i<4; ++i, mask>>=1) { + if (channel & mask) { + if (stbi__at_eof(s)) return stbi__errpuc("bad file","PIC file too short"); + dest[i]=stbi__get8(s); + } + } + + return dest; +} + +static void stbi__copyval(int channel,stbi_uc *dest,const stbi_uc *src) +{ + int mask=0x80,i; + + for (i=0;i<4; ++i, mask>>=1) + if (channel&mask) + dest[i]=src[i]; +} + +static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *comp, stbi_uc *result) +{ + int act_comp=0,num_packets=0,y,chained; + stbi__pic_packet packets[10]; + + // this will (should...) cater for even some bizarre stuff like having data + // for the same channel in multiple packets. + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return stbi__errpuc("bad format","too many packets"); + + packet = &packets[num_packets++]; + + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + + act_comp |= packet->channel; + + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (reading packets)"); + if (packet->size != 8) return stbi__errpuc("bad format","packet isn't 8bpp"); + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel? + + for(y=0; ytype) { + default: + return stbi__errpuc("bad format","packet has bad compression type"); + + case 0: {//uncompressed + int x; + + for(x=0;xchannel,dest)) + return 0; + break; + } + + case 1://Pure RLE + { + int left=width, i; + + while (left>0) { + stbi_uc count,value[4]; + + count=stbi__get8(s); + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pure read count)"); + + if (count > left) + count = (stbi_uc) left; + + if (!stbi__readval(s,packet->channel,value)) return 0; + + for(i=0; ichannel,dest,value); + left -= count; + } + } + break; + + case 2: {//Mixed RLE + int left=width; + while (left>0) { + int count = stbi__get8(s), i; + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (mixed read count)"); + + if (count >= 128) { // Repeated + stbi_uc value[4]; + + if (count==128) + count = stbi__get16be(s); + else + count -= 127; + if (count > left) + return stbi__errpuc("bad file","scanline overrun"); + + if (!stbi__readval(s,packet->channel,value)) + return 0; + + for(i=0;ichannel,dest,value); + } else { // Raw + ++count; + if (count>left) return stbi__errpuc("bad file","scanline overrun"); + + for(i=0;ichannel,dest)) + return 0; + } + left-=count; + } + break; + } + } + } + } + + return result; +} + +static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp, stbi__result_info *ri) +{ + stbi_uc *result; + int i, x,y, internal_comp; + STBI_NOTUSED(ri); + + if (!comp) comp = &internal_comp; + + for (i=0; i<92; ++i) + stbi__get8(s); + + x = stbi__get16be(s); + y = stbi__get16be(s); + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)"); + if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode"); + + stbi__get32be(s); //skip `ratio' + stbi__get16be(s); //skip `fields' + stbi__get16be(s); //skip `pad' + + // intermediate buffer is RGBA + result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0); + memset(result, 0xff, x*y*4); + + if (!stbi__pic_load_core(s,x,y,comp, result)) { + STBI_FREE(result); + result=0; + } + *px = x; + *py = y; + if (req_comp == 0) req_comp = *comp; + result=stbi__convert_format(result,4,req_comp,x,y); + + return result; +} + +static int stbi__pic_test(stbi__context *s) +{ + int r = stbi__pic_test_core(s); + stbi__rewind(s); + return r; +} +#endif + +// ************************************************************************************************* +// GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb + +#ifndef STBI_NO_GIF +typedef struct +{ + stbi__int16 prefix; + stbi_uc first; + stbi_uc suffix; +} stbi__gif_lzw; + +typedef struct +{ + int w,h; + stbi_uc *out; // output buffer (always 4 components) + stbi_uc *background; // The current "background" as far as a gif is concerned + stbi_uc *history; + int flags, bgindex, ratio, transparent, eflags; + stbi_uc pal[256][4]; + stbi_uc lpal[256][4]; + stbi__gif_lzw codes[8192]; + stbi_uc *color_table; + int parse, step; + int lflags; + int start_x, start_y; + int max_x, max_y; + int cur_x, cur_y; + int line_size; + int delay; +} stbi__gif; + +static int stbi__gif_test_raw(stbi__context *s) +{ + int sz; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') return 0; + sz = stbi__get8(s); + if (sz != '9' && sz != '7') return 0; + if (stbi__get8(s) != 'a') return 0; + return 1; +} + +static int stbi__gif_test(stbi__context *s) +{ + int r = stbi__gif_test_raw(s); + stbi__rewind(s); + return r; +} + +static void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, int transp) +{ + int i; + for (i=0; i < num_entries; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + pal[i][3] = transp == i ? 0 : 255; + } +} + +static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info) +{ + stbi_uc version; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') + return stbi__err("not GIF", "Corrupt GIF"); + + version = stbi__get8(s); + if (version != '7' && version != '9') return stbi__err("not GIF", "Corrupt GIF"); + if (stbi__get8(s) != 'a') return stbi__err("not GIF", "Corrupt GIF"); + + stbi__g_failure_reason = ""; + g->w = stbi__get16le(s); + g->h = stbi__get16le(s); + g->flags = stbi__get8(s); + g->bgindex = stbi__get8(s); + g->ratio = stbi__get8(s); + g->transparent = -1; + + if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments + + if (is_info) return 1; + + if (g->flags & 0x80) + stbi__gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1); + + return 1; +} + +static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif)); + if (!stbi__gif_header(s, g, comp, 1)) { + STBI_FREE(g); + stbi__rewind( s ); + return 0; + } + if (x) *x = g->w; + if (y) *y = g->h; + STBI_FREE(g); + return 1; +} + +static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) +{ + stbi_uc *p, *c; + int idx; + + // recurse to decode the prefixes, since the linked-list is backwards, + // and working backwards through an interleaved image would be nasty + if (g->codes[code].prefix >= 0) + stbi__out_gif_code(g, g->codes[code].prefix); + + if (g->cur_y >= g->max_y) return; + + idx = g->cur_x + g->cur_y; + p = &g->out[idx]; + g->history[idx / 4] = 1; + + c = &g->color_table[g->codes[code].suffix * 4]; + if (c[3] > 128) { // don't render transparent pixels; + p[0] = c[2]; + p[1] = c[1]; + p[2] = c[0]; + p[3] = c[3]; + } + g->cur_x += 4; + + if (g->cur_x >= g->max_x) { + g->cur_x = g->start_x; + g->cur_y += g->step; + + while (g->cur_y >= g->max_y && g->parse > 0) { + g->step = (1 << g->parse) * g->line_size; + g->cur_y = g->start_y + (g->step >> 1); + --g->parse; + } + } +} + +static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) +{ + stbi_uc lzw_cs; + stbi__int32 len, init_code; + stbi__uint32 first; + stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear; + stbi__gif_lzw *p; + + lzw_cs = stbi__get8(s); + if (lzw_cs > 12) return NULL; + clear = 1 << lzw_cs; + first = 1; + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + bits = 0; + valid_bits = 0; + for (init_code = 0; init_code < clear; init_code++) { + g->codes[init_code].prefix = -1; + g->codes[init_code].first = (stbi_uc) init_code; + g->codes[init_code].suffix = (stbi_uc) init_code; + } + + // support no starting clear code + avail = clear+2; + oldcode = -1; + + len = 0; + for(;;) { + if (valid_bits < codesize) { + if (len == 0) { + len = stbi__get8(s); // start new block + if (len == 0) + return g->out; + } + --len; + bits |= (stbi__int32) stbi__get8(s) << valid_bits; + valid_bits += 8; + } else { + stbi__int32 code = bits & codemask; + bits >>= codesize; + valid_bits -= codesize; + // @OPTIMIZE: is there some way we can accelerate the non-clear path? + if (code == clear) { // clear code + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + avail = clear + 2; + oldcode = -1; + first = 0; + } else if (code == clear + 1) { // end of stream code + stbi__skip(s, len); + while ((len = stbi__get8(s)) > 0) + stbi__skip(s,len); + return g->out; + } else if (code <= avail) { + if (first) { + return stbi__errpuc("no clear code", "Corrupt GIF"); + } + + if (oldcode >= 0) { + p = &g->codes[avail++]; + if (avail > 8192) { + return stbi__errpuc("too many codes", "Corrupt GIF"); + } + + p->prefix = (stbi__int16) oldcode; + p->first = g->codes[oldcode].first; + p->suffix = (code == avail) ? p->first : g->codes[code].first; + } else if (code == avail) + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + + stbi__out_gif_code(g, (stbi__uint16) code); + + if ((avail & codemask) == 0 && avail <= 0x0FFF) { + codesize++; + codemask = (1 << codesize) - 1; + } + + oldcode = code; + } else { + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + } + } + } +} + +// this function is designed to support animated gifs, although stb_image doesn't support it +// two back is the image from two frames ago, used for a very specific disposal format +static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp, stbi_uc *two_back) +{ + int dispose; + int first_frame; + int pi; + int pcount; + STBI_NOTUSED(req_comp); + + // on first frame, any non-written pixels get the background colour (non-transparent) + first_frame = 0; + if (g->out == 0) { + if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header + if (!stbi__mad3sizes_valid(4, g->w, g->h, 0)) + return stbi__errpuc("too large", "GIF image is too large"); + pcount = g->w * g->h; + g->out = (stbi_uc *) stbi__malloc(4 * pcount); + g->background = (stbi_uc *) stbi__malloc(4 * pcount); + g->history = (stbi_uc *) stbi__malloc(pcount); + if (!g->out || !g->background || !g->history) + return stbi__errpuc("outofmem", "Out of memory"); + + // image is treated as "transparent" at the start - ie, nothing overwrites the current background; + // background colour is only used for pixels that are not rendered first frame, after that "background" + // color refers to the color that was there the previous frame. + memset(g->out, 0x00, 4 * pcount); + memset(g->background, 0x00, 4 * pcount); // state of the background (starts transparent) + memset(g->history, 0x00, pcount); // pixels that were affected previous frame + first_frame = 1; + } else { + // second frame - how do we dispoase of the previous one? + dispose = (g->eflags & 0x1C) >> 2; + pcount = g->w * g->h; + + if ((dispose == 3) && (two_back == 0)) { + dispose = 2; // if I don't have an image to revert back to, default to the old background + } + + if (dispose == 3) { // use previous graphic + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { + memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 ); + } + } + } else if (dispose == 2) { + // restore what was changed last frame to background before that frame; + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { + memcpy( &g->out[pi * 4], &g->background[pi * 4], 4 ); + } + } + } else { + // This is a non-disposal case eithe way, so just + // leave the pixels as is, and they will become the new background + // 1: do not dispose + // 0: not specified. + } + + // background is what out is after the undoing of the previou frame; + memcpy( g->background, g->out, 4 * g->w * g->h ); + } + + // clear my history; + memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame + + for (;;) { + int tag = stbi__get8(s); + switch (tag) { + case 0x2C: /* Image Descriptor */ + { + stbi__int32 x, y, w, h; + stbi_uc *o; + + x = stbi__get16le(s); + y = stbi__get16le(s); + w = stbi__get16le(s); + h = stbi__get16le(s); + if (((x + w) > (g->w)) || ((y + h) > (g->h))) + return stbi__errpuc("bad Image Descriptor", "Corrupt GIF"); + + g->line_size = g->w * 4; + g->start_x = x * 4; + g->start_y = y * g->line_size; + g->max_x = g->start_x + w * 4; + g->max_y = g->start_y + h * g->line_size; + g->cur_x = g->start_x; + g->cur_y = g->start_y; + + // if the width of the specified rectangle is 0, that means + // we may not see *any* pixels or the image is malformed; + // to make sure this is caught, move the current y down to + // max_y (which is what out_gif_code checks). + if (w == 0) + g->cur_y = g->max_y; + + g->lflags = stbi__get8(s); + + if (g->lflags & 0x40) { + g->step = 8 * g->line_size; // first interlaced spacing + g->parse = 3; + } else { + g->step = g->line_size; + g->parse = 0; + } + + if (g->lflags & 0x80) { + stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1); + g->color_table = (stbi_uc *) g->lpal; + } else if (g->flags & 0x80) { + g->color_table = (stbi_uc *) g->pal; + } else + return stbi__errpuc("missing color table", "Corrupt GIF"); + + o = stbi__process_gif_raster(s, g); + if (!o) return NULL; + + // if this was the first frame, + pcount = g->w * g->h; + if (first_frame && (g->bgindex > 0)) { + // if first frame, any pixel not drawn to gets the background color + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi] == 0) { + g->pal[g->bgindex][3] = 255; // just in case it was made transparent, undo that; It will be reset next frame if need be; + memcpy( &g->out[pi * 4], &g->pal[g->bgindex], 4 ); + } + } + } + + return o; + } + + case 0x21: // Comment Extension. + { + int len; + int ext = stbi__get8(s); + if (ext == 0xF9) { // Graphic Control Extension. + len = stbi__get8(s); + if (len == 4) { + g->eflags = stbi__get8(s); + g->delay = 10 * stbi__get16le(s); // delay - 1/100th of a second, saving as 1/1000ths. + + // unset old transparent + if (g->transparent >= 0) { + g->pal[g->transparent][3] = 255; + } + if (g->eflags & 0x01) { + g->transparent = stbi__get8(s); + if (g->transparent >= 0) { + g->pal[g->transparent][3] = 0; + } + } else { + // don't need transparent + stbi__skip(s, 1); + g->transparent = -1; + } + } else { + stbi__skip(s, len); + break; + } + } + while ((len = stbi__get8(s)) != 0) { + stbi__skip(s, len); + } + break; + } + + case 0x3B: // gif stream termination code + return (stbi_uc *) s; // using '1' causes warning on some compilers + + default: + return stbi__errpuc("unknown code", "Corrupt GIF"); + } + } +} + +static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp) +{ + if (stbi__gif_test(s)) { + int layers = 0; + stbi_uc *u = 0; + stbi_uc *out = 0; + stbi_uc *two_back = 0; + stbi__gif g; + int stride; + memset(&g, 0, sizeof(g)); + if (delays) { + *delays = 0; + } + + do { + u = stbi__gif_load_next(s, &g, comp, req_comp, two_back); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + + if (u) { + *x = g.w; + *y = g.h; + ++layers; + stride = g.w * g.h * 4; + + if (out) { + out = (stbi_uc*) STBI_REALLOC( out, layers * stride ); + if (delays) { + *delays = (int*) STBI_REALLOC( *delays, sizeof(int) * layers ); + } + } else { + out = (stbi_uc*)stbi__malloc( layers * stride ); + if (delays) { + *delays = (int*) stbi__malloc( layers * sizeof(int) ); + } + } + memcpy( out + ((layers - 1) * stride), u, stride ); + if (layers >= 2) { + two_back = out - 2 * stride; + } + + if (delays) { + (*delays)[layers - 1U] = g.delay; + } + } + } while (u != 0); + + // free temp buffer; + STBI_FREE(g.out); + STBI_FREE(g.history); + STBI_FREE(g.background); + + // do the final conversion after loading everything; + if (req_comp && req_comp != 4) + out = stbi__convert_format(out, 4, req_comp, layers * g.w, g.h); + + *z = layers; + return out; + } else { + return stbi__errpuc("not GIF", "Image was not as a gif type."); + } +} + +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *u = 0; + stbi__gif g; + memset(&g, 0, sizeof(g)); + STBI_NOTUSED(ri); + + u = stbi__gif_load_next(s, &g, comp, req_comp, 0); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + if (u) { + *x = g.w; + *y = g.h; + + // moved conversion to after successful load so that the same + // can be done for multiple frames. + if (req_comp && req_comp != 4) + u = stbi__convert_format(u, 4, req_comp, g.w, g.h); + } else if (g.out) { + // if there was an error and we allocated an image buffer, free it! + STBI_FREE(g.out); + } + + // free buffers needed for multiple frame loading; + STBI_FREE(g.history); + STBI_FREE(g.background); + + return u; +} + +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp) +{ + return stbi__gif_info_raw(s,x,y,comp); +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR loader +// originally by Nicolas Schulz +#ifndef STBI_NO_HDR +static int stbi__hdr_test_core(stbi__context *s, const char *signature) +{ + int i; + for (i=0; signature[i]; ++i) + if (stbi__get8(s) != signature[i]) + return 0; + stbi__rewind(s); + return 1; +} + +static int stbi__hdr_test(stbi__context* s) +{ + int r = stbi__hdr_test_core(s, "#?RADIANCE\n"); + stbi__rewind(s); + if(!r) { + r = stbi__hdr_test_core(s, "#?RGBE\n"); + stbi__rewind(s); + } + return r; +} + +#define STBI__HDR_BUFLEN 1024 +static char *stbi__hdr_gettoken(stbi__context *z, char *buffer) +{ + int len=0; + char c = '\0'; + + c = (char) stbi__get8(z); + + while (!stbi__at_eof(z) && c != '\n') { + buffer[len++] = c; + if (len == STBI__HDR_BUFLEN-1) { + // flush to end of line + while (!stbi__at_eof(z) && stbi__get8(z) != '\n') + ; + break; + } + c = (char) stbi__get8(z); + } + + buffer[len] = 0; + return buffer; +} + +static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp) +{ + if ( input[3] != 0 ) { + float f1; + // Exponent + f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8)); + if (req_comp <= 2) + output[0] = (input[0] + input[1] + input[2]) * f1 / 3; + else { + output[0] = input[0] * f1; + output[1] = input[1] * f1; + output[2] = input[2] * f1; + } + if (req_comp == 2) output[1] = 1; + if (req_comp == 4) output[3] = 1; + } else { + switch (req_comp) { + case 4: output[3] = 1; /* fallthrough */ + case 3: output[0] = output[1] = output[2] = 0; + break; + case 2: output[1] = 1; /* fallthrough */ + case 1: output[0] = 0; + break; + } + } +} + +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int width, height; + stbi_uc *scanline; + float *hdr_data; + int len; + unsigned char count, value; + int i, j, k, c1,c2, z; + const char *headerToken; + STBI_NOTUSED(ri); + + // Check identifier + headerToken = stbi__hdr_gettoken(s,buffer); + if (strcmp(headerToken, "#?RADIANCE") != 0 && strcmp(headerToken, "#?RGBE") != 0) + return stbi__errpf("not HDR", "Corrupt HDR image"); + + // Parse header + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) return stbi__errpf("unsupported format", "Unsupported HDR format"); + + // Parse width and height + // can't use sscanf() if we're not using stdio! + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + height = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + width = (int) strtol(token, NULL, 10); + + *x = width; + *y = height; + + if (comp) *comp = 3; + if (req_comp == 0) req_comp = 3; + + if (!stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0)) + return stbi__errpf("too large", "HDR image is too large"); + + // Read data + hdr_data = (float *) stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0); + if (!hdr_data) + return stbi__errpf("outofmem", "Out of memory"); + + // Load image data + // image data is stored as some number of sca + if ( width < 8 || width >= 32768) { + // Read flat data + for (j=0; j < height; ++j) { + for (i=0; i < width; ++i) { + stbi_uc rgbe[4]; + main_decode_loop: + stbi__getn(s, rgbe, 4); + stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp); + } + } + } else { + // Read RLE-encoded data + scanline = NULL; + + for (j = 0; j < height; ++j) { + c1 = stbi__get8(s); + c2 = stbi__get8(s); + len = stbi__get8(s); + if (c1 != 2 || c2 != 2 || (len & 0x80)) { + // not run-length encoded, so we have to actually use THIS data as a decoded + // pixel (note this can't be a valid pixel--one of RGB must be >= 128) + stbi_uc rgbe[4]; + rgbe[0] = (stbi_uc) c1; + rgbe[1] = (stbi_uc) c2; + rgbe[2] = (stbi_uc) len; + rgbe[3] = (stbi_uc) stbi__get8(s); + stbi__hdr_convert(hdr_data, rgbe, req_comp); + i = 1; + j = 0; + STBI_FREE(scanline); + goto main_decode_loop; // yes, this makes no sense + } + len <<= 8; + len |= stbi__get8(s); + if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); } + if (scanline == NULL) { + scanline = (stbi_uc *) stbi__malloc_mad2(width, 4, 0); + if (!scanline) { + STBI_FREE(hdr_data); + return stbi__errpf("outofmem", "Out of memory"); + } + } + + for (k = 0; k < 4; ++k) { + int nleft; + i = 0; + while ((nleft = width - i) > 0) { + count = stbi__get8(s); + if (count > 128) { + // Run + value = stbi__get8(s); + count -= 128; + if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = value; + } else { + // Dump + if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = stbi__get8(s); + } + } + } + for (i=0; i < width; ++i) + stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp); + } + if (scanline) + STBI_FREE(scanline); + } + + return hdr_data; +} + +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int dummy; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + if (stbi__hdr_test(s) == 0) { + stbi__rewind( s ); + return 0; + } + + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) { + stbi__rewind( s ); + return 0; + } + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *y = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *x = (int) strtol(token, NULL, 10); + *comp = 3; + return 1; +} +#endif // STBI_NO_HDR + +#ifndef STBI_NO_BMP +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) +{ + void *p; + stbi__bmp_data info; + + info.all_a = 255; + p = stbi__bmp_parse_header(s, &info); + stbi__rewind( s ); + if (p == NULL) + return 0; + if (x) *x = s->img_x; + if (y) *y = s->img_y; + if (comp) *comp = info.ma ? 4 : 3; + return 1; +} +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) +{ + int channelCount, dummy, depth; + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + *y = stbi__get32be(s); + *x = stbi__get32be(s); + depth = stbi__get16be(s); + if (depth != 8 && depth != 16) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 3) { + stbi__rewind( s ); + return 0; + } + *comp = 4; + return 1; +} + +static int stbi__psd_is16(stbi__context *s) +{ + int channelCount, depth; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + (void) stbi__get32be(s); + (void) stbi__get32be(s); + depth = stbi__get16be(s); + if (depth != 16) { + stbi__rewind( s ); + return 0; + } + return 1; +} +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) +{ + int act_comp=0,num_packets=0,chained,dummy; + stbi__pic_packet packets[10]; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) { + stbi__rewind(s); + return 0; + } + + stbi__skip(s, 88); + + *x = stbi__get16be(s); + *y = stbi__get16be(s); + if (stbi__at_eof(s)) { + stbi__rewind( s); + return 0; + } + if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) { + stbi__rewind( s ); + return 0; + } + + stbi__skip(s, 8); + + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return 0; + + packet = &packets[num_packets++]; + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + act_comp |= packet->channel; + + if (stbi__at_eof(s)) { + stbi__rewind( s ); + return 0; + } + if (packet->size != 8) { + stbi__rewind( s ); + return 0; + } + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); + + return 1; +} +#endif + +// ************************************************************************************************* +// Portable Gray Map and Portable Pixel Map loader +// by Ken Miller +// +// PGM: http://netpbm.sourceforge.net/doc/pgm.html +// PPM: http://netpbm.sourceforge.net/doc/ppm.html +// +// Known limitations: +// Does not support comments in the header section +// Does not support ASCII image data (formats P2 and P3) +// Does not support 16-bit-per-channel + +#ifndef STBI_NO_PNM + +static int stbi__pnm_test(stbi__context *s) +{ + char p, t; + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind( s ); + return 0; + } + return 1; +} + +static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *out; + STBI_NOTUSED(ri); + + if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n)) + return 0; + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + + if (!stbi__mad3sizes_valid(s->img_n, s->img_x, s->img_y, 0)) + return stbi__errpuc("too large", "PNM too large"); + + out = (stbi_uc *) stbi__malloc_mad3(s->img_n, s->img_x, s->img_y, 0); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + stbi__getn(s, out, s->img_n * s->img_x * s->img_y); + + if (req_comp && req_comp != s->img_n) { + out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + return out; +} + +static int stbi__pnm_isspace(char c) +{ + return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r'; +} + +static void stbi__pnm_skip_whitespace(stbi__context *s, char *c) +{ + for (;;) { + while (!stbi__at_eof(s) && stbi__pnm_isspace(*c)) + *c = (char) stbi__get8(s); + + if (stbi__at_eof(s) || *c != '#') + break; + + while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' ) + *c = (char) stbi__get8(s); + } +} + +static int stbi__pnm_isdigit(char c) +{ + return c >= '0' && c <= '9'; +} + +static int stbi__pnm_getinteger(stbi__context *s, char *c) +{ + int value = 0; + + while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) { + value = value*10 + (*c - '0'); + *c = (char) stbi__get8(s); + } + + return value; +} + +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) +{ + int maxv, dummy; + char c, p, t; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + stbi__rewind(s); + + // Get identifier + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind(s); + return 0; + } + + *comp = (t == '6') ? 3 : 1; // '5' is 1-component .pgm; '6' is 3-component .ppm + + c = (char) stbi__get8(s); + stbi__pnm_skip_whitespace(s, &c); + + *x = stbi__pnm_getinteger(s, &c); // read width + stbi__pnm_skip_whitespace(s, &c); + + *y = stbi__pnm_getinteger(s, &c); // read height + stbi__pnm_skip_whitespace(s, &c); + + maxv = stbi__pnm_getinteger(s, &c); // read max value + + if (maxv > 255) + return stbi__err("max value > 255", "PPM image not 8-bit"); + else + return 1; +} +#endif + +static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) +{ + #ifndef STBI_NO_JPEG + if (stbi__jpeg_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNG + if (stbi__png_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_GIF + if (stbi__gif_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_BMP + if (stbi__bmp_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PIC + if (stbi__pic_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNM + if (stbi__pnm_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_info(s, x, y, comp)) return 1; + #endif + + // test tga last because it's a crappy test! + #ifndef STBI_NO_TGA + if (stbi__tga_info(s, x, y, comp)) + return 1; + #endif + return stbi__err("unknown image type", "Image not of any known type, or corrupt"); +} + +static int stbi__is_16_main(stbi__context *s) +{ + #ifndef STBI_NO_PNG + if (stbi__png_is16(s)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_is16(s)) return 1; + #endif + + return 0; +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_info_from_file(f, x, y, comp); + fclose(f); + return result; +} + +STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__info_main(&s,x,y,comp); + fseek(f,pos,SEEK_SET); + return r; +} + +STBIDEF int stbi_is_16_bit(char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_is_16_bit_from_file(f); + fclose(f); + return result; +} + +STBIDEF int stbi_is_16_bit_from_file(FILE *f) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__is_16_main(&s); + fseek(f,pos,SEEK_SET); + return r; +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__is_16_main(&s); +} + +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__is_16_main(&s); +} + +#endif // STB_IMAGE_IMPLEMENTATION + +/* + revision history: + 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs + 2.19 (2018-02-11) fix warning + 2.18 (2018-01-30) fix warnings + 2.17 (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug + 1-bit BMP + *_is_16_bit api + avoid warnings + 2.16 (2017-07-23) all functions have 16-bit variants; + STBI_NO_STDIO works again; + compilation fixes; + fix rounding in unpremultiply; + optimize vertical flip; + disable raw_len validation; + documentation fixes + 2.15 (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode; + warning fixes; disable run-time SSE detection on gcc; + uniform handling of optional "return" values; + thread-safe initialization of zlib tables + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs + 2.13 (2016-11-29) add 16-bit API, only supported for PNG right now + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes + 2.11 (2016-04-02) allocate large structures on the stack + remove white matting for transparent PSD + fix reported channel count for PNG & BMP + re-enable SSE2 in non-gcc 64-bit + support RGB-formatted JPEG + read 16-bit PNGs (only as 8-bit) + 2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED + 2.09 (2016-01-16) allow comments in PNM files + 16-bit-per-pixel TGA (not bit-per-component) + info() for TGA could break due to .hdr handling + info() for BMP to shares code instead of sloppy parse + can use STBI_REALLOC_SIZED if allocator doesn't support realloc + code cleanup + 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA + 2.07 (2015-09-13) fix compiler warnings + partial animated GIF support + limited 16-bpc PSD support + #ifdef unused functions + bug with < 92 byte PIC,PNM,HDR,TGA + 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value + 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning + 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit + 2.03 (2015-04-12) extra corruption checking (mmozeiko) + stbi_set_flip_vertically_on_load (nguillemot) + fix NEON support; fix mingw support + 2.02 (2015-01-19) fix incorrect assert, fix warning + 2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2 + 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG + 2.00 (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg) + progressive JPEG (stb) + PGM/PPM support (Ken Miller) + STBI_MALLOC,STBI_REALLOC,STBI_FREE + GIF bugfix -- seemingly never worked + STBI_NO_*, STBI_ONLY_* + 1.48 (2014-12-14) fix incorrectly-named assert() + 1.47 (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb) + optimize PNG (ryg) + fix bug in interlaced PNG with user-specified channel count (stb) + 1.46 (2014-08-26) + fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG + 1.45 (2014-08-16) + fix MSVC-ARM internal compiler error by wrapping malloc + 1.44 (2014-08-07) + various warning fixes from Ronny Chevalier + 1.43 (2014-07-15) + fix MSVC-only compiler problem in code changed in 1.42 + 1.42 (2014-07-09) + don't define _CRT_SECURE_NO_WARNINGS (affects user code) + fixes to stbi__cleanup_jpeg path + added STBI_ASSERT to avoid requiring assert.h + 1.41 (2014-06-25) + fix search&replace from 1.36 that messed up comments/error messages + 1.40 (2014-06-22) + fix gcc struct-initialization warning + 1.39 (2014-06-15) + fix to TGA optimization when req_comp != number of components in TGA; + fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite) + add support for BMP version 5 (more ignored fields) + 1.38 (2014-06-06) + suppress MSVC warnings on integer casts truncating values + fix accidental rename of 'skip' field of I/O + 1.37 (2014-06-04) + remove duplicate typedef + 1.36 (2014-06-03) + convert to header file single-file library + if de-iphone isn't set, load iphone images color-swapped instead of returning NULL + 1.35 (2014-05-27) + various warnings + fix broken STBI_SIMD path + fix bug where stbi_load_from_file no longer left file pointer in correct place + fix broken non-easy path for 32-bit BMP (possibly never used) + TGA optimization by Arseny Kapoulkine + 1.34 (unknown) + use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case + 1.33 (2011-07-14) + make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements + 1.32 (2011-07-13) + support for "info" function for all supported filetypes (SpartanJ) + 1.31 (2011-06-20) + a few more leak fixes, bug in PNG handling (SpartanJ) + 1.30 (2011-06-11) + added ability to load files via callbacks to accomidate custom input streams (Ben Wenger) + removed deprecated format-specific test/load functions + removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway + error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha) + fix inefficiency in decoding 32-bit BMP (David Woo) + 1.29 (2010-08-16) + various warning fixes from Aurelien Pocheville + 1.28 (2010-08-01) + fix bug in GIF palette transparency (SpartanJ) + 1.27 (2010-08-01) + cast-to-stbi_uc to fix warnings + 1.26 (2010-07-24) + fix bug in file buffering for PNG reported by SpartanJ + 1.25 (2010-07-17) + refix trans_data warning (Won Chun) + 1.24 (2010-07-12) + perf improvements reading from files on platforms with lock-heavy fgetc() + minor perf improvements for jpeg + deprecated type-specific functions so we'll get feedback if they're needed + attempt to fix trans_data warning (Won Chun) + 1.23 fixed bug in iPhone support + 1.22 (2010-07-10) + removed image *writing* support + stbi_info support from Jetro Lauha + GIF support from Jean-Marc Lienher + iPhone PNG-extensions from James Brown + warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva) + 1.21 fix use of 'stbi_uc' in header (reported by jon blow) + 1.20 added support for Softimage PIC, by Tom Seddon + 1.19 bug in interlaced PNG corruption check (found by ryg) + 1.18 (2008-08-02) + fix a threading bug (local mutable static) + 1.17 support interlaced PNG + 1.16 major bugfix - stbi__convert_format converted one too many pixels + 1.15 initialize some fields for thread safety + 1.14 fix threadsafe conversion bug + header-file-only version (#define STBI_HEADER_FILE_ONLY before including) + 1.13 threadsafe + 1.12 const qualifiers in the API + 1.11 Support installable IDCT, colorspace conversion routines + 1.10 Fixes for 64-bit (don't use "unsigned long") + optimized upsampling by Fabian "ryg" Giesen + 1.09 Fix format-conversion for PSD code (bad global variables!) + 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz + 1.07 attempt to fix C++ warning/errors again + 1.06 attempt to fix C++ warning/errors again + 1.05 fix TGA loading to return correct *comp and use good luminance calc + 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free + 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR + 1.02 support for (subset of) HDR files, float interface for preferred access to them + 1.01 fix bug: possible bug in handling right-side up bmps... not sure + fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all + 1.00 interface to zlib that skips zlib header + 0.99 correct handling of alpha in palette + 0.98 TGA loader by lonesock; dynamically add loaders (untested) + 0.97 jpeg errors on too large a file; also catch another malloc failure + 0.96 fix detection of invalid v value - particleman@mollyrocket forum + 0.95 during header scan, seek to markers in case of padding + 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same + 0.93 handle jpegtran output; verbose errors + 0.92 read 4,8,16,24,32-bit BMP files of several formats + 0.91 output 24-bit Windows 3.0 BMP files + 0.90 fix a few more warnings; bump version number to approach 1.0 + 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd + 0.60 fix compiling as c++ + 0.59 fix warnings: merge Dave Moore's -Wall fixes + 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian + 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available + 0.56 fix bug: zlib uncompressed mode len vs. nlen + 0.55 fix bug: restart_interval not initialized to 0 + 0.54 allow NULL for 'int *comp' + 0.53 fix bug in png 3->4; speedup png decoding + 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments + 0.51 obey req_comp requests, 1-component jpegs return as 1-component, + on 'test' only check type, not whether we support this variant + 0.50 (2006-11-19) + first released version +*/ + + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/src/include/switch_core_video.h b/src/include/switch_core_video.h index 21e6b77414..23d1356b78 100644 --- a/src/include/switch_core_video.h +++ b/src/include/switch_core_video.h @@ -395,6 +395,9 @@ SWITCH_DECLARE(switch_status_t) switch_img_write_png(switch_image_t *img, char * SWITCH_DECLARE(switch_status_t) switch_png_open(switch_png_t **pngP, const char *file_name); SWITCH_DECLARE(void) switch_png_free(switch_png_t **pngP); SWITCH_DECLARE(switch_status_t) switch_img_data_url_png(switch_image_t *img, char **urlP); + +/*!\brief Read an image file to switch_image_t */ +SWITCH_DECLARE(switch_image_t *) switch_img_read_from_file(const char *file_name, switch_img_fmt_t img_fmt); /*!\brief put a small img over a big IMG at position x,y, with alpha transparency * diff --git a/src/switch_core_video.c b/src/switch_core_video.c index 540edf0ae9..dcdbe67332 100644 --- a/src/switch_core_video.c +++ b/src/switch_core_video.c @@ -48,6 +48,9 @@ #include #endif +#define STB_IMAGE_IMPLEMENTATION +#include "../libs/stb/stb_image.h" + #ifdef SWITCH_HAVE_YUV static inline void switch_img_get_yuv_pixel(switch_image_t *img, switch_yuv_color_t *yuv, int x, int y); #endif @@ -3100,6 +3103,51 @@ SWITCH_DECLARE(switch_status_t) switch_img_data_url_png(switch_image_t *img, cha #endif +SWITCH_DECLARE(switch_image_t *) switch_img_read_from_file(const char* file_name, switch_img_fmt_t img_fmt) +{ + int width = 0, height = 0, channels = 8; + int comp = STBI_rgb; + unsigned char *data = NULL; + + if (img_fmt == SWITCH_IMG_FMT_I420) { + comp = STBI_rgb; + } else if (img_fmt == SWITCH_IMG_FMT_ARGB) { + comp = STBI_rgb_alpha; + } else { + return NULL; + } + + data = stbi_load(file_name, &width, &height, &channels, comp); + // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%dx%d channels=%d\n", width, height, channels); + + if (data && width > 0 && height > 0) { + switch_image_t *img = switch_img_alloc(NULL, img_fmt, width, height, 1); + switch_assert(img); + + if (img_fmt == SWITCH_IMG_FMT_I420) { + RAWToI420(data, width * 3, + img->planes[SWITCH_PLANE_Y], img->stride[SWITCH_PLANE_Y], + img->planes[SWITCH_PLANE_U], img->stride[SWITCH_PLANE_U], + img->planes[SWITCH_PLANE_V], img->stride[SWITCH_PLANE_V], + width, height); + } else if (img_fmt == SWITCH_IMG_FMT_ARGB) { +#if SWITCH_BYTE_ORDER == __BIG_ENDIAN + RGBAToARGB(data, width * 4, img->planes[SWITCH_PLANE_PACKED], img->stride[SWITCH_PLANE_PACKED], width, height); +#else + ABGRToARGB(data, width * 4, img->planes[SWITCH_PLANE_PACKED], img->stride[SWITCH_PLANE_PACKED], width, height); +#endif + } + + stbi_image_free(data); + + return img; + } else if (data) { + stbi_image_free(data); + } + + return NULL; +} + SWITCH_DECLARE(switch_status_t) switch_img_letterbox(switch_image_t *img, switch_image_t **imgP, int width, int height, const char *color) { int img_w = 0, img_h = 0; diff --git a/tests/unit/switch_core_video.c b/tests/unit/switch_core_video.c index 7d42eaae1f..cafa075337 100644 --- a/tests/unit/switch_core_video.c +++ b/tests/unit/switch_core_video.c @@ -199,6 +199,27 @@ FST_CORE_BEGIN("./conf") switch_img_free(&timg_small); } FST_TEST_END() + + FST_TEST_BEGIN(read_from_file) + { + switch_image_t *img; + + img = switch_img_read_from_file("../../images/cluecon.png", SWITCH_IMG_FMT_I420); + fst_requires(img); + switch_img_write_png(img, "cluecon-rgb.png"); + switch_img_free(&img); + + img = switch_img_read_from_file("../../images/cluecon.png", SWITCH_IMG_FMT_ARGB); + fst_requires(img); + switch_img_write_png(img, "cluecon-argb.png"); + switch_img_free(&img); + + img = switch_img_read_from_file("../../images/cluecon.jpg", SWITCH_IMG_FMT_I420); + fst_requires(img); + switch_img_write_png(img, "cluecon-jpg.png"); + switch_img_free(&img); + } + FST_TEST_END() } FST_SUITE_END() } -- 2.47.2