Skip to content

Images PGM

Énoncé

On se propose maintenant de travailler avec le format d'image PGM, qui est un format texte. Le format est très simple. Une image PGM contient les informations suivantes :

  • une premiere ligne contenant la chaine P2 ;
  • une seconde ligne contenant deux entiers (largeur et hauteur de l’image), séparés par un espace ;
  • une troisième ligne contenant 255 ;
  • ensuite "hauteur" lignes contenant "largeur" entiers strictement inférieurs à 256, séparés par des espaces définissant le niveau de gris de chaque pixel.

Pour plus d'information vous pouvez consulter la page wikipédia du format.

Vous devez générez un fichier PGM par une série d’écritures sur la sortie standard, une redirection permettant ensuite la création du fichier d’image. Le programme fonctionne de la maniere suivante :

  • on demande à l'utilisateur de donner les dimensions de l'image ;
  • on affiche l'en-tête du fichier (les trois premières lignes) ;
  • on tire aléatoirement les coordonnées de deux disques (centre et rayon) complétement localisés dans l’image ;
  • on itère enfin sur tous les pixels, affichant leurs valeurs ligne par ligne :
  • un pixel en dehors des deux disques est blanc, c'est à dire de valeur 255 ;
  • un pixel à l'intérieur de l'un ou l'autre des deux disques est plus ou moins noir, c'est à dire d'une valeur aléatoire entre 0 et 255.

Voici un exemple de résultat :

exemple de resultat

Correction

Cliquez ici pour révéler la correction.

Voici le code d'une correction possible :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#!/usr/bin/env python3
"""Mini projet Images PGM"""
from random import randint, seed


def contient(disque, point):
    """Fonction qui determine si un point est contenu dans un disque"""
    difference_abscisses = point[0] - disque[0][0]
    difference_ordonnees = point[1] - disque[0][1]
    distance_carree = (
        difference_abscisses * difference_abscisses
        + difference_ordonnees * difference_ordonnees
    )
    return distance_carree <= disque[1] * disque[1]


def tire_disque(largeur, hauteur):
    """Tire aléatoirement un disque complètement inclus dans une image de la taille donnée"""

    # On veut un cercle avec un rayon minimum de 20% de la
    # plus petite dimension de l'image.
    rayon_min = min(largeur * 0.2, hauteur * 0.2)

    # On tire le centre
    centre = (
        randint(rayon_min, largeur - rayon_min),
        randint(rayon_min, hauteur - rayon_min),
    )

    # On tire ensuite le rayon
    rayon_max = min(largeur - centre[0], centre[0], hauteur - centre[1], centre[1])
    rayon = randint(rayon_min, rayon_max)

    return (centre, rayon)


def affiche_entete(largeur, hauteur):
    """Affichage de l'entête pgm sur stdout"""
    print("P2")
    print(f"{largeur} {hauteur}")
    print("255")


def affiche_pixels(disque1, disque2, largeur, hauteur):
    """Calcul des pixels aléatoires et affichage sur stdout"""
    for ligne in range(hauteur):
        for colonne in range(largeur):
            point = (colonne, ligne)
            if contient(disque1, point) or contient(disque2, point):
                print(randint(0, 255), end=" ")
            else:
                print(255, end=" ")
        print()


def main():
    """Point d'entrée du programme"""
    # À dé-commenter pour de l'aléatoire "contrôlé"
    # seed(41)

    # On demande à l'utilisateur la taille de l'image
    larg = int(input())
    haut = int(input())

    # On tire deux disque aléatoires
    d1 = tire_disque(larg, haut)
    d2 = tire_disque(larg, haut)

    # On affiche l'image
    affiche_entete(larg, haut)
    affiche_pixels(d1, d2, larg, haut)


main()

Exercices