9
\$\begingroup\$

I made a python script that takes an image and converts it into an ASCII-art representation and saves it as a .txt file. The logic is somewhat simple. It resizes the image to a manageable size, converts it to gray-scale, takes the value of each pixel and assigns it a character according to it. Then appends the characters to a string and wrap it to the number of pixels of width. Can this be improved in any way? Does it follows conventions and best practices?

import PIL.Image image=None def closest(myList, myNumber): from bisect import bisect_left pos=bisect_left(myList, myNumber) if pos==0: return myList[0] if pos==len(myList): return myList[-1] before=myList[pos-1] after=myList[pos] if after-myNumber<myNumber-before: return after else: return before def resize(image,new_width=300): width,height=image.size new_height=int((new_width*height/width)/2.5) return image.resize((int(round(new_width)), int(round(new_height)))) def to_greyscale(image): return image.convert("L") def pixel_to_ascii(image): pixels=image.getdata() a=list("@$B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. "[::-1]) #remove the slice to get light mode pixlist=list(pixels) minp=min(pixlist) maxp=max(pixlist) vals=[] lst=list(range(minp,maxp+1)) def chunks(lst,n): import numpy as np return np.array_split(lst,n) lchunks=list(chunks(lst,len(a))) for chunk in lchunks: vals.append(chunk[0]) avals={vals[i]:a[i] for i in range(len(vals))} ascii_str=""; for pixel in pixels: ascii_str+=avals[closest(vals,pixel)]; return ascii_str if __name__='main' path=#drop your path here image=PIL.Image.open(path) name=input("enter the image name here: ") 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" with open("{}.txt".format(n ame), "w") as f: f.write(ascii_img); print(ascii_img) 
\$\endgroup\$
1
  • 5
    \$\begingroup\$Dumping your code through Black will give instant benefits! (as well as find a few syntax errors like if __name__='main' and format(n ame))\$\endgroup\$
    – ggorlen
    CommentedAug 4, 2022 at 0:25

1 Answer 1

9
\$\begingroup\$

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() 
\$\endgroup\$
5
  • \$\begingroup\$The use of light_mode is pretty clever. I didn't thought of doing that.\$\endgroup\$CommentedAug 4, 2022 at 2:30
  • \$\begingroup\$What do the "arrows" means? (The parts that do ->something outside of a function) I've seen them a lot but I have no idea what they are\$\endgroup\$CommentedAug 4, 2022 at 2:32
  • 2
    \$\begingroup\$Return value type hints\$\endgroup\$CommentedAug 4, 2022 at 2:54
  • 1
    \$\begingroup\$I'd suggest taking path as an actual pathlib.Path instead of as an 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)?\$\endgroup\$CommentedAug 4, 2022 at 13:11
  • 1
    \$\begingroup\$@TamoghnaChowdhury See edit.\$\endgroup\$CommentedAug 4, 2022 at 20:48

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.