Personal tools
Document Actions

PIL et superposition d'image transparente

by Rakotomandimby Mihamina last modified 2008-07-20 10:58

Voici comment utiliser PIL pour ajouter un masque semi transparent à une image pleine. Nous aborderons aussi rapidement le redimensionnement d'image, necessaire pour ajuster la taille des deux images à superposer.

Le but de l'exercice

Entant donné une image et un calque que nous avons pris soin de préfabriquer, comment obtenir la superposition de ceux-ci.

PIL

la Python Imaging Library est une bibliothèque qui n'est pas en standard dans Python et qu'il faut installer séparément. Elle est incroyablement remplie de fonctionalités pour manipuler des images. Une de celles qui ne sont pas suffisament documentée à mon gout est celle qui permet de superposer deux ou plusieurs images qui sont semi-transparentes.

JPEG, PNG, RGB, RGBA

Je ne suis surtout pas un spécialiste des images numériques. Cependant, ce que je sais c'est que le format JPEG ne permet pas de gérer la transparence contrairement au PNG. De plus, en PNG, il faut avoir l'image semi transparente en mode RGBA: le A dans RGBA désigne le canal "Alpha" qui indique la transparence. Le RGB (tout court, sans A) ne porte aucune information sur la transparence.

Ce qui veut dire que si les images originales sont en JPEG, il faut dans un premier lieu les ouvrir avec PIL et basculer en mode RGB. Il sera ensuite possible de la supperposer avec le masque semi-transparent qui est en mode RGBA. Le cas d'étude, dans lequel nous supposons que le lecteur est, est: Le masque semi-transparent est en PNG/RGBA et l'image sur laquelle nous allons déposer le masque en JPEG.

Sous linux il est facile de le savoir avant d'être en train de coder en Python, avec l'utilitaire file.

Par exemple, cela donne pour nos images:

modele_archi.PNG: PNG image data, 580 x 295, 8-bit/color RGBA, non-interlaced
original.jpg: JPEG image data, JFIF standard 1.01


Le calque

Le calque que nous allons utiliser est d'une taille quelconque mais suffisament proche de celles des images sur lesquelles nous allons le poser. Nous allons devoir le redimensionner à chaque fois. En fonction des besoins, il conviendra de bien choisir sa taille.

L'image initiale

Nous avons choisi une image volontairement en JPEG qui est celle d'un batiment dessiné par l'architecte P.Audric, qui travaille actuellement à Madagascar et dont je suis l'infogérant. Nous allons choisir de redimensionner le calque, pour ne pas alourdir le code ni déformer l'image.

Redimensionner le calque

C'est une opération relativement facile. Est-il necessaire d'en dire plus?
Remarquons que PIL ne redimensionne pas l'image originale mais crée une copie redimensionnée, d'ou la necessité de la stocker dans une "variable".

Convertir le JPEG

Pour pouvoir exploiter la transparence, il est nécessaire de "convertir" le fond JPEG en "RGB" avant de lui "flanquer" le calque.

Fusionner les images

La méthode paste() va maintenant nous servir pour fusionner finalement.

Explications

En réalité, tout se trouve dans la documentation mais les lignes en parlant ne comportent aucun mot clé permettant de le trouver.
Voici ce qui est dit en anglais:

im.paste(image, box, mask)
Same as above, but updates only the regions indicated by the mask. You can use either "1", "L" or "RGBA" images (in the latter case, the alpha band is used as mask). Where the mask is 255, the given image is copied as is. Where the mask is 0, the current value is preserved. Intermediate values can be used for transparency effects.
Note that if you paste an "RGBA" image, the alpha band is ignored. You can work around this by using the same image as both source image and mask.

Ma traduction est partielle et imparfaite, mais c'est ce que j'ai compris de ce qu'il est dit:

Si on fourni une image en mode "RGBA" en "mask" (troisième argument) alors sera extrait le "canal alpha" (qui détermine la "transparence point par point") et ce dernier servira d'indication sur la transparence à appliquer lors du collage. Si il se trouve que c'est une image "RGBA" qu'on veut coller, cela tombe bien, il suffit de mettre calque en "image" (NdT: ou PIL ne tiendra compte que des R, G et B) et en "mask" (NdT: ou PIL ne tiendra compte que du A).

Conclusion

Il ne reste plus qu'à sauver et observer le résultat.
Ce fût assez simple.
J'utilise ce script pour appliquer les mêmes modifications (calque + resize) sur la quelque centaines de photos du site Web que je maintient.