Aller au contenu

Conversion de l'image en ASCII

Maintenant qu'on a une image en nuances de gris et aux dimensions voulues, on peut la convertir en chaîne.

Conversion d'un pixel

On doit faire correspondre chaque valeur possible d'un pixel, de 0 à 255, à un caractère. Plusieurs valeurs d'un pixel peuvent correspondre au même caractère.

Pour ça, on peut créer une chaîne de 256 caractères ou plus. Dans cette chaîne, le caractère correspondant à une valeur de pixel de \(n\) se trouve en position \(n\).

Voici un exemple de 1 à 8.

chaine = "@#OO*-. "

Si l'on veut le caractère correspondant à un pixel de valeur 6, on fait chaine[6].

Comme on n'a pas trop envie de devoir spécifier les 256 caractères de la chaîne à la main, on doit représenter la chaîne d'une manière plus concise. Comme des caractères peuvent se répéter, et que la plupart des caractères vont se répéter beaucoup de fois dans la chaîne, on va représenter la chaîne sous forme d'une liste de tuples (str, int).

Chaque tuple représente, dans l'ordre de la liste, un caractère et le nombre de fois qu'il apparaît dans la liste à cette positino. Par exemple, pour représenter la chaîne de 8 caractères présentés plus haut, on a la liste suivante :

repr_chaine = [
    ("@", 1),
    ("#", 1),
    ("0", 2),
    ("*", 1),
    ("-", 1),
    (".", 1),
    (" ", 1)
]

Activité

Implémentez la fonction suivante

def repr_vers_chaine(l):
    """l une liste de tuples (str, int), qui représente la chaîne en spécifiant combien de fois (>0) chaque caractère est répété à sa position.
    retourne la chaîne correspondante.  

    >>> repr_vers_chaine([("@", 1), ("b", 1)])
    '@b'
    """
    pass

Ajoutez également quelques tests !

  • Il vous faut utiliser une boucle for.
  • Pour accéder à un élément d'un tuple, utilisez l'opérateur [].
  • L'opérateur * entre un entier et une chaîne permet de répéter la chaîne : "a" * 3 vaut `"aaa".
def repr_vers_chaine(l):
    """l une liste de tuples (str, int), qui représente la chaîne en spécifiant combien de fois (>0) chaque caractère est répété à sa position.
    retourne la chaîne correspondante.  

    >>> repr_vers_chaine([("@", 1), ("b", 1)])
    '@b'

    (Vos tests ici)
    """
    chaine = ""
    for c in l :
        chaine += c[0] * c[1]
    return chaine

Conversion de l'image

Pour convertir l'image, on parcours chaque pixel, ligne par ligne, et on l'ajoute son caractère correspondant à une chaîne initialement vide. Quand on change de ligne, on ajoute un caractère de retour à la ligne à la chaîne.

Pour accéder à un pixel en position (x, y) dans une image, on utilise la méthode getpixel, qui prends en paramètre un tuple d'entiers naturels (x, y) et retourne la valeur du pixel à cette position. Dans le cas d'une image en nuances de gris obtenue avec convert("L"), cette valeur est un entier entre 0 et 255.

Voici un code (autonome, à exécuter dans un fichier à part), qui charge l'image chien, la désature, la redimensionne en 10px par 10px, et affiche la valeur et la position de chaque pixel, ligne par ligne.

from PIL import Image

img = Image.open("chien.jpg")
img = img.convert("L")
img = img.resize((10, 10))
taille = img.size

for y in range(taille[1]):
    for x in range(taille[0]):
        print((x, y), ":", img.getpixel((x, y)))

Activité

Inspirez vous des deux boucles for du code précédent for pour implémenter la fonction suivante.

def image_vers_chaine(img, conv):
    """img une image PIL en nuances de gris
    conv une chaine de caractères d'au moins 256 caractères de long. 
    retourne une chaine qui représente l'image, où chaque pixel de valeur n est remplacé par le caractère en position n dans la chaîne conv.
    """
    pass

Modifiez ensuite la fonction main de manière à pouvoir vérifier manuellement que cette fonction produit le bon résultat. Vous aurez sans aucun doute besoin de la fonction repr_vers_chaine.

Il vous faut déclarer une chaîne vide, puis y ajouter un caractère correspondant à chaque pixel. N'oubliez pas d'ajouter des retour à la ligne, c'est le caractère "\n".

Dans la fonction main, appelez image_vers_chaine en lui passant l'image, et la chaîne obtenue en appelant repr_vers_chaine sur la représentation suivante :

