from PIL import Image
import numpy as np

'''
Modifiez les variables ci-dessous pour obtenir des résultats différents. Le projet est séparé en deux fichiers : celui-ci et core/asciizer.py. Ce dernier sert à 
la conversion des images classiques en images ASCII.
Tous les essais seront générés dans le dossier "out". Les images servant de résultat pour l'évaluation sont dans le dossier "résultats".

IMG: Le chemin jusqu'à l'image à modifier.

SCALE: Le facteur de redimensionnement de l'image, en deux dimensions. Pour la plupart des éditeurs de texte, une ligne fait deux fois la longueur d'un caractère.

CHAR_SET: La chaîne de caractères à utiliser, dans l'ordre de la couleur la plus sombre à la couleur la plus claire. La valeur peut être soit le nom d'une chaîne 
de caractères définie dans core/asciizer.py, soit une chaîne de caractères déjà définie.
Si un nom de chaîne de caractère est donné, placer ".reverse" à la fin inversera l'ordre des caractères.
Les noms de chaîne possibles sont: "classic", "alphabetic", "mathematic", "blocks" et "binary".
'''


modes = {
    "blocks": "█▓▒░ ",
    "classic": "$@B%8&W#*oahkdqmZ0QLCJUYXzcvunxrjft/|(1{[?-_+~<i!lI;:,\"^`'. ",}


class ImageAscii:
    def __init__(self, data: str = "", size: tuple = (0, 0), char_set: str = "", char_set_content: str = ""):
        self.data = data
        self.size = size
        self.char_set = char_set
        self.char_set_content = char_set_content

def makeAscii(img: Image.Image, scale: tuple = (0.2, 0.1), char_set: str = "classic") -> ImageAscii:
    result = ImageAscii()
    img = img.convert("RGB").resize((int(img.width * scale[0]), int(img.height * scale[1]))) # Cette ligne permet d'entrer l'image
    result.size = img.size

    data = ""
    pixels = np.array(img) # On definit une liste (numpy) contenant chaque pixels de l'image-source, ce qui est plus optimisé que "img.getpixel()"

    for y in range (img.height):
        for x in range(img.width):
            color = pixels[y, x]
            gris = (int(color[0]) + int(color[1]) + int(color[2]))/3 # On converti les unicode-int(base 8) en int simple pour éviter les Overflow

            data += char_set[int(gris //(256 / (len(char_set))))]
        data += "\n" # Retourne à la ligne
    result.data = data
    
    return result

IMAGE: str = "modifyme.png"
SCALE: tuple = (0.4, 0.2)
CHAR_SET: str = "blocks"

if __name__ == "__main__":
    img = makeAscii(Image.open(IMAGE), SCALE, CHAR_SET)
    output_name = IMAGE.split("/")[-1].split("\\")[-1].split(".") # On récupère le nom et l'extension du fichier dans une liste
    file = open(f"out/{output_name[0]}-{img.size[0]}x{img.size[1]}_{img.char_set}.txt", "w") # On ouvre un fichier (ou on en crée un s'il n'existe pas)
    file.write(img.data) # On y écrit les caractères de l'image ASCII
    file.close() # On sauvegarde le fichier
