myList
should be my_list
by PEP8.
Add PEP484 type hints.
from bisect import bisect_left
should be moved to the top of the file.
I think it's clearer, rather than image.getdata()
, to just use the np.array()
call on the image file. That way you can min
and max
on it without converting it to a list.
I don't see a lot of value in defining a local function chunks
that you only call once and has only one line (the import not counting; that should also be moved to the top).
avals
should not use a range
, and should just zip
over the two sub-series.
You should extract from your main code a conversion function that neither prints nor saves to a file.
Suggested
import PIL.Image
from bisect import bisect_left
import numpy as np
CHARSET = (
"@$B%8&WM#*oahkbdpqwm"
"ZO0QLCJUYXzcvunxrjft"
"/\|()1{}[]?-_+~<>i!l"
"I;:,\"^`'. "
)
def closest(my_list: list[int], my_number: int) -> int:
pos = bisect_left(my_list, my_number)
if pos == 0:
return my_list[0]
if pos == len(my_list):
return my_list[-1]
before = my_list[pos - 1]
after = my_list[pos]
if after - my_number < my_number - before:
return after
else:
return before
def resize(image: PIL.Image.Image, new_width: int = 300) -> PIL.Image.Image:
width, height = image.size
new_height = int((new_width*height/width)/2.5)
return image.resize((round(new_width), round(new_height)))
def to_greyscale(image: PIL.Image.Image) -> PIL.Image.Image:
return image.convert("L")
def pixel_to_ascii(image: PIL.Image.Image, light_mode: bool = True) -> str:
pixels = np.array(image.getdata())
direction = 1 if light_mode else -1
charset = CHARSET[::direction]
minp = pixels.min()
maxp = pixels.max()
lst = np.arange(minp, maxp+1)
lchunks = np.array_split(lst, len(charset))
vals = [chunk[0] for chunk in lchunks]
avals = dict(zip(vals, charset))
ascii_str = ''.join(
avals[closest(vals, pixel)]
for pixel in pixels
)
return ascii_str
def convert(path: str) -> str:
image = PIL.Image.open(path)
image = resize(image)
greyscale_image = to_greyscale(image)
ascii_str = pixel_to_ascii(greyscale_image)
img_width = greyscale_image.width
ascii_str_len = len(ascii_str)
ascii_img = ""
for i in range(0, ascii_str_len, img_width):
ascii_img += ascii_str[i:i+img_width] + "\n"
return ascii_img
def main() -> None:
ascii_img = convert('archived/image2l.png')
name = input("enter the image name here: ")
with open("{}.txt".format(name), "w") as f:
f.write(ascii_img)
print(ascii_img)
if __name__ == '__main__':
main()
Output
IxL00QOqW%Q)I... . . .``',~tCd****#MW&%%%%&*d0c/?~<i!I;;:,""^`'``'....'...'''````^`'... ....'' .'`'.
ln0ZOQ0wMBO\!'`` . ..`:~(vma**o*#W8%%%BB%MdUr([-+>!I;;I;:,"""^'''```````^^^^"^`'`'''''.'' .'''.
;xQZOCQm#8Zti'`' .'^^;+\Uq*M##*#MW8%BBB8*pUf([_<!I::,,,,,^```^"^^^^`^^^^^``''''''..'` .....
IrQqwQ0wMBwj>',". `"^^:~|cZk##*ooM&8BBBB8#pUt}?+<il;:;I;:"^"","^^"^^^^````'``''. '` .''.
. ,\UqpO0m#Bqri."". ....'`^``,<(vmoWWM##W8%BB$$8bCr([_<illI;:"^^^^^^","^^^`````````. '''... .'''.
")XdkmZq#8dc+'""'. .'^^,<(Xqa####M&8%BB$%MdUj1-<>>!I,^```^^^"^^`''.''.'''. `^`'.. ....''.
.. . ^{cpkmmqo#mn<',,. .. .^,,,;~(u0kM&WMMWW8%BB8a0u|}-<!lI;:,,"^`^^````. .'..`^`' .''.....'. .. . ...
.... ...... ^1cqdOOwkaOx<`,". . .. .`"I!Il</Qa%8M*o#M&%B%8Ma0v\[+<ilI;:"",,"^""`'..'''..`^. .... .``'.... .... ..
.. '_xmpQ0w*&qu+^;: ..''. `,;li]fO&%&8888WW8%%BB%8owv([_~>!;"""``^^^``^^`'`^'.....'. .''.. ....''..`^,;l>+{|frxnnuvr\{_l"""^`.
11{{1)))1}]?---__-___-_1uZ**pqbW$#mzft\(1}[[[})|/rcCOJj?"`' `;-fLaaaWB$$B%%%%8W&%BB*qUx\[++?}1|/tfjxuvvvvxjf\}_<iI:"```,l<-]]-<;^"I+1fvYJLQ0QLQQCUXzzzzUQO0LX\+:`'. ..
bbbbdddddpppppppdbkaahhaoo**oaa#&W#abbdddddbkkkbbkk#$#C|;,,' I|L*ada#MWB$$$$%8&&W&%B8MkZCOpqwZ0CYczYcxvYUC0wkbmX|{1\xcJOZQLQLJLOmwqqZ0CXuxxf/|)1{}[]][][\vmakOx(1{{]+!:^'''.. .
bbbbdppppdbbbdbkbppqpddpqwmmwZOmqqwwwqqqqwqqwwZOOZmdobL\:^^. .. . I\O8MbbkbkoM%$$$$B%&W&8$$$&hq0Yurt|))))1{{{11)|xYmbhbwwm0Jznt//|(fzZbkqzf/|){}}}{{[[[[[[???)rUZqq0LCL00Q00CXr(]>:^..''.........
00QLLQ000OOZO0000QQLLLQQQQ00OOOOO00OOOOZZOZmZO00OZwdhbOf!::`. !jm&Waaakka#B@@$%88B$$8#bOYnt|(()1{}}}{}}{11{{|uQbkqCnf\||()}[{{1}}(/jf)}{}}[[[[[[]]???]]]][[{1111{{{1)\/jcC0ZZJj}!:,"^```'.....''......
mZZOOZZmmmwwwmmwqqqpddbbkkkkhhahkbbkhbddppqwZZZmmwmqbdZfI,:`. ijw%Wao#&8&Wokq0COd##qJvj/()}]??]]]]]]]][[]--1fzYcr|1}[][}{{[]]][[][[[]--][[[]]]]][[[]???]]]][}}[]]???--][]?])uCwC/_;^```^`..``^`'''... ...
#######MMMMM####MWWWMM#*********oaao**#W%B8#bmqdpqmmppZt,`"' !fm%8M%BWk0XnjfnYwkOzt()))11}[}}}[[[[[[}{}]???]]]??]][]?][[]???][]]]]]]??]]]]]???]]]]??------???????--????]]?-+)zQ0u}i,^^^^.'^"^``..`````''''.... . . .. .
pppqwwwwwwwmmmwwwqqwmmZZZZZZOZZmmZZmmmqb*%B8awqpqmZmdp0/,^,` !fw$@@8oLuf\\||cmmLx|()1{{}]]]}}[]]][]]]]]]]??????]]]]????[}]]?]]??]]]]]][[]???]]]?-------???????????-?]]]?-]?__?tC0Ct~I:"^`````''..'''''''............................ .....
zzXXzzzXXXzccczXYUJJCCJUUUJJCCLLLLQ0OOZqhW8&hwqqwOQ0mqZjI,:`. . ixp$@&pUx/|){{(tj/(1{11}}}[?][[]]]??]]]]][[11[?????????-??]]]?-__--???]?]]??---?????----?]]]]?????]]]??????---]?~?\YqOc1lllI:"`'...''```````'''````'..'''''''.''''..'''..................... ... ....
czzzzccczzzzzXXXXXYUJJCCCJJJCCLLQ0000Zwpa&8&apqqZ0LLOmZf:":^. .,>}jXZ*BWpXff/)}[[}}[]???-?[]?][[]???][[]]?????]]?---------?]]?-??--_--??]]]??-------??]]]???]]]]]???]]]]?]]]]--]}}}}[[\cwokwOQCXx\}+!I::,,,,,""^^```^^''''''''''''..''''''''''``'''''''.'...........
YYXXXzvccXXXzXXXYUUYYUJCCJJJCCLLLQ00OZwdo&%8aqqqmOQQQZZj;,;"'. .. `l?jXUUXux0#kLj1))1{}[[]]???--?[}]]]]]]]??]]]?--????????????????--?????--??????]]]]]???---???]]]?--????--?]]]????????][[]]]][)/jxrxzJ0wqOYj1~!lI,"^^"^`^^^````'''`''`^'..'```''````""^`^``''''....''.'''.
UYXzzzzczXYYYXXzXUUYYUUUYUCLLLLLLLQ0OZmpa&%8aqqqwOCJLZwx!;I"'. ."-fJmLzj|11|cZJr([}{}[]]]]??]???]]]?]]]]]]???]]?--??????????????-------????]]]??-????-----------???----???--?]????]]]]??]]??----?]]]?_-}(fcLZZJn1~l;:::"^""^^""^^^^^^`^^`'```^"^```'`^^^``'''...........''....... .
JJYYXXYYUUJJUUYYYUYXYYUUUUJJJCLLLLLQ0Omqa&%8hmmmZ0CJQwpxI,:"'. `?nLZUr)[{{[]]}1}]][[[]?_-]?--?--]]??????]]?--?]??---????????????-------??---????---???-----------????---?]?????????][[]]]]]]?--?[}]??][[[[[?]|nJOOLct?>!I:;I;:,"^^^^^^^^^`''''`^^'````^""^`'''..... ....''......... ......
JJJUYYYUJJUUUUUYYXXYYYUUJJJJJCCLLLCLQ0Zwh&%&hmZmZ0CJLZmj;,;"'. I|YwLx([}}]][[?][[[[[??][[]]??????[]??]]?????--???-__---??????--------------__----??]]]????????????????--?]]]???]]]?-?]?-___-----?][]???][}[??]??](nCqmX\~!!ll:,::,","^""""^````^"^```''^^^``'''..'.. ....''''''...........
JJJJUJJJUYXYYYYYXXXYYUYYUJLLLCCLQLCLLQOwa8%WhwwmZOQLQZmj:^,^'. ^<jqpJx()1{}??[[?][[[[[??][[]--?--??]?]??-_-???---??-__----???-------------??-__-------?????-------????--_--?----???-----__--??-___?]]?----??][}{{}?_+{rJwz]>!lI;:;:,,:,"","^^```^""^^^^``^^''''`''''.....'.''''''''''...........
CCCJJCLCUYYUUUJJJJUYUUYYYJLLCCCLQLCLLQOwh8%WappqZ0QQOwqr;`^'. ';}nm*Mmx/|()){[]][}[?????-----_-?]?-????]]?-------_----__-------------_______---------___-???-______--???-_________-----???------_____------??-?]\vC0Xx/|/Ya0(+i;:::;:,,""^"""^``'`^^^^^^`'`^^``^^`''``'''''''''``````'''''''''````
LLCCUJJJUJJJCCCCCLCJJCUYUUJJJCLQQLLQ0Omqa88MhpqmZ0QLQZZf,'^. .. 'l|vzUOqpU\)(1[[[]???]]???????]??---???-_--------_____---------___-------___+__------___+____--??--_-???-?????--__+____--?-___-----------_+-?-------+-/XmpCcnQWm)<lII;;II;:,"^"""""^```""""^``^"""""^`'`""^```````^"""""^^^""^^`^^^^^^
CLLLCCCCCCCCCCCCCJJJCCCJUUCCCLQ00QQQ0Ompo8&obqwmZ0LL0ZOt"'`. .+fUCx/\/t([}{[]]??????????????????-???????---_-??------------?-_++___--------___------_____----?????]]]??-?????--------_________---------___---?--?[]-+]x0baddbX}+<!IllI;:,""",,,,,,"",,,"^``^,,,,""""","^```^,,"""""""^^^",,,"^"",:::
QQQQLLCCCCLLLLCCCJCLLLLLLLQLCLQ000Q0OZwpo%8*bqwmOQL0wmL('."`. `ijJvt({[?--?[[?-]]??????-?]]??-?????????????-_-?]?-----?????????-___--------_____-------__---?????????]]]??]?----------______---------________--?--?[[[_+?/Qa&bu1+~_<!I;;;:,,,,,::::::::;;;:,,,,:,,:;I;;;,"""^";II;,"^"""^^":;I;:::::::
QQQQQQLLLLLLLLCJJJCLLCCLQQQLCLQQQ00Zmmqd*B%*kpwmmZLOdpC1 .,' `-rYUt}{1}[}]??]]??]]]????-??]]?-?????????????----??-------????????]]]]]]????-____---???-------?]???????-??]]]?---???????----___---??????----??-__??-?]]]]]+-|XhhCt+<+ill!I;;;:::::;;;;;:::;;::::::,,:;;;IlI;;:::III;;;;II;;;;III;;;I;;;;
00QQQLLLLCCCLLCJUUJCCCCCQQQLLQ000OOmmwqb#$8adwmZZ0COapX[ ',' :[vOUj)}))}[]]]]]-_-?????]??????????--???--__????-__-----------------????]]]]?????????]???------???--???---??]?-____---???????-__--?]]]]]]?????--??????-???-??_(YpoQ1+<!l!!II;;;;;;;;;;IIII;::,",:::,,:I;:;lIIIl!!III;:;l!!lllII;,,":;:,,,
OO000QLLQLLLLLLLCJJCLLLQQQLQ00OOOOZZmmqkM$&hdpwZZ0CmMpr~.'"' >jUCj[}11{]?]]]]]?-----??]]?????????---??--_--???-_+_---____-------__-----------__?]?]????--------__-?]]]]?]]??--------????]]]]????]]]]]]?-------------?????]]])rZB8qz\[+~<!lllII;::::;;;;:::::;;;;;:;;;::;Il!!!lI::;;:::IIII:,,,"",,:;;;;
OOZOO0Q00O0QLLLLCCCLLLQQQQQ0OO000OZZmZwkM@%obpwmZOCwMw/i..'. `{YUu|]{1[?-??][]]??????]]]]]]]]]?---_-????????--__++_------_____----_----??---__+__-_____--???--____-??]]]]]???------??--?????][]]???????--__----???????]]]]?--](UW$8bJt[_~il!llI;;;;;;:,:::;;;;I;::;I;,:IIII;;;::::;;II;II;:,,,,,,,:;IIII
ZO0OOOO00QLLQ00QLQQQLLLLQ000Q00OOOZmmmqbM$%obqwZ0QLqWq\i' .:/ZJt)}11]----?]?-__-??]??]]??????-----?????????----____-???--____-?-----??????????---------?????-_+_____--------__---??????????]???---????----?????]]]]][[[]]??}\U*&*aqj+~<!llIIIII;;::::I!!llIIIIIIIII:,::;;;;;;;;;IllI;;I;;::::::::;Illl
ZZOOOOOOO0QLQ000QQQ0QQLLQ000000OZZZmwwqd*$%*kqmO0QCwWpf+^ `(0Ln|[[[?-___---__--???---------______-----??????]]]?-----???----------????????]]]----------__________________--___-------?--????-----????-------------??????]?1jCbakobx~<<>i!llIII;;;IIl!!!llIll!!!lll;;Ill!!!llIII;;;;:;;;::::::,,,::;;;
ZZZZO0QOZZOQLQQ0QLQ00O000OOOO0OZmZZmwqpdo%8#kqmZZ0UZMpr+' -zCYf}}}]-___----????????---------????????----------??------?]]?--_----______---??-_--------??????---_______-------______--?????--------??------------??????]?-?1\fYmdmti><>i!!lll!!llllll;IIIIll!!lllllIIIll!!llI;;;;;;;;;::,,:::,,,,:;;;
ZZZZZO00000QQ000QLQOZZOOOOOO00OZmmmmwqpda88MkwmmmOJmWdr~ . . itYLx1)(}]??]][]?---?-??????-----???]]]]??--________-??------?????-????--______---___-----____------___________________---------_____--????---------????????]]]-~_{zbqY)!!!IIIllI;;;;;;;;;;IlI;;;;;,,:;!l;;;;II;;::;;;IIllI;:,:;;;;;;II;;;
ZZZZmZZZOO00000QQQQ0OOOOZZZZZOOZZmmwqqpdo&8WkmmmmOCw&bx_'.`. I)Ywc))1[????][[[]????----______----?????-----_____--?------------????-----___--?----????---____-____________________--??--____--_-__-----_--------??--??---???-+1vqWO\->iii!lI;::;;;;II;IllII;;;:,"",:;;IIIIlIIII;IIllllIII;::;;;;IIlIIII
OOOOOZmZZ0QQ00000O00OOOOOOOOOOOZZZmwqqpb*8%&hwmmZ0CZMdn?^.'. "_vwz(1{[?---?][{[]??_______----?????????]]]??-____--___--------___--_++++++++__--------_____________--__-??--?--_____----__++-[?------____-?--__-???-----__?}1)(zhowx_<<i!!l;::;;;;;;;IIIII;;;Il!!lIII::I;:l>ii>>>i!!!lII;IlI;IIIIIII;:::
ZZmmZZZO00QQQLQ0OO0Q0OOOOZZZZZOZmwwqqqqdo8%8aqwwZ0Lmoqu?. ... ;1Xwc1[]??--???][]?----????????????????]]]??-__+______-----------______+++_---____--_+++++__-______+______--__----___++______+-]?_______----------???-------[\zOb*#Of[<<~illlIIl!ii!lllllIll!lllliiiiii!i>!I!>>i!!l!ii>i!!lIII;:;I;:;IIIII
ZZmmmZOOOOOZO000OZO0OZZOOZZZZZZZZwqppppdaW%B*qwwmOCZopu?. . `1CQYf{{{[?---???]]?-_----------------___--___++++__---??-______-?---?-___--?????-________--------_______________---__+++__--___---------__---??---???---??---(UphZr{~<~>lI;;;;Il!llIIIl!!i>>>i!!>~+~<>>><~<<>><~<>!iii!ii>>>ii!I;II;Il!!!!
ZZZZOOZZZOOOZZO0OZO0OZZZZmmmmmmmmwqpddddhM%$*qqqmOJOapc]..^' ^+udC\)111[??--?]]?]]?-??????----------____--_____-?????---______--???--__---__-???-+++_----_______--__-_______+__----_____---____-?-__-]1||1[-?]?-???----????-(JZJtl,!!!!lII;;IIl!!!!!iii!i<<>i!!i<<<<<<<<~+_++~<>ii!!!ii>>>>>>i!!!!!ii!lll
qqwmZZZZZZOZOOOOZZZOZZZZZmZmmmmmwqppppdbaM%B*qwwwZLZapz[..^' >nL0n[}1}?]]]]?][]?????]]]]]?]????------__--???------?-___--------___---???--___--??__----------__-------______+__??-__-????-------?-_---\CCu/}]]?????----??-?|zb*qJrtt////tft//ttffrncYCLQ0OO0QCCCLQZmqqmZZmmZOO0CJJYzvxf\(()1{}{{{{}[[[]]]
qqwwmmmmZOOOZZZOOOOOOZZmmmmmmmmwwqpqqqpbaM%B*qqqmZ0mkdC(^`"' -LOXj{[[?-]]?--?]?????]]]]]?????---?-??-_+__----____---__------??--_---]]]?-_+_--])tnx1?-_+_-____++------_-?---???][{1)}]?????????--____+|L0zf1[[?-?]]]?]]?]1j0hohpph*W&&#ahhbdpddbkkbkkkkbbkkkao*#MM*oabpwwwqqqkoaaoM%%&*hddkahaoooooaaaaaa
mmwwwmZZZZZZmmmmZOO0OZmmmmmmmmmmwqpppqpdh#%$#pppwmOmkkZfI"^' ]O0x|{}[-_??----?----?]]]]??????----???-_++______+___--______________++_---_++__+_)vaaj??--][{1}]--_--_-)jcXf1[???[tzUXf1{}]?]]]?_--??+-|vmQr([][???]]]]-_[/YpMMqCXzJZhMMdO00LCCCCLLLCJUUUYYYYXYJCL0O0QLCCCJCCCCLCJYYJObM%@@$%Makbbbbbbbdppp
mwqqqwZZZmmwmZZmZZOOOOZmmwwmmmwwwqpqqwqdh#%@#ppqwm0wahZj!:,' .)pwx|}}[?-??--??----?]]]????????????------?????---------______-----__------??-?]++|X*oj-_?1xJCXf)1}--}\nUQJu|[}]_[/UdZz/}}}[[][[]?---}/vQ0Ux)}}]--?---]1tzOk#Mkw0Q0QJOkoaOYJCCJUUUUJJJJCCCLLLCCCCLQQQ0QLLLLLLLQ0QQCJJUYJ0kWMhwQLLLCJCQOOQLLL
mwwwwmZZZmwwwmZZZmmZOOOZmwwwmmmwwqpqqqpbh#%@#qwmmOLZabJ(,^"' .(bm/1{[?--??????----?]]]???????????----_+_____+++__------_____-----__-???----___]|YqbOt}1jJwpUt1]?]{tU0OYf)]?-_-[j0pwu[?]]???]?-__-1rUOOYx({}[]-__?1\rUp*8&opO0QQLCUYZohmYuXJJJUUUUJCCLLLQQQLLLLLQ0QQ00QLLLLLLQ000LCCCCJCp#aqQJQQLQQQQQQ0000
wwmmZZZZZmmmmZZZOOZZZZmmmmmmmmwwqppqqqpbh#%@MdwZZOQmodX1:,:` .(kwt)1]-__??--??----?]]]????????????-----??]???--_____---__++_----______+___+~+[x0bdz/1/YmkOn|})\fvOqmYt){}[?_+1u0dLf}+?[-_-?}{)fcQqdwUnt|()(\juXUQqh#MMadwOQQ00QLJUJw#amJzJCUUYYYYJCLLLCCLLQLLLCLLLLLQQQQLCJCLQOO0QQLCCQd*hqO0OOQQ0QLLLQQQQ
ZZZZOOOOZZZZZZZO00OOZmmmZZZZZZmwqppqqpdbh*8@WkqZZZOqapY(I,,' ^/opf1}1)[???----?---?]]]]???????----???????----_+++++_--__+++__---_++_-_+~~_{fUd*#bZLQp*&#dLzYLOmdqLv/{--?-]1tYmahOzjnzvnnuzUCJULZb*M#kpppqqqpdhooabpmOQQ000QQQQQQLLLq*odOCLQLLLCJJJCLLLCCLLLLCCCLLQQLCCLQQLCCLQQQLLLLCL0dapOLLOOQLQLLCCCLLL
ZmmmZO0OOZmmZOOOOOZZmmmmmmZOOZmwqqqqqqpbh*%@&adwqwmqapY(;``. .}mwc\[}{}]]]?--???????]][]]??----?]?---__++++______+__---_--??----_-----[|xJ0O0CYzccunucYYXU0bMMawJr/fjxvzUL0Zwm0CUUUJJYcvnrt\)[+>?/UqbbwZZOQQQLLLLCCCLQQQQQLLLLLLLCCmhbw0CCCCCCCCCJCLLLCCLLCCCLLLLLCCCLLLLLLLLLLLLQQQQQOdap0CJLLLLQQQ0QLCCC
wmmZZOOZZmmmZZZZO0OZmwqwmZ000OZwwwwqqqpdh*8@&hqmqqZqadC|;""`. <uCUj}}1{}[]]]]]????]]]]][]??---????-_______________---____-??-__+~+-[\cQZ0Xj1+!lllI;::;I;;I!+}|fnzUJUYzcnj\1-<!llllllllIIIIIIIII;:;~(z0ZOCJCJUCQLCCCCCLLLLLCCCCCCLCUQpdpOCJCCCCCCCJJCCCJJLLLCCCLLLQQLLLLLQQQQ0000OO0QQQOk#dQCCLQQQLLLQQLLLL
wwwwmZZZZmmmmZZZZZZmmmwwmmZOOZZwqwwqqppdko8@8odqppmqabQ/l,:^``. 'l1r/[[[]?-??]]???????---???-__-????]?--__----__------??----?]----[\nYJXr)-<ii!lllI;IIllII;;IIIIIl!>>i!lllII;;;;;;:::;;;;;;;;;;;;;;:,:<)zOpwLJUJLLLQQLCUJLLLLLCUUJCJYLqhhZJJCCCCCCJJJCCCJJCCCLLLLLLQQ00QLCQ00QQQQ000QQQQZaWdQLLQ00QQQQQLLQQQ
wwwwwwwmZZZmmwwmZZZmmwwwwmmZOZmwqwwqqqpdbaWB8#kppqmpabL/l::`.. ^</Xr[?]???????]]]]??------__---??]]????_--------????---????]]_+?tU0Lu(_illllI;:::;;::;;;Il!!lIIIIIII;;;;;;;IIIIIIIIIII;;;;;;;;;::;;II:;</QqmQYXXJLLLLCJLQQLCJCLCCCJYQphhOUJCCCLLLLLLLLCJJJCCLLQQQ000QQQQQ0O0QQLCCLQ0000ZhMqCJCLQ00QQQLLQ0QQ
mmwwwwwmZZZZmwwwmZZOmwwwZZZZZZmmwqqqqqqdbhMB8#bwqqZwkdQ\;,;^' ,]fct_?}}}[]???]]]??----?]?-???---??---------------??----?]?+_[tUQJj-il!!I;IlI;:,,::::;;;;:;;II;;;;;;II;;:::;;III;::;;IllllII;;;IlIIlll;,l[uwwQYcYCCCCCLLLLCUUJCCJJUYQphk0YJCCCLLCLLLQLLCCCCLLQ0000000Q000000000QQQ00QQLQd*qCCCQ000QQQQQQQQQ
qwmmmmmmmmmmmmmmmZZOZmmmZZmZZZmmwqpqqwqdbb*%%WbZwwZmbpL(``;,`' ,?fXr}{))1}[[[[]]?????????]]??????--------___--------?--?]__-|YQCr?i!!i!llI;;;;;;;;;::::;;:::::,,;;:;III;:::::;;;::::;;;IIIII;;;IllIlllII:,+fCqOJUUJJJJJJUUUUUYYUUYYYLwkh0zJLCCLCJJJCCCCLLLLLCLLLLLLLLQQLLLLQQ0000QLCCCLOb*dOLL0O00QQQQQLLLL
mwwmZZZwwwmmmwwmmZZZZZmmZZO0OOZmwqqwwwqdbk*&%&kmqqOZdqJ(^'"`. "_jJu)11[]??]]]??---??-__--??----__-?]]]----____________-?_}rY0z}>l!i!IIII;;;;;;::;;;;:::::::::::;;::;III;;:;;;:,::::::;;;;;;;;;IIIIIlII;:::I)XZqLXYUUUUUUUYYYUUYYUYXU0pbQzUCCCCCCJUUUJCCCLLCJJJCCLLLLLCLLQQQQQQQLQLCCCLObodOQQ00QLJCLLLLCCC
wwwmZmwwqwwwwmmmZZZmZZmZZO00OZmmwqqwwqppdkoM%8bOwqZwkpC(^^;` .:(Jc|{]+~_-?----__----__------------???--___---__++++_-++?/Q0j[il!!lI;;;;;;;;;:::;;;;;;:::::::;;;;::;;;;;;;;;::,,::::::::::::::::::::::;Il;:I-vqqZJXXXUJUUYYYXXzzzXXCZqqCcXUJCCCCCJUUJJCCCCCCJCCLQQQLCCCLLLQQQQLLLLLCCLOpbZCJCLLCJJLQQLLCCC
pqwmZZwwwwmmmZZZZmmmmmZZZO0OZZmmwwwwqpppdbaM%%bOwwZmdqC)`"l^ .. .-cJXf1{}[]]]?---??]]]]]??---------???-__-----_____+++++]tzLz]!iii!l;;;I;;;::;;;;::::::;;;;;;;::::;;:::;;;;;:::::;;;;;;;;;;;;;;;:;I;:::;;;Il;;]j0pLXccXYYYYUUYXYYXXYQpdwCzYUUUJJJJJJJJJCCJJJCLLCLLLLLLLLCCCLQQQLCLLCCCLOdhmLLLLLCCCCCCCCCCC
ppqmZZmqpqwmZZZZZmmmmZmmmZOOZZmwwqqwwqpddbh#&8kmwwOZpwL|"^:^.. ;1Xmc()1[???---???????---??????--_------_______________{XQc\<l>ilI;;;III;;;;;;;;;:::::;;;;;;;::::;;::::;;;::::;;;;;;;;;;;;;;;;;:;;I;:;II;I!l;;<umZQXczXYYYYYYYUUUXcCqdqLXUCUUJJJJCCJUUUJUJJCCCJJJJJJCLLCCCCCLLQQQQCJJLOdhmJJCCCCJJUYJCCCJJ
wwwmOOZwqwmZZmmZmmmmZZmmwmZZZZmwqqwwwqpdbbh*&8kZmwqdhkO/,";"'. "\LXf{-][?-----?---_-_--?]]]]?-___----______+___---_-[tmpt~>iil;;;;;IIII;;;;;;;;;::::;;;;;;;:::;;;;::::::::::;;:::::::::::::::::;l!I;IIIIII;:l|zOZYczXXXzXXXXXXXzzLqpwJcYJUUUUUJJJJUUUUJJJCCJUYYYYYUUUUUUUJJCLQQLJUUCOdk0XXYJJUUUYUJLCCCC
mmmmZZmmwmmmmmZZZmwwmZmmwmZZmmwwwwwmwqppdbh*8BhZmwwphkmt,";,`'. ~fULr1)1}]?-??????-??????]]???--____++______-_--___?{fwdf+<i!lllIII;;;;III;;;;;;;;;;:::::::;;;;;;;;;:,,,::;;;:::::::::::::::;I;:;II;;;;;III:;>)JmCYzzzzzXXXXzzcvcJmwZUcXUUUUUJJJJUUUYUJJYYYYUYYYYYYXXXYYUUUUUUUUXXYC0dhZUYYUUYYYYUJCCCCC
wwZZZZmZZZZmmZZZZmwqwmmZZZZZmwqqqwmmmwqppdh*%$hZwqwpbbwt^^;"'. ^+XpX\(1[?---????-_-????----------_________----___~+[tOm|>i!lI;;I;;;;;;;;:::::;;;:::::::;II;:::;;:::::::;;:::::::;I;;:;;;;;I;;:::::;;;;;;;;;;;_uQ0LXczXYcvczccvvvCwqOUvXYYYXXYYYUUUUYXYYYXXXYYXzzXYUUYUJJUUUYYXXXYUJLqhmJYYXXYXXXYUUUUUU
pqmZZmmmZZZZZZZmmmmmmmmZZZZZmmwwwwwmmwppdbh#B$*pppppdbpj,";^.. . `t0Lv\{}[?------__-??-______--??-?_+++__+++~~~++_~~}jOZ\<>ii!lI;;::::::::::::::;;;::::;IIII;::;;:::::::;;:::::::;I;;::;;:;I;:::::::;;;;;;;;I,itY0LvuvccvvccvvvvuJqqZUvzYYXzzzXXXXXXzzXYXXXXXXXXXXXXzcXUUXYYUUYYYYUYYOpQzcvczXXXXXYYYYYY
qwmZZZZZOOOOOOZmmmmZZZZZZZmZZZmmmwwwwqpdbka#B$oqppqqpdqr:";^'. )XJc|}1{]-__-___-?]]?-____--??--__---___________~+1xmw\<i!!lIII;::::::::::::::;;::,,:::;;;;::;::::::::;;::::::::::::::::;;;:::::;;;;;;;;;II:>fUZLnxvunuvvvvccvuUmwOYuczccccczzXzzzcczzzXYYYXzzzXXzzzXYUUYYXXXXXzzXUOwCvnnuczzzXXXYXzzz
wwmmZZZZZO000OZmmmZOOZZZZZZZZZmmmmmwwqpdbho#%Bhmqpqpkhdn!;I"'. .. . .?rYz|[}[-__---?]][[[]?-____----__________--__+~~<+[fZw\>>i>!;II;::::::::::::::::::,,,,,::::::::::;:::::::::::::::::::::;;;::::::;;;;;;;;;II;~rJQXttxxxxnuvccvvcJmqZYnczcvvvvczzzzccvuvccczzccvvuvvvuvvcXzzcczzcvuvX0wCcvczXXzcvvvczXXX
mmZZOOOOO0QQ0OZZZZZZZZZZZZZOOZmmZmmmwwqpbka#%$hZwpwpboac>II,`'. .l1XJ/[]?-------?]]?---______---??-__-----_+~~~~~<<_|Opr?+<>l;;;;::::::::::::::;:::::::::;;:;:::::;;:::::::;;::;:::;;;;;I;;::::;;;;;;;;;;;II;~xJUcffnxxnnnuvvuuvJZZLzxucccvuuuvccccccvvcccvvuuuuvccvvuvvvvvvcczzcvvcQwCvuuvcccvuvczzccc
ZZZZOOOOO00Q0ZZZOOZZZZZZZZO0OZwmZmmmmmwpdka*%$amwwwwqa#Xi:;^.. `~zQf}]][[[?_++__---------____---???---_++++++++~~<}Cwr]iIIIl;::;;;;;;;;;;;;;:,,,,:::::::::::::::;;:::::::;;;;;:,:;II;;II;;:::;;;;;;;;;;;Ill-cQYutfxxrxnnuuvuuvCqmCznuvvvvvvvzzzcvccvvuvcccvuvcccvvcvuuvvvvvccccvcYOpLvnxuvcvuvvzXXzzz
wmmZZZZmmZOOOOOOOOOOOOOOOZZZZwqqwmmmmmwqdkho8$hZmwwZOkWU>::^'.... . "xLn\{[{}]?????-__?]?????--------?---_______++~~++[zQz/~lii!lI;:::::;;;;;I;I;;;;;;;;I;;;IIII;;:;III;;;;;III;;;;;;;;;;;II;I;;;;;;;;;;;;;;Ili}zLXujjxuuuuuuccvuvCqmLXuvvccvczzcccvvczcvvvccvvvvvuvczzzcvvvcvvvvvvccz0pQzunvvuuvvvvvzXzz
wmZZZZZmmZZOOOZZZZZZZZZZZZmmmmwwmmmwwwqpbkao%$hZwqwZQb&C~:,"`'... . `|zzx1[1[-_--????-----------------_______---___+++]jUOY[i>ilII;;;;;;;;;;;II;l?|rj)]_~ilIl!lI;;I;;;;;;I;::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;I!+)XLvrjrxnnnnnuvvnnvJZOLzuczcvuvzcvczvvczcvuuvvvvcccvvccvvccccvvuuvvcczXOdQzuuvcvvvvuuuuuuu
wmZOOOOZZZZZZmmZZZZZZZZZZZZZZmmmmmwwqpddka*MB$hZwqwZLd&Q]I"""'... .~/CU)-]?-----?---______-----------___++__------_+-1nbp/+>i!lII;;;;;IIIIIII;l>]/rruzzv\?<i!lIIll;;II;;;;;;;:::::;;;;;;;;;:,,::;;;IIIIIII;![jQ0ujxnunnnnxnvvunnYZOJvxuccvvvzcvccvuczccczzzcczzccvvvvvvccccvvvvvvvcY0wCvuuuuvvuvvvuvvvv
ZZOOZZmmmmZZOOOOOZZZZZOOOOOOOZZZZZZmwwqdko#W$$awqqm0QdWO(!^""'. ^-UQt11}]-__-??--??-------_____-]]?-__++______-?_++\dhv{ili!lIIIIIIIIIIIIIIIII;Ili~(xvuxf/)+!ll!!lI;;;II;;::;;;;;;;;;;;;:,,::;;IIIIIIII,I)cmmurvvuuuvvunnuuunYO0CcnvzzzcvvvvvvcczzccczzXXXXzcvvccccvccvuunuvcvvXLmqJvcccczzcczzzcccc
mmZZZZZmmZZOOOOZZZZZZZZZZOOOOOOOOZZmmwqpko#&B$*pqwZ0QdMZt<`^"' IxQQv{__-?-_?]????????------__?[]?-__+_______-?_+<1LqJtiIi!lIIII;;II;;;;;;;II;:,,":l+{\rzcf1~!lII;;;;;::;;;;;;;;IIIIIIIIII;;;;;;;;;;;;"I/JZ0urvvnnuuuuuvvvuuUZm0zrucccvvvvcvuvcccccvccccvvunnnuvvvvccvvuvvvcvnX0wwJvvcvvcccccvvczzz
wwmZZZZZZZOOOOOOOOOOOOOOO0QQQQ000OZmmwqpbh*MB$#dqwmOCq#wx~''^. 'i/OL/}[]?-__---??---????????????-______------_++<[vQLx>I!lI;III;;;;;;:::::,:;;::::::::;i}xvrt|)}_>!III::;I;IIIIIIIIIIIIIII;;;;;;;;;;I:>xQ0JurnuunnnnunnnunxYZmQcrnvuunnuvvvvvvvunnuuuunuuunnnuunuvccvuuvvvvunYmwOYnuvvvvvcvvcczzzz
ZZZZmmZZZmmmZZOZO0ZmwmZOOmdkhahdqwwwwmwpka*#B@owOOwZQq#qu-`",' IfYCn{?]??--__--??]?---???--??]]?-____-?--?-_-_>-uQOv~I!lII;;IIIIIIII;;;;;;;;;IllllIII:I~}\rzJCj]<!lIIIllI;:IlI;IllI;IlII;:;;;;;;;Ill_zwLcrjnxxrxxnnnnxxrxYmm0XnuvvvunnuvcccvuunnnuuuuuuuvvvvunuvvvuuvvccvvuUZZLznucczzzcvcczzXXX
wwmmmZZZZZZZZZZZZZmmZO0Zk#88&%B&odmwwwwpbho*8BMahoWMbh#dY{",:`.. 'Itw0j1??]?-----???--__---____-?----_-??-___-_+~-tUpC}<<!IIIIIIIIIIIII;;;IlIIIllII;;;;;;;;::I]tnccvvr(]~>ilI!i!!lIllIII;;;;::;;;;III![CbLvxrnuunxnuxrxxnnvJww0zxucczzcvuuuvvvuunnuvcvuuuuuvvvvnuccvuuuvczzcvY0Z0XuvzzzXzcvvczXXXX
qwmmZZZZZZZOOZZOOZZZZwph8B#bmbW&#dZmwmwpkaooW%BB$$@$8%%aC1":I^'. !tvcf{1)}]__???]]?---??-___--___--_+_------??-])vbO(+>lIIlllllllllIIIII!!I;IIllII;;IIIII!!lIl_1|tnXCXf}<i>!!!!ll!!!lIIIII;::;Il!ll>1QbJnuvvvvunvvuuvcvucLqmCcnzXvuccvvvczzzvuvcczXzcvvvvvczcuuvvvvvcccccvvJwwOUcXYXXYYYXXXYXXXX
mZZZZZmmwmmZZZZO00Ommwb*$%bmOp*WWbZmwmwpko*#&%$@$$$@@@@#0/>i!,`'. .I\Ju)}]?-__-????-----?-__---?-_--__-----????--}xbZ\_i!llllllllllllllll!!IIIl!lIIIllIIl!!iii!l;:""i|ncj?>illl!!!!!!lIIlIIllIIIIl!~)vp*wCUYzcvvvvccvcvnuzLmOJzvXYcvzXzzzzXXzccczzzXzcvvvvcczcvvcccccczzzzzcJmwZJzYUYXYYUYXXYXXXX
mmZZZZmmwwwmZZZmZZZmmwkM$8pOOqhW&b0Ommwdh*#M8$$$$$$@@@@#Zj_<>:^'. . [YYx)_?[?????]]????][]]]?-???-]}{{}]-?[]?-_+-1vkm|+>!!!!!!lllllllll!!lIl!!!l!i<~__-?--?-??]?---__?/ULUzuxf([_<i!ll!i>i!!llI;i?/zZh*awQCYcuuuvvcczzzvvzQbqQznvzczYYXXXXXzzXYYXXXzzzzzzzXXzzzzXXXXXYUUUUYY0dbwLYUJUUJUYYXYYYYYY
qwwmZZZZZmmmmZZZZOZZOmkM$%bmZwh&BhZZZZmdho*M8$$$$B$$$@@Mmx]+>;"`. itYLf-[{[?---?]???][[[[[]-?])fcJQ00Cvf)[]???{fUkO)~>i>>>ii!!llllllll!lIl!!<}jJmkaaooaaooao*######o*W&8%BB8#kmLXuf)?_+<>i+1tuYLOmpbkd0CLQQLCCCUXYYYYXzz0hhwXxzUzzXXXYJJUXzYUUYXzccXXXXYYXzzXXXXXYYUUUUUYY0dpmCYUJUUUUUUUYYUJJJ
ZZmmZZZZmmmmmmmZZOOOOZd*B8pOZqk&@aZZmZwph*M&%@$B8W#M%$@*0/>i!:^'.. . ,?vOn{}}[]__-][[]]]]]]]]??}\XZQz|(uCmZQ0Omwwpk*WoZ0ZO0OZO000QLJJUYXcvxf/trUpW@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@$&qu|}}(nQa%$BW**WB$@$$B$@@@B8#hZQ0QJYX0khdJvYJYzzXXXXXXzcczXzzccccXUUUXzzzXzzzzYYYXYYYYYQqw0YcYJUYJUYYXYUUJJJ
mmmmmmZmmmZZOZZZZ00QL0p*$8qQ0mb&@aZZmZmpko#WB@@$BB%88$@aJ(lII"'. ,f0Xt)[[]?---?---?]]?-_-]|uwhY(+l!-/LW$@@@@@@@@@@@@@@@@@@@@@@@@@@@@@$B%%$@@@@@@$B&*bqm00mdho#M&W*abpppppdbhM%$@@&hm0wh&$@@@@@@@@@@@@@@@@@@@@$Wp00QUXXCmppCczXzzczzzcccczXXzzzzzzccczXXXXXcczzXYYzzXXzzX0dpOUcXYYYUUUYXYUUUUU
mmmmmmmmmmmZZZZmmO0QQ0p*$8qQ0ZdW@ammmmmqba*M%@@@@@@@@@$aC/+>!:^' -nJJf{{[-_---????]]]?-1jQ*B%J\|/xf{/Up#*aaadwZ00QQCUC00Zqdkao#MMMMMMW8%8%B$@@$8aJj)-!l<xZ0z/{1\nYCLCzr\{_[j08@@@@@@@@@$WhZLJLOmOXnrjjuLkB@$&amLLCYXYLmddLvczXzcvvvvczcvcczXXXzcvvczzcczccczXXXXcczXcccQddZJcXUUYYYUUYYYYYYY
OZZZOOOOZZZZZmmZZOOO0Zp*$8pOZwb&@omwqwqbh*M&%@@$@$$8#MMwn];;;^. ^~u0ct({{}}[]][[]]]-?}nqW@Baz()xmOr1[fCZwp0j[+>iiil;;;;I!><~~++___+<~]]-|Xb$@$hJ)~_<:":1zQ0v|~;:i}jYQOLz/)fL8@@@@@@@@@8dX(-?|uXv],,"`I1C8@$Md0JUYXXYCmbkLvucXXcvvvvzzcvvczXzzccvczzzvvvcccczXXzcvvvccc0kbmCXYUUUUUUYYUCUYYY
OZZZOOOOZZZZZZmZZZZZZmd*$%dZwqk&@aZmwwqbho#M%@@$@@$&dh&pn]:;;^. .[nUYt)()1[?????]]?{f08@@hJt(xJq0/-!<])()]>llI;;l!!llllIIII;;;IllIIIllI?rq@@Bpc1~~<i;"^:[rJ0Ux[i;"",i}fz0d*B@@8*dwa8@&QnfjcLwq0f?-~!>1J8@$*qQJJUYzcUOko0vvcccvvcczzzzzXYYXcccvvcczcccccczXYUYXXXXXYYX0dbqQUJJYYUJJUYJCCCCC
OOOOOOOOOO00000OOOOO0Zd*$%dmwpk&@hOZmwqbh*#M%@@@$$@&dkWqr_":;^. . ,]Cwu(}][[]???]]?-)uq$@@wx|jdoLt>!+<lII;;;IlI;Il!!lIIIIIII;;Ill!!lIlll}ud@@Bmx1_~>l;:^'`"!]tncu/}~i>+}\vqM$@@#ZufLoB%bmZJnjjYQn)-i;>(L%@$omQJJJUYXYCb#OunnuvccccvvcvvvczzccvvuvvczzzzzzzXXXXXXXXXUYY0dkbQXUJUUUJJJCCCCCCC
OOOZZZZmZZOO0QQQ00OOOZpoB%hqwqb&$kQZmZwdh*#W%@@@@@$%M8$dx];,"`. . ,vmUr1[1{?-_][]?-?)xQk#qz|(UZLn]~~>iI;;;Il!!IIllllIIIIIlllIIIIll!!lIl[up@@Bpz(_~!;::,,"^^`.,-|xunvzJCzYpM$@@oLr/Yb8BhOc/{(jcc)i!I,-vpB@$hOLCJUYXXczmhZYcvczcczcvczcccvvvvvvvczXXXXXXXXYYXXXYUJJCCJULwkh0zUCLLJUCCLLLLLLL
OOOOOOOZZZOO0QQ000ZmZZqaB%kwmmpMBkOmwZZwdaM8$@@@$B8W#&$dn{i;,`.. ']xLCf((1}]]][[[]?-]1umaaCf1{t\]<llilIIIIIIIII;;;;IIIIIIIIIlllIl!!lII<(0$@@%oQn|]~l:,,"^^`...`,!-)fnXLqW$$@Bdv//Yb%%p0Q0mOJx)+lllI)Q*$@%b0LLCJUYXccQdwQUYUUXXXXXXYYYYXzzczzzXXXYYUUUUUUUUUJCCCCCLLJCQqbZCCLQQCJJLQLCCLLL
OOOOO0OOOOOO00000Q00Q0whBBaqZwkM8kOZmOZqboM8B@$$$$%WaW$pj+"",'. .^?U0v/}]}[[?-??--]/XYcXCdpx[<!>]|)-<llII;;;;;;IlI;IIIIIIIIlllII;IlllI>jwM$@@@%Mokpm0LUzvxf//\|||/rYw#B$@@8hLj|/Yd%%p00Zwc[~>>i!>?u*$@%#wCJJJUYYUYX0pqZUzXYXXXXXzzXXXXXzczYYXzcXYYYXXYYYYUJJUUYUCJUUCZpZLJUJJUUJJCCJJJJJ
OO00QQQ00000000OOO00Omdo%B#dZwhWBW**adqdh*&%BBBB$$$%M&%px-,",`. ;jJLz\)1[???]??[(zpY}i>tJw0j\rCdJ(_!!!!llI;;II;;;IIII;;IIlllII;;;IllIl~/Up*&B$@@@@@@@@@@@@@@@@@@@@@@@@@BaCx(?]xZ&$Maho*qUXXzXJObM$@@&kOJCCJUYXzccQpqOcxvcccccczzXzccczzzYXzzzXYYYYYUYXYJJUJUUUUYXUQdamJYYCLJJJJJLQLCCC
OO00QQQQQ00000OOOOmqaW%B@$8Mo#8$@@@@B*hhoM&%B$$$$@@BMW&pu],,,`.. `?nwL|}1}[[}[[[\zLLj<!ii?uL00Czr{ilIllIIll;;;::;II;IIIIIIIIIIIIIlllIIIIIl+{|tjuYCQZpka*#W8%$@$$$$%WW#kZzj(]<l!1chB@@@@@@@@@@@@@@@$8*d0CJUUYYUXcczLqpmzxvcvvuvvczXYXzzXYXXXXXXXXXXYYYUUUUUYUUJUUYYJ0boZYYULLJUUUUCQLCCC
000QLLLLLQ00000000mbW$@@@$BBBB$B$$@@B*hhao#M8B$@@$B8M%@bn+`^,`. .")wmj(1{{{}-]|cpOf]!!ii!!i<<ilI;:;::::;;;:,::;II;;;;IIIIIIIIIlllI;;;;:;III;;;;Ill!iii>>><+_-__]}_<~~>!!lll!I;;</Xmko#MM*akkdqmOLYzzXXXzccczzcvvcULZZXxuuuuuczcczXXXXXYYXXXXXYYYYYYUJCCJUJCLCJUUUJLqhmJJJJJJUUUUJCCCCC
QLLCCCCCLLQQQQQQQ0mbMBBB@%addka&@@@@$8&&WWMWW&%$$B&#hM$bx+^",`. !vQCu|(()}_[rQhL[><>i!I;:::;IlII;;;;;;;::::;;;;;;;IIIIIlllI;;;;;;;IIIIIIIIl!l;IlIIII;::;IIllIIIlI;:;;;IlIIII::![uOahmUuuvunnnnnnuvccvvczzzccvvcXCqdCcccccvvccvczXYYYYYYYYYYUUUUUUJJJUUJLLCCJJUUJ0b#d0CUUJCJUUUUUCCCC
LLLLCCCLLLLLLLLQ0Zb#8$BB@B#ahoW%@@@$$$@@@$$$$$$$$BW*aW$dx-,,,`.. ,1YkQ\)11{]1xLbY~li!llII;;IIII;;Il;;;III;::,,:;IIIII;;IIllllI;;;IIIIIIIIIIIII;;;:::;::;IllI;II!+}(tjrxrrrrt(}-ii-fOkadOmpqm0JzzYYXzcczXYzzXXzccYQhoOXXXYXccczzXXYYXXYUUUUUUJJJJJJCCCJJCCJJJJJUYUQdop0LJUUJUUUJUJCCCC
QQQQLLQQQQQQQLQOmb#B$@@@$$$$$@@@$@@@@@@@@@$$$@@@@%#ak#%du?"",^.. .:x&ac/{1){|z0qviI<il;;IIIIII;;;;I;;;;;:,:;::::;;;;;;III;;;;IIIIIIIIIIIIIIIII;III;;;;I;;,;i?|rvcvxjf/(1{{1{[_<>!II<tOdpCcX0aMawUXYUUUUXcczzXYYXU0o&mXzzXXvcXYYYYUUXXYUJJJJUJCCCJJJCLLCCCJUJJUUYULd*pQUXYUJJJUUUYJCCC
00QQQQQQQQQQQLQZqhW$@@@@@$%B@@$@@@@@@@@@@@@$@@$B%&*hb*8bc?^",^. (kWaQx/(1tQwQr>i+>l;;IIIIIIIIIIII;;:::;III;;;I!iilIIllI;IIIIIIIIIIIII;;;IIIII;;IIlll;I>{rczr)-<!i~]1)(()[_~>i!!l:I+\zUUucwo*pYzYUUUUYYYYYYXzvcUbMwJYXXzvzUUUUUJJYYUUJJJJJJJCCCJJJJCCJJCLCCJJCJJqadOCUJCJJCCCCCCLLL
000QQLLLQQQQQL0ZqbM@@$@$$%W&B$$$$$@@@@B88B$@$%*kbbbdpo8pn+'^,`'. "|q&$#mcfjXbpn{ii~>lI;II;III;;;;IllIIIIll!~[fXOqqm0Xf}i!i!lllllIIIII;;;;;;lllllIIII;;!}uzx(<IIi}n0hM&&88&MaQn|}]-+>l;!)vOkohZJzzYYYYUCCUUUUYYXXJb#mUzczXzYJJJUUJUUUUJCCCCCLQLCJUJCLLLCJJCCCCCLCCp#hwQCLLLL000QLLQQQ
00QLCCCCCCCCCCLQmb#B@$$$$B88%B$$@$$$@@%okh#%8#bwqppqwa%dn-^,:^'. .:|Z#%BMmYXQ*p/+!!i!lIIIIIII;;;;IIIlIIIIIl>}/jf([??]]_>I;I;IIlIIIIIIIIIII;IlllIII;;:;!+|Uc[iIIli[u0pbqwZ0QQLcf)]-~<i!!lIl_|c0pq0JXXYXXXXXXUJJJUYJb#mUzzYUYUJCCLLLCLLCLLLLLQQQLLCCLLLLLLCJJCLQLCCLb#kZLJLQQQQQ0QQQQQQ
O0LCCLLLLLCCCJC0md#B$@@$$B%%B$$$@$$$@@B*hhMB8#kqqqddqo%dx_^":^' .;\ma#%BdQZpkC-I!!!lIIIIIIII;;;IIIllllllllllllI;Ii+]?+illi!!!llIIIIIIIlllllIllI;II;;;!+)uu/\\()11)(((()){]?-~<>>>ilIIIllI;;!]jJqmJYYXXYUUUJCLCJUCdomJUUJJJCCLQQLCCLLLLLLLQQQQQQQLLLLCCLQQLLLLCJJLbMpCUUCLLLQQQQQQLLL
00QQQQQLCCCLLLQ0md*%@@@$@$$$$$@$$$$$$@%ohaM%&*kqwwqwZh%dx+`^,^' ,\wkboWMM%Mmu?ii!!llIIIIIIIII;;;;;IIIIIIIIllI;:;i(JwwY\]~>illllI;I;;;;;;IIIIl!lIIIIIlIi_{\jrxnxxrrrrrrrnvJ00QCCQQUUUXcr/({-+?xdb0JXXYYUJJJJCJJJQh#wJUUJJJJCCLLLLQ0QQLLQQQQQQQQLLLLLCJCL00000QLLOkMbOOO00QQQQQ00QQQQ
00QLLLCCCLLQQLL0wkoM&%B$$$$B%%B$$@@@@$&hbk#B8#kpqqpwZk%dx_^^"`' .:tdhwph%@%kc|}_>!!llI;;;II;III;IIIIIIIIIIllllIII;>(nCCXUYx|?<i!lIIl!lII;IIllIIIIIIIl!ll;Illll!!l!!!i!!!i-uwdqLJOZQQOZmqddddqqkW*q0JJCCCJCCLQLCCQhMpQLLLQQQQQQQQLQQQLLLLLLQQQQQQQQ0ZOQQQQQQQLLLQOhWaqmZO0QQ0OO000000
0QLCCCJJCLQQLCC0wdbbbbhaaaaoo*#W8&&WM*abbhMB&*bqqqqmOk%qt>`^"^'. ,thowZq&$kY)~+~>i!llIIIIllIIII;;;;;;;IIIIIIIllll;I>}fnzOdw0QJXur\}]]-+~<i!!!lIIIIII;Ill;;Illl!llll!ii!!li|Uda0XXzcczXYUJCLQQLLQQ0QCCJCCCCCCCCCC0aMwCCCLQ0OOO00000000000000QQ000000O0000000000QLQbWaq0LOO000OZZZmwww
QLLLLLLCLLQQLLCLZpbbdqqqqqqqpdbkahhhkbpwqk#%WobqqwwZOk%m|>"",^'. ^\dhmmqM8bU|-_<ii!llllllIIII;;;;;;;;;IIIlIIIIIIllI;l_fJCv)>i>-\X0wm0LLCCQQJXuxxjt/|1[-+>!!!lllIIl!ii>iill?rd&wJUUJJJJCJUUUJUYYYUCCCCLLLLLQQQQQOwM8qLLQQ0OZZO000OOOOOOOOOOOOOOOZZZZOOZZZZZZZZmZOOb#hqZOZZmmwwwmZmwww
00QQQQQLCLQ00QQ0ZwmOQLCCLQQQLLQQLLLLQ00QZd#%WabpqqwmZaBZ1l^^"`. ^/kawZwa#*mf[-~i!!llllllIIII;IIII;;;IIlllllll!lIIIll;l_/vcx|1)xZC|>`'`:?XJ|+!i-{\rvJQCUzccvuvzXYvnnnnxj|}?)Q*kZJYUJCCJCCJJCLCCCCCCLLQQQ000QQQQ0moMqQ0OOOZZZO0Q00OOZZZZOOOOOOOOZZZmmmmZZmmmmmmmZZdabqmZOZmwqqwwmmwmm
O0QQQQQLCCLLQLLQLJUYYYYUJCCCCCCJUUJJCLLLOp*%Wadqwwmmwa8L-:`^"'. "f*#qwqk*%av)}_>i!!!ll!!llIIIIIII;;;;;;;;IIIll!!lIIII;:l~1fzOk&@WZu)-~_|O0-. ;rUf1}[}}}\uqbu}]?][1fcXUp**bQUCCLCCCCCCCLLLLLLLLLCQ000QQ0QQ0m*WwL0OmmmZZOOOZZZOOZZOOOOOOOOOOZmwwwwwwmwwwwmZZZb*hpmZmwwmmmmwwwmmm
LLLLLLLLLCCJJCCCJUUUUUCCJJJJJCCJUJJJJCCLOp*%Whpwmmmwp*&C+;:"^'. "fo*wwqpk$8Lf[~ii<>i!!!!!llllIIII;;;;;;;IIIIIIllI;;;III;;Ili~-)ruvvcczCqM#Lnf|{<I~\waY)I'. i|L0? ~upWaqmOCCLLJJCJJCLQQQLLCCCCLLQQLLQQ00QOq&BdLQ0OOO0QQ0ZmmmOOOOZZZZOOOOOZZZZmmmmmmmmmmmZOOb*#aqZZmmmmmwwqmZZZ
LLLLCJJUJJJCJJJUUUJJJJCCCCCCJCCJUCCJJCLLOq*%#bpwmZZmd#&J~;:,^'. .:j**Zmqqk%&0r]i!i>i!l;IIII;;IIIII;;;;;;;IIIIIIllllIlllIIIIl!!llIIIIl>_]}1(truzXzXLwh#WM*bwZZd*WoU/[<:"l\0bkQzXYUUUYYYUUJCCCCCLLLLCCLLLLLLLLLCCQZoMqLCLQQ00000OOZZZO00OOZOO0OOOOO0OZZZZZmmmwwwmmmdo#aw0OZZZOmqqqwmmm
LLCCCCCCCJJJJJUYYYXYUJJJJJJJCCCCCCCJUJCC0q*%#dqwwmZmd*WY>::,"'. '!uW*OZppk8&mu[<<>>ilI;;;IIIIIIIII;;;;;;IIIIll!!!!lIIIIlllllIIllIIIll!!I;;;llll!><~_-}|rYCQmd#%B$$B&*kbhW$$%&*dwmZO0QLJJCCCJJJCLLLLCCCCCLQQ00QQQOdkZLQ0OZZZ00Q00OOOO0OOZZZZZZOOOOOOZZZOOOOZZZZOOOqh##q0OOZZOZmwwwwww
LLLLCCCCCCJJJCCUUJJUUUUUJJJJJUJCLLLJJCLC0qo8#bqwwmZwb*MXi::"`'. . 'iuW*Ompwqa*kC(??+>!llI;;Il!!lIIIIII;;;;IIIllII;I;IIIIIIllIIllIIIl!lIl!!i!l!lIII;;;I;;;;Ill!>_[1(\tfxvUOkW%$@@$%&WM#obwZ0QCJJJCCLQQQCCLLLLQQLLL0mh*qQLLQQ0OOOOOOZZZZOOZZZmmmZZZZZZmwmZZZOOOOOZZOOwboowQ0OZZZmmmZZmmm
JJJJUYYUUJJJUUUUYYUUUYYYYUUJJJJCCCCUUUUULwo%#dwmwwmqb*#Xi::,^'. 'lxoaOwdqqba#qr1]+>!llIII!ii!II;II;;;;;IIIIIIIIIIII;IIIIIIIIll!lII!lll!!lll!!llIIlllI;IllIII;II:,:;;;;Il<]\nXYcr({)cbokmLCCJJJCLLQQQQQQQLLLLLCCLOh#pO00QQ00OO00000OZZZZZOZZZOOOOOZmmZZOOOOOOOOO0OOwo#q00OOOOOOZZmmmm
JJUUUJJJJJJJUYYYYYUUUUUYUYYYUJLCJCCCJUYYLwo%#bwmmmmqk*#X<Il:^'. .;jhhOwdqqkoMqf}-~i!llIll!!lII;;II;;IlllllII;IIIIIIllllllIIIllll!lIIllllll!!!lllllllllI;;III;;IIIlllllllIIII;;;Il[uw8MdOCCLCCCCCCCLLLQQQQQCCCJJJQdawQLLQ000QLLLQQ000OOOOOO0O000000OZZOOZZZOO00000Ow#8kZO00OOOOOOOOOO
CCCJUUUUJCCJUYYUUUJJUYYYUUYUJJUUUJCLCJUJQq*%MbqmZZZwboovl","^'. ';jaamqdddka#wt}]+>!!!!!!!lIII;;II;;l!llllII;IIIIll!!!!!!!i!IIl!!!!!!!ii>iii!!i>i!ll!!ll!!lllllllllllllll!!l!!!?rO&&bZCJCJJJJJUUUJCLLLLLLLLLLLCCQb*dOCCLQQQQLLLQQQQQQ00OOOOO00000000OOOOO0OO00QLLLOaWkm00ZZOOOO0OZZZ
JJCCJJJCLCJUUJJJJUJCCJUYUUJUUUJJJCCCCJJULmo%MhdqmZ0mdaocl"""^' . .IjhamwppdhahQ/[]+>i!llllllII;;IllIIlllllllllllllll!!!lllll!llllIIllllllllll!!!!llllllllllllll!!!!!!llll!i!llll[YdMdXcYUUUUJJJJJJJJCCCCCJJJJJJJUCb#kmLJLLLLCCCLQQQQQLQQ0000QQLQQ000Q0OZOOOOOO0QQQLQkMkwQLZZOOO0Q0000
CCLLLCCLLCCJUYUJCLLQLCCCCCJJJCQLCLLLCUUULwo%WhbqmZOmdaavl:I,`' .IjbkZwpqp**wz(]?_~>i!lll!!!lIIl!!IIIl;IIl!!i!l!!!!lllllllllllli~++_-??-+~<>>!!lIII;;IIIl!!!!!!!!iii!!ll!i!ll!l?vq8hXvzXYUUYYXXXXXXYUJJUYYYUUUYXYwhbmLUJCCCLLLLLLLLLCCLLLLCCCCCLQQQLLQQQQQQ00QLLLC0kMhwCJ00QQ0QLLLLL
LLLLLLLLCJJJJUJCCCCCCCJJJUYUJCLLCLLLLJJJ0p#BMbqwmZ0ZpaauI;!:`. .. ,-vh*hkhho%WZu(]-~>ii!llllllllIIIlIIII;;IIll!!i!l!!ii!!l!!>~-)uCwba*######hm0LYvuxj/)}?_~<>i!!lll!iiii!l!>!l!!l>{Y&#CXXYUUUUUYXXzzXYUJJJYXXXYXzczOdkpLYYYYUJJJJJJCLLCCCLLLLLLQQQQQQQLLQQQQQLLLLLLCLbodZJULQCLLLLLLLL
QLCCLCCCCCCCCJCLLCCCCCJJUYUJJJCCCLLCCJUULq*$MbpqwZ0OdaavlI!,'. ... ^i)uOb*M&8%$@@&Ou|}?+>ii>>>iiii>>illlIllllIll!!!!!!iiii!!<]tz0doW%%&#ahbqqo&&oZOdhaaooabqqwZQUcnt)1{]-+<ilI!>!liili[z&M0JJZdbpZQCUXULQ0QLCJYYYUUUUYUQmbdQYUUUJCCCJJJCCLCLQLLLQQ0000QQQLCCLLQQLCCLQQLCLdobmJYCQ0wbbdwZOO
QLCLQLCJJJJCCLLLLLCJCLLCJUJUUJCCCCCCJCJUQp#$MdqqmZ0Zk#*cl:I"'. `}cd#abqb*W&W#&aYf([+>!!i>><>ii>>iiiii!ll!!i!ll!i!l!!!<]/XwokmQQbokpqqqqqZZh#awznvvuXQhMpCXY0b&%8&##*bwOJvj/|)[-__-(Xd%*CJ0wbaokmJXX0h&8k0JUJJUYUJJYYCmM8aq0LLCJJCCCLLLLCCLLLLLCJLLLCCCLLLLLLCCCLCJUUUCpahmXcCOpko*apO00
LCJCQLCJUUJCCCJJCCCJCLCJUUYYYUJJJJCCCCCJ0p#B#dqqwZQOd**cl;l"'.. .. ."~\QkakpqpbaM&M**qx){?~<>>ii>>>!!!iiii!!ll!i>>iiiii!ll_fJdkwUf_:,?LapwqqqwmOOk#*b0CLCCma%$h0UCwhM&8%&hmOZpo%$$%Madqqpa88amCOdppbkdmJXUZo8$MbOJUYXXXXzczCqW$%#q0JUJUYUUUUUUUYYUJJUYUJCJJUUUUYYYYYJCCL00LXzQpdwJYQmdkkhk0UUJ
CCCCLCJJJUUJJCCJJJJUCLJUJUXXXYYUUJCCCLCC0p#$MbpqwZQZk*avl:I".. .. . `I-/zZkkbddppddbh*&&*qXr/)[_~>iiii>>>>>iiiii!!l!!i><<>>~{vm#Wh0urr\)(rp#dwwwwmmOZa&#hqqppqoB@$#bpk&B%%B@$*pwwpa%$@$8#a*MMMW#akk*WM*##abwmpaWWM88*kpwwmwmOQQOwbho*#kOQQQQQLLLCCL0mwwmZOOZwdkhdZ00000QLQOb&8#qLZpkbmmdkhhhhbOCLQ
LLLLCJUJLCCJJCCCCCJCCLJJJUYYYUUJCLQLLCCULw*BMbpwZOQma#hu!;I"`'... . ';[vOhoohkbbddddppddpdk#WW#hbpLuf\{-~<>i!!!iiiiiiiii>>>>!~/C#@@BW#*###**#88W#okpqwZmo&M##WBB&%$@@$B%B$$BB$$@$$BB$$@@$$BB%%%%%%%BB%BB8&%B8WMW8&Moa*&%$$BBBB%8WMWW#akaW8&*bdpdpmOOmd#B&apmwdoMMW%B%&#abppdkaMB@$8#ooMMooMW&&888M*##
JJJCCJUUJUYUUJCCJUUJJUUUUYXXYYYUUJCCCLLC0pM$MbpwmOQmh*hu!Il,`'... .. `+uqWWabdddddbbdddbbdppddbbh*M&8%%&*d0Uzx\)1]_~<<<>><<<i!<{cpW$B&*hbdbbbbkho#W&888WhdoW#aqpho**okdbhookpmwdkaahhkdppqmmwqppwmmqpdbbkkpqbaMWWW#ohbddbko##aaa*W&&88W#aha*WWWWM####*#MWM#***###ohbkh*MW&&MM&8&W**#W&8&&&8%8&MabbhM%88
YYYUUUYYYYYYYUUJUUUUUUUYXXXXXYYUUUUJCCCJ0dM$#dqqwZLZh#oc!:I,`'.. ... ,1zb#okppddddddddddbbdddddpddddbbkkko##MWW#*akdqZCzxft/())tcp&B$%W*ahkkbbbbbbkbbh*W%8&%%*pCYYXzccuxxnczcvuuccczzccvuuuvvvvvvvuuvcczXUUYXYUL0O0LLCCCCCJJCJJJJJJCQQQ0QLLCJCQOwpbkbdqmOQCLOwppqZQCUYXXYJL0OmwqwmOOOO0OOQQ00QQQ00LCQO0Q
YYUUJJJJUUUUUUUJJJUUJCJUYYUUUUYYYYYJJJUYQdW@#pwwZ0J0b*av!:;^'....... .>/Zoakqqdddpddddpdddppppdbppddppddpddbbbbbkhhh*WWW&8&&WWWWWWWWWWM*akbbbbddbkdddbbbdbaM%$BMdLYYXvvvunxxnuuunuuuuuunnnnnnnuvccvuuunnnuvvvvvccXXYYYXzzzXXYYXzcccvvcccvvvvvvvvuuuvczcvuuvvvvuvczzccvvvcccvvcvvzXzXYYXXzcvzzzcczXYYYXXXYY
CCCCJJJUUUUJJJCCCCCCLLCJUUJCCCJJCJJCCJJJ0bW@MbqmOQCQqa*X>"^^`''`'. '^>up##bppddddddddbbddbbbbbbbddbbbbbddbkkkbbbbbbbbbddddbkkkkhahkdpbkkbbbkkbdpdbkbddbbkbdkoW88oZCJXcccvvuuuuuunnuuvuuuuuuvvuuvvccvvvvuuvvvvnnvzXYYYXzzXXYYXzzzccczzzzzccvcccccccccccvvuvvczzzcczzzzzzzXYYYYXXUOwwOCUXXXYYUYzczXXzvzXzzYU
QQQQLLCCJJJCCCLLCCCLQQQLLLQQQQLQ0000QLLLZk&@WhdqmOL0qoWJ~,^""``^`..'.^_rq#hdpdkbddbkkkkkbbbbddbbbbbbbbbbbddbbbbbbkkkkkkkkkbbkkkkbkkbdbkkkkbbdbbkkkbbkhkkbkkkbdbaM%8kZCYXzccvccccccvvvvcunuvvvccvccvvuuuuuuuuuvvuuucczzzzXXXXXzzzzzzzXXXXXYUUYXzzXYYXXXXXzzXXXXXzzczXYYYYYUUJJUUJQZdhapLUJLZpkkdwZO0000QLCJUU
LLLLCCJJJJJCCLQ0QLLQQQLLLLCLLCCLLLQ0O0LLObW@&hdqZ0LOb#&Y>:;"^^^^^'..`ixqaobppdddpdkkbbbddbbbbbbbddbbbdbbdddbbkkbbkkbbbbbbbbdbbbbbbbbbkbbdddbkkbbbbkkhhkbbddbkhhkhM&&oZQCJJUYYYXXzzccvvvuuuuuuvuuvzcvuuuuvvuuuvcvvvvvvcczXXXXzcczzXYYXXXzczzzzzzzXYYYXzcczXYYXXXXYJJJJUUUUJJUUUJLOOCLZqbkaakpZOZqbbbdbkhahbwm
LLLLLLCCCCCCLLQLCJCLLCJJJUUUJCLLLLLQQLCJQp#$WhpmZOQZkMWY<;I,^^^`''.'!(OWodpdbbddddbddddpddbdbbkbddbbddbbbbbbbkkbdddbbddbbbbbdddbkkkkkkkbdddbbkbbbbbbkkbbbddddkhkba#B&d0JUUYYXYYYXzcccvvcccvvvnnnuvuuvvuuuvcvuuuuuuuvvcccccccccvvvvzzcczzczzzzXXzXXXXzccczXUUzccXJLLCUYXYYYYUUJL0LJXXCZdbdmQJUYYUJJJUUJJCQQLL
CCCCJJJJUJCCCCCCCJCCCCCJJJJJCCLLQLLQQCCJObMBWhpmmZOmb#8J~l!I:,"..`^;{zbWhpbkbbdddddbbbbddbbbbbddddkkdddbbbkbbbdddbbbbdppddbbddbbkbdbkkbbdbbbbbbdbkkbbbbbbbbbbbkkbba88oqCYYXzccczzzXXzzzzzcczcvvuunnuvvvuvczzccccvuuuuvvvvvvvvvvvvvczzXXXzzzczXYXXXzzzXYYYYYYXzzXYYYYYYUUYYYYYYYYzzzXYUUYXzzzzzzXXXXzzcccczzz
CCCCJJUUYJJJJJJJJJJJCCCCCCCCCCCLLLLQQQQQmkW$WhdwmZOZq#$O[l:^`^^`'.`lfmo#bwpdbbddbbddddddba*M*kbdddbkbbkkbbbbbbbbkkkkbbbbkkkbbbbbkbdbbbddbkkbbbbbkkkkbbbbbbbbbbbbbbh#W&ow0JYXzczccccvuuuuuvvvvvvvvcvvvvccccccczzcvvvvcccccccczzzzcccczXXzzcccczXYYYXzccccvczzXXXXzzzzXXXXXzcczXXXXXXXXXzccczccccczzzzzzzXXXXX
JJCJUUUUUCLLLLLCCCCJUUYYUUUUYUJLLQQ00QLLObM$WkpwmmmZmo$q/~,^^^`''':-za*adqpdddppddbddbbbkhM%Wahkbbbbkhkkbbkkkbbbbbbkbbbkkkbbkkkkkkkbkkkbbkbdddbbkhkbbbddbbbddbkkkbka#8#pQXzcunnnrrxxxnuuunnuunnxnnxrrrxnnxjjjrxrrrxxxxxxxxxxrrnunnnnnnnnxxxnnunnnnxxxnnnxxnuuuuuuunnnuuunnnuuvvuunnuvvvuuvcccvvvvvvvvvvuuuuu
JJJUYYYYYJCCCCCCLLLCJJUUJJUUUUCLLLLCCCCC0q*%&obqwmmmma%dn-";I^. '~jw&oqpbao##*##MM*ooaaaoM%&#ohhhhhhhkkkhhkkbddddbbbbbbbbbdkkbbdbbkkkbddbbbbbddbkbbbbbbbbbka**ahhkk*8MbQvnxjft/\|||/fjft////\\\||||((|\||(((|||||\|||||\\\\\\tfjjjjjftt/tfjrrrjjjffjrrrjjrxxxrxxxrrrxrrrrxnxrrjjjrrrjjjjrrxxrjfffffjfffffff
CCJUYYYYUJCCCJJCCCCJJJJJJJJJJJJJCCCJJJJC0w*B&okpmOOOZk8hY},;I"' !\Ca**&88#dOJJJXcYC0mh*#&B8#ahhoW&WWWW&&WMMMM#*ahhkhhaahhkkkbbkhkbbddbbkkbbkbbbbbbbbbbbddh*MMakbbbo88#mXvurft/\\\\||||()1)(|()))(((((|||||\\\\/\\\\\\||\//////ttffft////tjrjjjjjfffffftfjjffjjjrrxrjjjjjjfffjjrrjft/ttfftttfftttttffffffff
JJJUYYUUUCCCJUJJJJJJJJJJJUUUJJJCLLLCJCCCQwo%WhdwZOOOObMa0|Il!,`'...'I?\v0db0f1]??_~+--|Jk8B%Moao#W%$BB$$BBBBB%8W#**M&8&M#***#MMMWM*ahkh*#M*ahhhkkkkkkkbbkbbh*W&#ahaoM%%WqYzvxft/////\()\jxnf\()(((((|||||\\\|\\/\((|\//||\/t/\\||||\\//////ttttffft/ttffffjjfffjrrxrjft///////////\\|||\\\\\\\////\\\\\/////
000QLCCJUUUUJJUYYUJJJUUUUUJJJUJCCLLCJJJCQZh&*pZQ00QQQwohZ/Ili:^^^'''. `}xJz[<?-~~~<<+|Ch8&abbaM&%88&&W&&%$$B%&M*oo#W%WoaoM8BBBBB8MoahoM&&Mo*WM#oahhaao*#*aaoW8M*o*WWodOUvnxrft///\|()\XZdmr\xJwmJx|(|\///||(((()11)|//|()))(||(((((||\\\\\||||\\\\\//ttt//tttttftttt/\\||||((|||(||()(())(|||(((((((|\/\|||
UUJJJCCJUUUUUUUYYYYXXXYYUUYYYYUJCLLCCJJL0mhWopZQO0CUJZaopr<~+I"^^^`'.. `/UJn?<]-<<~<+[jw**oa*MW&M*akkkbh*W%B%&#*aao#&BWooM8BBBBB$%W#*aoW%8Wo*&8&888888%BB%&WWMaJjtckomJcuxrffttttt//txXQmZ0JLw*BMqOLJzxt/\\||()11))(|||(){{{1)(((((((((||((()))(((((|\\\\\\\\\\|\||||||||||))(||)1)((())1)|||((()))))(((((((
UUUYXXXXXXXYYXXXXXXXXXXYUUUUYYUJLQQQ00Zwpb#%MkwOZ0JYUZaaqtI!!^. "vmXt-<_+~~+>_\Uo&hh#WW#akbbkkbbddh*MWM#oahhoM&W##MMM**#M&8&W##M8B%&MM88888888%$$BB%B%Mpu)\X#WZUcunrftfxvXC0Zw0JUJ0ZZQYQbdZmqhk0zr/|(())1)(((()1)))))))(((()))))))))))11)(()))(((())((((((((((||||||)(||((((()(()1)(((((((())(())))))
OOZmmmwwwwwqpddbbbbkkkkkkkkkkkkao***#W&%%8B$&admOLUYJma#aLnnunxrjfjrrxxXo80x|{[_<~_~[cp88kdkkbppdkkkbddbbbbbbbkhkkkbkkhhhkbbbkkkkhhhkkhao*****oa*M&%B%W&B$$$B#wn|tJW&ZUvnrrrjffffruczx//fjjft\/ft|11rYQOLJYzcunxxjt\|(()((||||((((((((((((|||))((((((|||(()((||||||||||(((()(|((|||())()11111)((())))())1111
#MWW&&WWW#*###*o****ahbddppqqwmwwqqqqmmZZwh&&#dOCUXXJZa&%Moaaao*###MMM&%$WQnj\)[-__+1Uh88kdbbbbbbbbbbbbbbkkbbbddbbkkkbbbbbkkkkbbkkkkbbbbddbkhkbbh*W8W#hh*&B$$oOvffY#Wp0Jzvuunnnnxxrrjjfjrffrrjt/\//\|\fnvXUUYUUYzurf//\||||||||||||((())))))))(|||(((((())1)|||||||||(()))111))((())()1{{{{11)((()))))((((((
OOOO00QQQCJCCJUUUUUUYYYUUUUYYYYYYYYYYYXXYCwo8$8M*ooo###ohqOOOQQ00QLLQOda#dn(/([??_-}jq&&#bdbbbbddbbbbbbbkbbbbbbbbbbbbbbbbbbkkkkkbkkbbbbbbbbbdpddkhhhhkkkbaWB$hCx/tUW8pQUzccvnxnunnnxrxnnuuuuxffrrfffffffft////tttt///ttft////////tttt//\\\\\\((||||((||(()))||||||((((((((||()11(()))1{1(()(((((((())1)))111
YYXXXXXXXXYYUUYYXXXXYUUUUUUUUUJJJJJUUUUUJCL0wdppppqwwZ00QQLLQ00000OOZm*8hQr||)]--_?/U#$*kbddppdbbkbbbbkbbbbbbbbbbbbbbbbbbbkkbbbbbbbkkkbkbbbbbbbbbbdbkkkbpdh&$hJj\x0%%qQCYXXXcuxxnuuunnnnnnnxrrrxxxrrxxxrrrrrjjffffjjjjjjfttt//////tffffffffjjtttt/\\\\/\\\\\///\|||\\|((((||)111)(((())))1111{{{11)))))))(((
uuunuunnxnnuvvuuuvvccczzvvccccXXzzzccvvczXzzzzzzzczcvczXXYXYYXXYYUUJLmW$qc/)){]-??)YdW&kpkkbbdbbkkbbbbbbbbbbbbbbbbbbbbbbbbbbkkkbbbbbkkkkkbbkkkkkkkbbkkkkkka&$dXjjJd%WmLLJUYYzcccccvvuuuuuunnxxxnnunnxxnnxxxxnxxxrjjrxnnxrjjjjffffffjjfffttfjjttffftttfff//////tttttfftttttftt/\\/tt/\\/\||||((((|\\\\///tfff
xrjjjjjffjjjjjfffjjjjjrrrrnxrxxxxrrjrrrrjjrxrrrrrrjffjrxnnxjffrnnnxxcLM$Zx/(1[-+_[/m&MobdkkkkbbkkkkkbbbbbbbbbbbbbbbbbbkkbbdbbkkkkbbbkkkkkkkkkkkkkkkbkbkkbbkWBdXrn0hWo0JJUYXzzzccccvvvvvvvvvunnnuuunxrrrxxrrrxrrrxrrxnnxrrxnuxrjjjjffjjfttffjjjfjjrjffjrxjjjjttjjffffjjrxxxxjrrrrxxrjffjfffjftttffjjfffjjjjjj
jjjjjjjfftffjfjjjjjjjjjjffft//fffjjfftttfjjjt//tfjfffjjrrjffjjrrrrxxuU*B0f\()}?-](nbB#kkkhhhkkkkkkkkbbbbbbbbbbbbbbbbbbkhkdddbkhkkbbkkkkkbbbbbkkkkbbbkhhkbbkWBdXrxOa#hQUYzvccccvuuuuunuuuvvunnnnnnnnnnnxxxnnnxrrxxnxxrjjjrxnnnnxxxxrrrrrjfjrxxrrxxxxjjrxxrjrrffjjjjjrrrxxxrjfjxxrxxxrjjrrjxxxrjjjjjjjjjjjjjjj
ffttffffffffffffjjjjjfff//tt//tfffffft////tft//ttfffffrrrjjrxxxrrnnncC#BQt(11[--[tUo$Mkhhhkbbbbkkkkkkbbkkkkkkkkkkkkkkkkkbbbbkkkkbbbkkkkkkbbbbkkkkbbbbbkkdba&$pcfrZo#kQJUXcvvunxnuunnxxxxnnxxxxxxxxnuuunnnnnnrrxnnnxxxxxxxxnnuunxnnnnxxrrrrrrrxxxxxxrrxrrrrnuuuunnnnnnnnuunrjrnnnxxnnxxxxxxxxxrrrjjjrrjjjjjjj
tt/tttftttffffffftttttff//////ttttttffffffffjjfffffffjrxnuuuuuuvvuuuUm&BQft|{]__[r0#B*bkhkkbddbkhhkkbkkkkkkkkkkkkkkkkkbbbkkkkkbbbbkkkkkkkkkkkkkkkkkbbbkkbbh&$pcjnq#MkLYYzvunnnnnuuvuunnuuuunnuuuunnuunnnnxrrrnuvvuuuvcvvuuvvuunuuvccvuuvvvvuuuuuuuuvvunxrxnuuunnnuvunxxnnnnnnuunxxxnnxrrrrrxxxrjjrxnnnnxxxxx
fttt//////ttfffjjtttjjjffjxxxrjjjjfjrrxxnunnnnuuuxjjrxnuunxnuvvvuvuvQb#az||)[--?1vqM%obbkhhkkkkkkkkkkkkkkkbbbbbbkkkkkkkkkkkkhhkkkkkkkbbbbbbbkkkkkkkkbbkkkkkW$bUnuZoWhCXzccvuvuuunnvvvunuvvuuuvuxrxuvunuunxrrrxnuuuuunnnnuvvuxrrrxnuuuuuuuuuvvvvvvvvvvvunxxxnnnnxxxxxxnnnnnnnuuunnxrxnnnxxnuunxxuvcvuuvuuuvvv
///\\\\//tffffjrrrrrjjjjrrjjrjjjrrrrrrrxxxxxxnnnxrjjxxxnnnnnnnuvuunvQkhqu|\|}?][(UaMMakhhhhhhhkkkkkkkkkkkkkbbbbbkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkbbbkkbbW$kUxrCbWoLXXzccvuuuuuuvvuuuuvvunnunrjjrxnnxxnxxxxnnnuxrrrxnnxrrrxxxxrrxnnxxrjjjrxrrxxnnuuuunxxnnnnnnnxxxxnnnxxxnnnnxnnxxnunxxxnnnrrnuuunnuuuuuuu
\\\/ttttt////ttffjjjftffjf//tttttfjjjjjfffjrrrftfjjrrjjrxrrxnxxrxxxv0hhZt-1)}?-]|C#W#kdkkbbkkkkkkkkkbbbkhhkkkkbbbbbkkkkkkkbbbbbbkkkkkkkkkkkkkkbbbbbbbkkkkkhW$hCnn0a8oLXXcvvunnnnnnnnxnnnnunrrnnxrrrxnnxrxrjjrjjjjjrrxxxxxrrxxxjjrxuunxxnnxrrjrrrrrrxnnnxxrxxxxnnnnnnnnuunxnunxrjrxxxnxxxrrrxnnxxxrjjrnnnnuuu
ffffffffffffftfjrrrrrxnnxrxxxrjffjxxxxnxxxnuunrfjjxrjfffjjruvxrjjxxnLkhmt-)(}]??{nmW$#kkkbbkkkkkkkbbbbbbhhhkkkkbbbbkkkkkkkkkbbbbbbkkkkkkkkkkkkkkbbbkkkkkkkh&$aQuuZaMkYvcuxnnxrrrxnnxrjjjjxnrjrjjjrjfjjjrxjttjjjjjjjrrjjfffjjrrjffrnnnnnuunxxxxxnnnnuuunxrrxxxxxnnnxxxxxxxrxxrjt/tfffjjfjjjjrrxxrjjrrxnnnnnnn
nxxrrrrxxxrjjfjxxxrxnnnxxxnxxrrrxxxxrxxnnnnnxxxxxxnnxxxrrxnuunnuunxnYwMWU|(1}[[-~]tOM8WkdkhkkkkkkkkkkkkkkkkkkkkbbkkkkhkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkhkbdkMB*mzvZa#bXvcuxnnnxxxnnxrjjjjjxxrjjrrxnxjjrxxxrjjxxxxrxxxxxxrrrrrrrxxrrrrjjjrrrrxxjfffttffjffttfffffjjjjjjfffjjrrrjttffffffffjffjrrrrjffjjjrrjjjj
xxnnuuunnnnnnunxxxnnnxxxnnnnnnvvunxxnnnnnnnxxrnnnnnnxxnnnnuxxnuvuxrjxzp*qYt)(1]-_+?/Y*$&ohkkkkkkkkkkkkkkbbkkkkkbbkkhhhhkkkkkhhhkkkkkkkkkkkkkkkkhhhhhkkhhkka&BoZvnOhMbYcXvxxnxrrjjjrjfftffjjfftfrxxrjffjjftttjjjftfffffjjjrrrrrrrrrjjjjjjjrrrrjjjffffffftttfft/////tt/\\\/ft/tt//ttt/t/////tttffffffjffffjjjj
On path-likes
@TamoghnaChowdhury suggests
taking path
as an actual pathlib.Path
instead of as a str
, at least for the purposes of the type hint. Maybe even path: pathlib.Path | str
to shut the type checker up (I'm not sure where you can get the type annotation PathLike
from)?
You can use os.PathLike
. However, if we were to abide by the protocol of the inner open()
call, then a PathLike
is incorrect, because it can also take a file-like:
:param fp: A filename (string), pathlib.Path object or a file object.
The file object must implement ``file.read``,
``file.seek``, and ``file.tell`` methods,
and be opened in binary mode.
But I consider all of that to be a bit much for this application, and would constrain it to PathLike
for simplicity and clarity.
Simplified algorithm
I don't think you need to bisect. You can simply load the image in 'F'
mode (32-bit floating-point), scale to your min and max, round to the nearest index and then index into your charset. You can take the opportunity to improve Numpy vectorisation and eliminate your loops.
from os import PathLike
from pathlib import Path
import PIL.Image
import numpy as np
CHARSET = (
"@$B%8&WM#*oahkbdpqwm"
"ZO0QLCJUYXzcvunxrjft"
"/\|()1{}[]?-_+~<>i!l"
"I;:,\"^`'. "
)
def resize(image: PIL.Image.Image, new_width: int = 300) -> PIL.Image.Image:
width, height = image.size
new_height = new_width * height / width / 2.5
return image.resize((round(new_width), round(new_height)))
def pixel_to_ascii(pixels: np.ndarray, light_mode: bool = True) -> str:
direction = 1 if light_mode else -1
charset_str = CHARSET[::direction]
charset = np.array(tuple(charset_str), dtype='U1')
minp = pixels.min()
maxp = pixels.max()
scaled = (pixels - minp) / (maxp - minp) * (len(CHARSET) - 1)
indices = np.around(scaled).astype(int)
ascii_array = charset[indices]
rows = ascii_array.view(f'U{pixels.shape[1]}')[:, 0]
return '\n'.join(rows)
def convert(path: PathLike) -> str:
greyscale_image = resize(PIL.Image.open(path).convert('F'))
return pixel_to_ascii(np.array(greyscale_image))
def main() -> None:
ascii_img = convert('archived/image2l.png')
print(ascii_img)
if __name__ == '__main__':
main()
if __name__='main'
andformat(n ame)
) \$\endgroup\$