repr_chaine = [
    ("@", 40),
    ("#", 40),
    ("0", 40),
    ("*", 40),
    ("-", 40),
    (".", 40),
    (" ", 40)]

Affichez la chaine retournée par image_vers_chaine au lieu d'afficher l'image.

def image_vers_chaine(img, conv):
    """img une image PIL en nuances de gris
    conv une chaine de caractères d'au moins 256 caractères de long. 
    retourne une chaine qui représente l'image, où chaque pixel de valeur n est remplacé par le caractère en position n dans la chaîne conv.
    """
    chaine = ""
    taille = img.size
    for y in range(taille[1]):
        for x in range(taille[0]):
            chaine += conv[img.getpixel((x, y))]
        chaine += "\n"
    return chaine
def main():
    img = Image.open("chien.jpg")
    img = img.convert("L")
    taille = img.size
    nouvelle_taille = nouvelles_dimensions(100, taille)
    img = img.resize(nouvelle_taille)

    repr_chaine = [
        ("@", 40),
        ("#", 40),
        ("0", 40),
        ("*", 40),
        ("-", 40),
        (".", 40),
        (" ", 40)]

    conv = repr_vers_chaine(repr_chaine)
    chaine = image_vers_chaine(img, conv)

    print(chaine)
from PIL import Image
lancer_main = True

def nouvelles_dimensions(l, d):
    """l un entier > 0, la nouvelle largeur voulue pour l'image
    d un tuple d'entiers (l1, h1), respectivement la largeur et la hauteur de l'image 
    retourne les nouvelles dimensions pour l'image, telles que la largeur soit l, et que le rapport de forme soit préservé

    >>> nouvelles_dimensions(500, (1000, 1000))
    (500, 500)

    >>> nouvelles_dimensions(1000, (500, 1000))
    (1000, 2000)

    >>> nouvelles_dimensions(400, (1200, 300))
    (400, 100)

    >>> nouvelles_dimensions(1000, (1920, 1080))
    (1000, 562)
    """
    l1 = d[0]
    h1 = d[1]
    ratio = l1/h1
    return (int(l), int(l / ratio))

def repr_vers_chaine(l):
    """l une liste de tuples (str, int), qui représente la chaîne en spécifiant combien de fois (>0) chaque caractère est répété à sa position.
    retourne la chaîne correspondante.  

    >>> repr_vers_chaine([("@", 1), ("b", 1)])
    '@b'

    (Vos tests ici)
    """
    chaine = ""
    for c in l :
        chaine += c[0] * c[1]
    return chaine

def image_vers_chaine(img, conv):
    """img une image PIL en nuances de gris
    conv une chaine de caractères d'au moins 256 caractères de long. 
    retourne une chaine qui représente l'image, où chaque pixel de valeur n est remplacé par le caractère en position n dans la chaîne conv.
    """
    chaine = ""
    taille = img.size
    for y in range(taille[1]):
        for x in range(taille[0]):
            chaine += conv[img.getpixel((x, y))]
        chaine += "\n"
    return chaine

def main():
    img = Image.open("chien.jpg")
    img = img.convert("L")
    taille = img.size
    nouvelle_taille = nouvelles_dimensions(100, taille)
    img = img.resize(nouvelle_taille)

    repr_chaine = [
        ("@", 40),
        ("#", 40),
        ("0", 40),
        ("*", 40),
        ("-", 40),
        (".", 40),
        (" ", 40)]

    conv = repr_vers_chaine(repr_chaine)
    chaine = image_vers_chaine(img, conv)

    print(chaine)

# Ces deux lignes permettent de lancer les doctest
import doctest
doctest.testmod()

if __name__ == "__main__" and lancer_main:
    main()

Vous devriez obtenir, au final, une image comme suit :

