Vous êtes sur la page 1sur 3

from PIL import Image

import numpy as np

#une liste de tuples où chaque tuple représente un caractère ASCII et le nombre de pixels associés à
ce caractère dans une image. Les tuples sont triés en fonction du nombre de pixels

pixelsPerChar = [(32,0),(33,37),(34,51),(35,98),(36,87),(37,88),(38,71),(39,25),(40,42),

(41,48),(42,44),(43,46),(44,26),(45,24),(46,15),(47,44),(48,80),(49,49),(50,72),(51,69),

(52,71),(53,74),(54,84),(55,50),(56,93),(57,83),(58,30),(59,44),(60,50),(61,39),(62,52),

(63,56),(64,98),(65,83),(66,92),(67,71),(68,78),(69,87),(70,77),(71,83),(72,85),(73,52),

(74,62),(75,94),(76,55),(77,105),(78,100),(79,82),(80,73),(81,102),(82,88),(83,86),

(84,62),(85,82),(86,74),(87,109),(88,88),(89,67),(90,74),(91,47),(92,43),(93,47),(94,32),

(95,28),(96,15),(97,78),(98,88),(99,66),(100,91),(101,82),(102,62),(103,81),(104,72),

(105,42),(106,51),(107,77),(108,45),(109,87),(110,60),(111,67),(112,80),(113,85),

(114,50),(115,70),(116,58),(117,64),(118,61),(119,78),(120,75),(121,65),(122,61),

(123,49),(124,36),(125,48),(126,28)]

pixelsPerChar = [(32,0),(65,83),(73,52),(87,109)]

pixelsPerChar.sort(key=lambda y: y[1])

maxPixelsPerChar = 109 #valeur maximale de pixels par caractère

def charForLight(light): # prend en entrée un niveau de luminosité light et renvoie le caractère ASCII

correspondant à ce niveau de luminosité.

n_light = light/255 # 0..1 #Normalise la luminosité à une échelle de 0 à 1.

minDiff = 1 # réglé au max possible par défaut

c = " " # Initialise la variable c à un espace, qui est le caractère par défaut

for asciii,pixels in pixelsPerChar: #itère sur chaque tuple de pixelsPerChar

n_pixels = 1 - pixels/maxPixelsPerChar # 0..1 #Normalise le nombre de pixels à une


échelle de 0 à 1.

if abs(n_light-n_pixels) < minDiff: #vérifie si la différence entre la luminosité


normalisée et le nombre de pixels normalisé est inférieure à minDiff.

minDiff = abs(n_light-n_pixels) #Si la condition est vraie, met à jour minDiff


et c avec les valeurs actuelles.

c = chr(asciii)
return c # Retourne le caractère correspondant à la luminosité minimale différentielle

print(charForLight(255)) # " " #impriment le caractère correspondant à une luminosité de 255, 127
et 0 respectivement.

print(charForLight(127)) # "L"

print(charForLight(0) ) # "W"

#prend le nom de fichier d'une image, le nom de fichier de texte de sortie, la taille des blocs,

# et le type de sortie (texte ou HTML).

def awesomeASCIIArt(imageFilename, textFilename, blocSize=(1,1), type="text"):

image = np.asarray(Image.open(imageFilename), dtype='int32') #Ouvre l'image spécifiée, la


convertit en un tableau numpy d'entiers 32 bits.

h = len(image) #Récupère la hauteur h et la largeur w de l'image

w = len(image[0])

blocW, blocH = blocSize #Déstructure la taille du bloc. Cette variable est supposée être un
tuple avec deux éléments, et cette ligne de code assigne ces deux éléments à deux variables
distinctes blocW et blocH. Plus précisément, si blocSize est un tuple de la forme (largeur, hauteur)

alors après l'exécution de cette ligne, blocW prendra la valeur de la première composante du tuple
(largeur) et blocH prendra la valeur de la deuxième composante du tuple (hauteur).exp;blocW,
blocH = (3, 5)

nbBlocsW = int(w/blocW) #Calcule le nombre de blocs horizontaux et verticaux.

nbBlocsH = h//blocH

s = "" #Initialise une chaîne de caractères vide s

for blocY in range(nbBlocsH): #Les boucles imbriquées parcourant les blocs dans l'image.

for blocX in range(nbBlocsW):

sumRGB = 0

for y in range(blocH): #C'est une boucle qui parcourt les lignes du bloc.

for x in range(blocW): #À l'intérieur de chaque ligne du bloc, cette


boucle parcourt chaque colonne du bloc.

realX = blocX*blocW + x #Calculent les coordonnées réelles


(realX et realY) à partir des coordonnées

realY = blocY*blocH + y # du bloc (blocX et blocY) et des


indices de la boucle (x et y).Cela permet d'accéder au pixel réel dans l'image complète.
Accès aux valeurs RGB du pixel et calcul de la somme : image[realY][realX] donne les valeurs RGB
du pixel à la position (realX, realY). Les valeurs R, G et B sont additionnées (image[realY][realX][0] +
image[realY][realX][1] + image[realY][realX][2]) et divisées par 3 pour obtenir la moyenne.

sumRGB += (image[realY][realX][0]+ \

image[realY][realX][1]+ \

image[realY][realX][2])/3

avgRGB = sumRGB / (blocH*blocW) #la variable avgRGB est calculée en


divisant sumRGB par le nombre total de pixels dans le bloc (blocH * blocW) pour Calculer la
moyenne des valeurs RGB dans chaque bloc.

if type=="html": #Si le type de sortie est "html", génère une balise span avec une couleur

de fond basée sur la moyenne des valeurs RGB.

color = "rgb("+str(avgRGB)+","+str(avgRGB)+","+str(avgRGB)+")"

s += "<span style='font-family: monospace; background-color: "+color+"'>"

c = charForLight(avgRGB) #Appelle la fonction charForLight avec la moyenne des valeurs


RGB et ajoute le caractère résultant à la chaîne de sortie.

if type=="html": #Si le type est "html", ajoute un espace insécable si le caractère est un espace.

s += c if c != " " else "&nbsp;"

else:

s += c

if type=="html": #Si le type est "html", ferme la balise span.

s += "</span>"

if type=="html": #Si le type est "html", ajoute une balise de saut de ligne.

s += "<br/>"; #Ajoute un saut de ligne à la chaîne de sortie.

s += '\n'

f = open(textFilename, "w") #Ouvre le fichier de texte en mode écriture.

a = f.write(s) #Écrit la chaîne de sortie dans le fichier

f.close()

#Trois appels à awesomeASCIIArt avec différentes images, tailles de blocs et types de sortie.

awesomeASCIIArt("rickroll.jpg","rickroll.txt", (2,3), "text")

awesomeASCIIArt("worm.jpg","worm.html", (1,1), "html")

# awesomeASCIIArt("ld.jpg","ld.txt", (3,2), "text")

Vous aimerez peut-être aussi