Pièce jointe « pnm_v2.py »

Téléchargement

   1 # encoding: utf-8
   2 
   3 #
   4 
   5 # Création d'une image unie
   6 
   7 def creer_image_gris (largeur, hauteur, maximum):
   8     return {
   9             'format': 'gris',
  10             'largeur': largeur,
  11             'hauteur': hauteur,
  12             'maximum': maximum,
  13             'donnees': bytearray(largeur * hauteur)
  14         }
  15 
  16 def lire_pixel_gris (image, x, y):
  17     position = image['largeur'] * y + x
  18     return image['donnees'][position]
  19 
  20 def ecrire_pixel_gris (image, x, y, valeur):
  21     position = image['largeur'] * y + x
  22     image['donnees'][position] = valeur
  23 
  24 
  25 def creer_image_couleur (largeur, hauteur, maximum):
  26     return {
  27             'format': 'couleur',
  28             'largeur': largeur,
  29             'hauteur': hauteur,
  30             'maximum': maximum,
  31             'donnees': bytearray(largeur * hauteur * 3)
  32         }
  33 
  34 def lire_pixel_couleur (image, x, y):
  35     position = (image['largeur'] * y + x) * 3
  36     rouge = image['donnees'][position]
  37     vert = image['donnees'][position + 1]
  38     bleu = image['donnees'][position + 2]
  39     return rouge, vert, bleu
  40 
  41 def ecrire_pixel_couleur (image, x, y, rouge, vert, bleu):
  42     position = (image['largeur'] * y + x) * 3
  43     image['donnees'][position] = rouge
  44     image['donnees'][position + 1] = vert
  45     image['donnees'][position + 2] = bleu
  46 
  47 
  48 # Écriture d'une image en format PNM
  49 
  50 def ecrire_pbm_binaire (image, fichier):
  51     sortie = open(fichier, "wb")
  52     en_tete = "P3 %d %d\n" % (image['largeur'], image['hauteur'])
  53     sortie.write(en_tete.encode("ascii"))
  54     sortie.write(image['donnees'])
  55 
  56 def ecrire_pgm_binaire (image, fichier):
  57     sortie = open(fichier, "wb")
  58     en_tete = "P5 %d %d %d\n" % (image['largeur'], image['hauteur'], image['maximum'])
  59     sortie.write(en_tete.encode("ascii"))
  60     sortie.write(image['donnees'])
  61 
  62 def donnees_ppm_binaire (image):
  63     en_tete = "P6 %d %d %d\n" % (image['largeur'], image['hauteur'], image['maximum'])
  64     return bytearray(en_tete.encode("ascii")) + bytearray(image['donnees'])
  65 
  66 def ecrire_ppm_binaire (image, fichier):
  67     sortie = open(fichier, "wb")
  68     sortie.write(donnees_ppm_binaire(image))
  69 
  70 def afficher_ppm (image):
  71     try:
  72         # en Python 3
  73         import tkinter
  74     except ImportError:
  75         # en Python 2
  76         import Tkinter
  77         tkinter = Tkinter
  78     tk = tkinter.Tk()
  79     img = tkinter.PhotoImage(width=image['largeur'], height=image['hauteur'],
  80             data=donnees_ppm_binaire(image).decode('latin1'))
  81     label = tkinter.Label(tk, image=img)
  82     label.pack()
  83     return tk.mainloop()
  84 
  85 # Lecture du prochain "mot" sur un fichier PNM
  86 #
  87 # le mot est composé de tous les octets qui suivent jusqu'au prochain octet
  88 # correspondant à un caractère d'espacement, lequel n'est pas conservé. Selon
  89 # la spécification du format PNM, un caractère '#' introduit un commentaire,
  90 # il est ignoré ainsi que tout ce qui le suit jusqu'au prochain retour à la
  91 # ligne.
  92 
  93 def lire_mot_pnm (entree):
  94     mot = b""
  95     while True:
  96         octet = entree.read(1)
  97 
  98         # Test de fin de fichier
  99 
 100         if len(octet) == 0:
 101             return mot
 102 
 103         # Test de fin de mot
 104 
 105         if octet in (b' ', b'\r', b'\n', b'\t'):
 106             if len(mot) != 0:
 107                 return mot
 108 
 109         # Traitement des commentaires
 110 
 111         if octet == b'#':
 112             entree.readline()
 113 
 114         else:
 115             mot += octet
 116 
 117 # Lecture d'un fichier image PNM
 118 #
 119 # Le format est déduit du premier mot du fichier.
 120 
 121 def lire_pnm (fichier):
 122     entree = open(fichier, "rb")
 123     forme = lire_mot_pnm(entree)
 124     if forme == b'P3':
 125         return lire_ppm_ascii(entree)
 126     elif forme == b'P4':
 127         return lire_pbm_binaire(entree)
 128     elif forme == b'P5':
 129         return lire_pgm_binaire(entree)
 130     elif forme == b'P6':
 131         return lire_ppm_binaire(entree)
 132     else:
 133         raise ValueError("Format inconnu: %s" % forme.encode('ASCII'))
 134 
 135 # Les fonctions suivantes servent à décoder un fichier image dont on connaît
 136 # le format: on suppose que le premier mot a déjà été lu et on lit la suite.
 137 
 138 # Format PBM binaire
 139 
 140 def lire_pbm_binaire (entree):
 141     largeur = int(lire_mot_pnm(entree))
 142     hauteur = int(lire_mot_pnm(entree))
 143     ligne = (largeur + 7) // 8
 144     donnees = bytearray(entree.read(ligne * hauteur))
 145     return {
 146             'format': 'bitmap',
 147             'largeur': largeur,
 148             'hauteur': hauteur,
 149             'ligne': ligne,
 150             'donnees': donnees
 151         }
 152 
 153 # Format PGM binaire
 154 
 155 def lire_pgm_binaire (entree):
 156     largeur = int(lire_mot_pnm(entree))
 157     hauteur = int(lire_mot_pnm(entree))
 158     maximum = int(lire_mot_pnm(entree))
 159     if maximum > 255:
 160         raise ValueError("Intervalle trop grand (%d)" % maximum)
 161     donnees = bytearray(entree.read(largeur * hauteur))
 162     return {
 163             'format': 'gris',
 164             'largeur': largeur,
 165             'hauteur': hauteur,
 166             'maximum': maximum,
 167             'donnees': donnees
 168         }
 169 
 170 # Format PPM binaire
 171 
 172 def lire_ppm_binaire (entree):
 173     largeur = int(lire_mot_pnm(entree))
 174     hauteur = int(lire_mot_pnm(entree))
 175     maximum = int(lire_mot_pnm(entree))
 176     if maximum > 255:
 177         raise ValueError("Intervalle trop grand (%d)" % maximum)
 178     donnees = bytearray(entree.read(largeur * hauteur * 3))
 179     return {
 180             'format': 'couleur',
 181             'largeur': largeur,
 182             'hauteur': hauteur,
 183             'maximum': maximum,
 184             'donnees': donnees
 185         }
 186 
 187 # Format PPM ascii
 188 
 189 def lire_ppm_ascii (entree):
 190     largeur = int(lire_mot_pnm(entree))
 191     hauteur = int(lire_mot_pnm(entree))
 192     maximum = int(lire_mot_pnm(entree))
 193     if maximum > 255:
 194         raise ValueError("Intervalle trop grand (%d)" % maximum)
 195     nombre = largeur * hauteur * 3
 196     donnees = bytearray(nombre)
 197     for i in range(nombre):
 198         mot = lire_mot_pnm(entree)
 199         donnees[i] = int(mot)
 200     return {
 201             'format': 'couleur',
 202             'largeur': largeur,
 203             'hauteur': hauteur,
 204             'maximum': maximum,
 205             'donnees': donnees
 206         }
 207 
 208 
 209 # Conversion de couleur vers gris
 210 
 211 def couleurs_vers_gris (entree):
 212     if entree['format'] != 'couleur':
 213         raise ValueError("l'image n'est pas en couleur")
 214     largeur = entree['largeur']
 215     hauteur = entree['hauteur']
 216     sortie = creer_image_gris(largeur, hauteur, entree['maximum'])
 217     for x in range(largeur):
 218         for y in range(hauteur):
 219             r, v, b = lire_pixel_couleur(entree, x, y)
 220             teinte = (r + v + b) // 3
 221             ecrire_pixel_gris(sortie, x, y, teinte)
 222     return sortie
 223 
 224 # Zoom d'un facteur arbitraire
 225 
 226 def zoom_gris (entree, facteur):
 227     if entree['format'] != 'gris':
 228         raise ValueError("l'image n'est pas en gris")
 229     largeur = int(entree['largeur'] * facteur)
 230     hauteur = int(entree['hauteur'] * facteur)
 231     sortie = creer_image_gris(largeur, hauteur, entree['maximum'])
 232     for x in range(largeur):
 233         for y in range(hauteur):
 234             teinte = lire_pixel_gris(entree, int(x/facteur), int(y/facteur))
 235             ecrire_pixel_gris(sortie, x, y, teinte)
 236     return sortie
 237 
 238 def test (largeur, hauteur):
 239     image = creer_image_gris(largeur, hauteur, 255)
 240     for x in range(largeur):
 241         for y in range(hauteur):
 242             teinte = ((x*x + y*y) // 20) % 256
 243             ecrire_pixel_gris(image, x, y, teinte)
 244     ecrire_pgm_binaire(image, "sortie.pgm")
 245 
 246 if __name__ == '__main__':
 247     i1 = lire_pnm("pinklady.ppm")
 248     i2 = couleurs_vers_gris(i1)
 249     i3 = zoom_gris(i2, 10)
 250     ecrire_pgm_binaire(i3, "sortie.pgm")

Fichiers joints

Pour vous référer aux pièces jointes d'une page, utilisez attachment:filename, comme indiqué ci-dessous dans la liste de fichiers. N'utilisez pas l'URL du lien [get], car elle peut changer et donc être facilement cassée.
 All files | Selected Files: delete move to page copy to page

Vous n'êtes pas autorisé à joindre un fichier à cette page.