@@#####@@####00000000#####000*000#####000#######000000##000***---------*00##############@@###0***0#@
@@###########0000000#####0000*000####0000#######00****00000****-------**00####################0**0##
@@###########00000#######00000000####0000######00***************------***00###################0***0#
@######0***0#############000000000#############0***----******0***-----***00###################0***0#
####000*****0#############00000000#############*----------*******-----**000####################0***0
###000*******###############00000000########000.**---------******----***000####################0*-*0
###000*******##################00000**0####000*-***--*-----*******---***000####################0*--*
###000*****-*##################0000*.**0#00000**----********************00######################*--*
0#00000*-*-*000#####@@###00####0000-0***0#00##-*---*-*******************00######################*---
0000000****00000###@@@###000###000***--**00###----*--*000000000000*****000######################0---
00***000000000000##@@@####00####00-*-----0####**-**--*##########000000*000######################0---
*************00000#@@@###########0-*-*---*###0-*-00*--#############000000######@@###############0*--
*************00000#@@@###########*-****---##0--*-00*--##@@@@##################@@@@##############0*--
-****----****00000##############*.*****-----..-*-00*-.#@@###################@@@@@@##############0*--
--*****--**0000000#############0..**00*---.--.*--00*-.0@###############@@@@@@@@@@@@##0000#######0**-
--******-**0**00000000######00*-.--0#0*-**--*****00*-.*##########0####@@@@@@@##@@@@##0000########0**
---*******00*00**0**0*0000000*-. .-###*--00**00000#0*-*0000####0000###@@@@@@@#@@@@@###0000#######000
---******00000***************-. ..-##0*-0###000000##0*-*0000###00000####@@@@##@@######0000#########0
.---***0000000****-----****-..  ---#@0**#####0****000*--0000####00000####@@###########00000########0
----*000###000***------***--.   -*-0#0*0######0******0*-0000#####0000##################0000########0
---**######000***------***-.    -**0#000########00*-*00*-*0################000###00#####000########0
---*0#######0000**-----*-... ...--*00000####000###0*-*00-*0###############000000000000#00000#######0
--**#########000**---**-.. .....--*000#####00000###*--*0**0###############0000000000000000000000###0
-**0#@#@##0000000**--*-..  ....--*##0##@###0*****##*-.-0#*0##0#####@#@####00*0000000000000**--**0##0
**0####@##00000000**--..   ..-..*#@###@@###0-----0#*-.-0#00##00####@@@@@##00000000**000000**--**0##0
**0######000000000**-..    ... .0@@##@@@###*---.-*#*-.-0#00#######@@@@@@@#00000000****0000*---**###0
**00#####000000000**-.     ....-0@@@@@@@###0----.-#*---*0*0######@@@@@@@@##0000000****0000*---*0###0
***00###0000000000*-.      ....-0#@@@@@@@@#0------0*--**-*0#####@@@@@@@@@###00##00***00000*---*0###0
****0000000***0000*-.      .-.-*0#@@@@@@@#0--**---**.-#*.*#######@@@@@@@@@#####000***00000----*0#000
*****000000***000**.      ..---*0##@@@@#00*0#@#*---*--#*.0#########@@@@@@@######00000*000*----*00000
******0000****00**-.      .---**0**000*---#@##@0--.*--*-.0######################00000000**----*00000
*******0*00000****-.     ..-****-----------0###0--.-*-.-.*####################000000000***---****000
***********00****-.      ..-***-------------------..---..*#@##################000000000*----******0*
********0000****--.      ..-**--------------------...---.*#@################00000000**0*---*********
*******0000****--..    ....-**-------------------...------0@@#####@@@#######0000000*******-*0*******
*******0000****-...    ....***-------------...---.---------0######@@@@@######000000********00*******
******0000***----..    ....-**-------------....-....----*0000#####@@@@@@@####000000****0000000*****0
***00000*******---.    ....-**-------------...--.....---0###00#####@@@@@@###0000000****0000000*****0
***0000***-******--. .. . .-*0*-----------------....---*###@######@@@@######0000##00**00****0******0
***00******---*00**........-*0*------------------.-----*##@@######@@@##00##000000000000*************
***************000*-.......-000*-------------..--------*0####00###@@##000000000****000***--*********
*****000*****--000*-.--...--*00*-------**-------------**00###*000###00000**00**---**000**--****-****
*****0000***---*00**------**0##0*------------**-------**0###0*0*00#0000*******-----00000*****---****
00000#####00**--********0**00###0**----------***-----**00##0*00000000*********-----0##0000**----****
00#####@@@@#00**-*0****00#00000000**------------*****000##00000000000*********----*00###000*----**--
####00##@@@@@#0*-***--**0########00***-*****************0**00000000000*********---*0000000*-----**--
###0*-*0@@@@@@#0*****-***0#@@#####00************------*000000**0000000****0*****--****-****----***--
@##0*--*0@@@@@@@#0**---**0#@@@#####000*********------*000000****000##000000*********-----**-----***-
@@#0*--**#@@@@@@@#***--**00#@@@#####00*********-----*000000**---*0####00000*******---...---------***
@@#0*---*0#@@@@@@@0*--****0#@@@@####000**********--*0000000**---*0####00000***00*--.....----------**
@#0**----*#@@@@@@@#0*-*-**00#@@@@@###000********--**0000000**----*####0000****00*--.....-----------*
@#00**----0@@@@@@@@#*******00#@@@@@###00*****-----********------*0###00**********-.....------------*
@#00**----*#@@@@@@@@#******00##@@@@@##00****------**--*--..-----*0###*-----******-----.----------***
##00***---*0@@@@@@@@@#0****0000#@@@####000**-------*----....----**00*--------*--*-----......-----***
#00****---**@@@@@@@@@@#0********0#@@#00#00**---------.......-----***-...-------------.......-----***
000****---**#@@@@@@@@@@#0*****--*00###000**-----------......------**-...-------------.......-*----**
#000****---**#@@@@@@@@@@#0*****---*0###00*------------.......----***--.--------------.....--**------
0000*****---*0@@@@@@@@@@@#00***-----*000**------------.......----**-----**------------...--*0**-----
00000*****--**#@@@@@@@@@@@##00**-----*00***------------.....----***----****-----------...--*00***---
00000*****---*0@@@@@@@@@@@@@#00*-----*0000**-----------...------***----***-------------...-*00****--
000000****---*0@@@@@@@@@@@@@@#00*-----*0#0**---------------*-...-**----**------**------...-000*****-
0000000****--*0#@@@@@@@#@@@@@@#00*-----*00**---------**---**.....--------------*-------..-*00**-****
0000000****---*0@@@@@@@##@@@@@@#0**----*0**-----------*****-.....--------------*----------000*---***
0000000****-***0#@@@@@###########0**----*-------------------.......------**---**---------*00*----***
#####000********#@@@@@########0##00*----------------------..........----*00***0**------****--..-****
#####000********#@@@@@########00000**-------------------....-----...---*00000##0***--.------...-***0

