Manipuler des images.

Image binaire

Les images jpg, png, ppm... sont codées de différentes façons.
A l'affichage sur écran, on peut toutes les considérer in fine comme un grand rectangle de pixels (c'est à dire de points colorés).

La complexité des divers formats (jpeg, png par exemple) rend très difficile la manipulation directe de ce tableau de pixels. On utilisera donc dans la suite un module python (PIL ou pillow) qui nous permettra de manipuler les images comme si leur encodage se limitait à un tableau de pixels.

A chaque pixel est associé une couleur. Nous verrons plus loin en détail un encodage des couleurs.
Nous nous limiterons ici à présenter et utiliser le code RGB : un nombre est associé à l'intensité du rouge (R), un second nombre pour l'intensité du vert (G) et un troisième pour l'intensité du bleu (B). Ces composantes de rouge, vert, bleu seront codées dans nos exemples sur un octet et varieront donc de 0 à 255 (en binaire : de 0b00000000 à 0b11111111).

Dans une telle représentation, une image peut donc être considérée comme un grand tableau, chaque cellule du tableau correspondant à un pixel de l'image et contenant donc trois entiers (un pour le rouge, un pour le vert, un pour le bleu).

Les formats d'image

Les images jpg, png, ppm... sont codées de différentes façons.

Ces différences d'encodage correspondent à des algorithmes différents, et souvent à des objectifs différents.

  1. Un objectif possible : réduire la taille du fichier image. Les formats d'images compressées (notamment le format jpeg) essaient de répondre à cet objectif d'une taille de fichier la moins grande possible (tout en conservant au mieux les qualités de l'image).
  2. Un autre objectif peut être de préserver au maximum les données (fidélité de l'image, manipulation plus aisée des bits pour retravailler l'image...). On aura alors plutôt affaire à des formats non compressés.
  3. Toutefois, certains formats compressent sans perte de données (avec le format jpg par exemple, on ne peut pas reconstituer les informations de départ de façon intégrale, tandis que le format png compresse sans perte d'informations).

Bien d'autres spécificités distinguent les différents formats :
par exemple : images en noir et blanc, images en niveau de gris, images en couleur.
Des images en noir et blanc ont encore de l'intérêt aujourd’hui : elles sont naturellement plus légères que des images en couleurs (pour un transfert par fax par exemple, la légèreté de l'information à transmettre reste un facteur prépondérant). Nous avons vu par exemple avec le format pbm qu'il suffit d'un caractère '0' ou '1' pour coder un pixel (ce qui nécessite un seul bit par pixel en format binaire). Pour une image en couleur, il faut a priori autant de codes différents que de couleurs différentes.
La compression d'un fichier en noir et blanc est beaucoup plus facile. Imaginons par exemple qu'une ligne est constituée de 500 pixels noirs, puis 100 blancs puis 600 noirs. Cette information n'a pas besoin de 500+100+600 bits, il suffit d'avoir l'information 500'1'-100'0'-600'1'. Pour une image couleur, dans laquelle il y a en général plusieurs milliers de couleurs, les changements de couleurs sur une ligne sont très fréquents et cette méthode de compression (nb de pixels de telle couleur- nb de pixels de telle autre couleur...) n'est plus du tout efficace (et risque même d'augmenter la taille du fichier).

Image vectorielle

Dans ce cours, nous ne parlerons que des images bitmap et non des images vectorielles.

Une image bitmap est une image définie pixel par pixel : on dispose d'un grand rectangle de points et on attribue une couleur à chacun des points.

Pour une image vectorielle, la définition se fait plutôt par interprétation de commande géométrique. Au lieu de colorer en noir un certain nombre de pixels formant un carré, on écrira "dessiner un carré". On dispose ensuite d'un logiciel capable d'interpréter cette commande. Pour aller plus loin sur ce thème des images vectorielles, vous pouvez chercher sur le web des renseignements sur le format svg par exemple, ou sur le logiciel inkscape.

Da façon simple, on peut dire qu'un appareil photo prend les images dans un format bitmap tandis que les formats vectoriels correspondent plutôt à des images "construites" par l'homme.

Le format ppm

Le format ppm est un format très simple permettant d'encoder les images presque exactement comme décrit ci-dessus : un grand tableau, chaque cellule contenant trois entiers correspondant aux couleurs RGB.

Pour manipuler ces images, nous n'aurons donc pas besoin d'un module spécifique. Il suffit de savoir écrire et lire dans un fichier comme nous l'avons fait avec les fichiers d'images au format pbm.

Exemple.

Nous présentons un premier exemple ci-dessous. Exécuter ce code python. Ouvrir ensuite le fichier image avec un logiciel adéquat et comprendre le lien entre le code et l'image visualisée.


largeur=100
hauteur=600

f=open('couleurs','w') # ou f=open('couleurs.ppm','w')

############ entête du fichier ##########################
f.write('P3'+'\n') # P1 était le code pour un pbm format ascii
			  # P3 correspond au ppm format ascii
f.write(str(largeur)+' '+str(hauteur)+'\n')
# valeur max pour l'intensité des couleurs :
f.write('255'+'\n')
############### fin de l'entête ########################


#########  les pixels #################################
def rectangle(couleur) :
	""" couleur est un triplet d'entiers, code RGB."""
	for j in range(hauteur//6) :
		for i in range(largeur) :
			f.write(couleur+'\n')
			

rectangle('255 0 0')
rectangle('0 255 0')	
rectangle('0 0 255')
rectangle('0 255 255')
rectangle('255 0 255')
rectangle('255 255 0')

########### fin pixels ############################

f.close()

On obtient l'image suivante : couleurs.ppm

Traiter maintenant les exercices concernant ce format.

Remarque : pour une ouverture automatisée de l'image après création, voir ici.