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.Vous n'êtes pas autorisé à joindre un fichier à cette page.