On y devine à peine le chien. Essayez avec l'image de Marie Curie utilisée dans la présentation du projet :

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@####@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#@#@########@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@######0****00000#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@####0*****--****0###@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#@@@@@##0**--*********-*000#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#@###0*------*-******0*0#######@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@###0---.----******000**000000#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@##*-.------*****00********0*0###@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@###0-.-.-----*****000**-**000000###@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@##0*-.-------*0*000000**--*00000#0###@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@#00--.-------*00*00#00000******00#000###@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@#0*--.------***000#00#0000##0****00##0####@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@##*-..---******00####0000##00*00**000000##0#@@@#@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@##0-.....--*0*000#000**00##000000**0*****##000##@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@##0-......-***0******000000000000*0*-**-*##0--0#@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@#0*-......--***********00**000*00000*--***00-.*###@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@#*---....----------***000**0#00000000--***0**--0#@#@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@#0*-......----....--***00000000000000**---**0*-.*#@#@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@#0*-......--.......----**00000000##0*00*--***---*###@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@#00*..................---***0*000*****00**000*-*--###@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@###-..................--------*****0***--*000**---0##@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@#####-.....  .  ............-----*----**---*000**----##@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@###0......         .............----------*000*00*-.*###@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@##*.....         ................-----**--00###0*-.*0###@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@##0-....       .. ................-----**0-*0000**-.*###@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@##0-....         .................------*0*********.*##@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@##*-. ..      ...................-------*0*****-**-.-##@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@####0-. ..    . .................--------**000**---*-.-00#@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@###00*-. ..    ..................----------*000*-**---.-*0###@@@@@@@@@@@@@@@@@@@@
#@@@@@@@@@@@@@@@@@@@##0**-.  .     .  ..............---------***00*------.-*0##@@@@@@@@@@@@@@@@@@@@@
#@@@@@@@@@@@@@@@@@@@@##0*-.  ..        .............-------*****000-.----.-**0#@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@##00-.  ..       ............---------*****000*-------*00#@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@##***.....      ..........-------------*00**000**-----**###@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@##0**.....     .........--------....---**000000****---00####@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@##00*-....    ....-----------.---.....--**00000*000*-*000###@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@###0*-... .....---------------------..--*00000*000***00#####@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@##00*-. ...-*******--****0000*****------***00000**--000###@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@####*-...-**000000*--*00#######000***----**000000*--0#####@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@#0*-..-*0###@@00*-**0#####@@####000**---**00#0*****00###@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@#0**-..-0#000###0*--*000##@#######0000*---*000********00#@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@##0**-..-0#00#@@#0*..-*00####0@@@###0#0-----*00******00*0#@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@#00***-. .**--###00-...**00##0-0#0*0##00-----*000000000000###@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@##*****-.  ...--****. ..-*000**--*-**00*------**00##00#0000###@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@#0*0***-.    .-----.  ..--****---***----..----**00##000000####@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@##0000*--.  .  .....   ..---***---------...----*000#0*0000#####@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@##0000**-.  .  ....    ..---****-------....----*00*00*0#00####@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@###000**-.   ......    ..----***------....----**000***###00###@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@###0***.  ......     ..--***-------..----*-**00#0-**#######@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@##000*. ......      ..-*****----------******00#**-0########@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@##0000....... ...  ...-*-***-------********00##0**0#######@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@##000-.......... ..-----*0*------********000#00*0#####@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@###00*........-..--***00*00*-----*******0000#000@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@###0*.......---*-00##@@#00**-----*****0000#@#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@##00-.....---..-*#@@@@0*****---*****00000###@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@###0*.....---....0###0*--**********000000#####@@@@@#@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@#00*....---... .-**0**--*********0000000######@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@#000-...--......---****-*****0**0000000##@##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@#00*...--.-.  .-.---******000000000000###@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@###0......*--**--0****0***000*0000000#0#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@####-....*#**0###@@@###000*****00000#000#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@###0...-0-  ..-******0##0*****0000##000@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@##@#...--...-----******00****0000###0**#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#@@@*.......*0000000********0000###00**#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#.......-*000********000000####00***#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@0........------*****0000###@#000****#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*...........--*****000##@@@#000**-*#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@0-.......----****0###@@@###000**-*##@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@0-....---****00##@@@@@####00**--0#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#0----***000###@@@@@@@###000****00@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@###***00#####@@@@@@@@@####000**00**@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@####*0*--0######@##@@@###0000**0#@@#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@####0*@0..-*0########@@##0000000##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@####--##-..-*0##########0000000##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@####0.-#@*..-*00########0000000-0@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@######0-0@@0...-*000####000000#0-.-#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@######0*#@@#-..--*0000000000000000###@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@######**#@@#-..--***0000***00*0#@@@##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@######.-#@@@*..--*********00--#@@@@#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@######-*#@@@*-..-*******-0#*-*#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@####@#-0@@@@0-..--***---0##**0@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@#@@@@@@###@@#-0@@#@0-..------*####0*0@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@##@@@@@@###@@0-0#00##-..---..*00**00000#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@#@@@@@@@@@##@@@@@@##@@@*..--*0#*...-****-.-*@@@@##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@#@@@@@@@@@@@@@@@@@##@@#---*0####*...0@##0--0@@@@@#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@#@@@@@@@@@@@@@#@@###@@#0@@@@@@@@@0-.-#@#0--#@@@@@#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@##@@@@@@@@@@@@@@@@##@@##@@@@@@@@@@@@#*0@@@00#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@##@@##@@@@@@@@@@@@##@@@@@@@@@@@@@@@@@@#*0@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@###@@##@@@@@@@@@@@@@@@@@@##@@@@@@@@@###*.*##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@###@###@@@@@@@@@@@@@@@@@@@@@@@@@@@@@##0-.*0#@@@##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@###@@@#@@@@@@@@@@@@@@@@@@@@@@@@@@@@##@#*.*0#@##0#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@#@@@#@@@@@@@@@@@@@@@@@@@@@@@@@@@@000@@@#*0#@@@00@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@#@@@##@@@@@@@@@@@@@@@@@@@@@@@@@@0--0#@@#--*0@@*#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
@@@@@@@@@@@#@@@@##@@@@@@@@@@@@@@@@@@@@@@@@@0--00##*..-#@#0@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
@@@@@@@@@@@@@@@@##@@@@@@@@@@@@@@@@@@@@@@@@#0*-000*..-0@@0#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@##@@@@@@@@@@@@@@@@@@@@@@@@@#00----.-*0@@##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@##@@@@@@@@@@@@@@@@@@@@@@@@@@#*-....-*#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@###@@@@@@@@@@@@##@@@@@0*... .**#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@##@@@@@@@@@@@@##@@@@@#--**--0#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@#@@@@@@@@@@@#####@@@@0-*#00-*#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@######@@@#..0##0-.-#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#####@@@#--0#0*..-#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@####@@@#--0#0*.-0#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@##@@@@@0-000**#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@0.----0@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@0..-.-0@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@0.----#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@00###0#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@####@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#0#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Ca ressemble un peu, mais c'est pas encore ça !

Améliorer cette sortie sera le travail d'extension, présentées au chapitre suivant. Vous devez faire au minimum deux extensions !