Module externe PIL / Pillow pour python
PIL (Python Imaging Library) est une bibliothèque graphique écrite par Fredrik Lundh à partir de 1995, et reprise en 2010 sous le nom de Pillow par Jeffrey A. Clark et d’autres personnes. La transition s’étant effectuée en bonne intelligence, le nom du module est resté PIL. Cette page est basée sur la version 11.1.0 de Debian 13 Trixie.
Cette page suit les recommandations de 1990 pour une orthographe réformée.
Page en cours d’écriture, surtout selon mes besoins
Voyez la page modules pour les généralités. Pour rappel,
- le paquet python3-pil (nom pour GNU/Linux Debian) devra probablement être installé
- from PIL import Image importe seulement le sous-module Image, l’usage est Image.methode()
- directement appliqué·es à un objet, méthodes et attributs ne doivent pas être préfixé·es : objet.copy(), objet.size
1. Fichiers et images
1.1 Créer un objet-image
1.2 Charger et sauvegarder une image
1.3 Attributs
1. Fichiers et images
1.1 Créer un objet-image
new()
img0 =Image.new(mode, (w, h), couleur) crée une image selon un mode (voir ci-après), un tuple représentant le couple largeur-hauteur en pixels et une couleur de fond.
- Les modes pleinement supportés sont :
- "1" Noir et Blanc, 0 (noir) ou 1 (blanc), huit pixels par octet
- "L" échelle de 256 valeurs de gris, de 0 à 255, un octet par pixel
- "LA" ajout d’un canal «alpha» (de 0 =transparent à 255 =opaque)
- "RGB" 16Mio couleurs (256 niveaux de Red, Green, Blue, les lumières fondamentales)
- "RGBA" ajout du canal «alpha» pour l’ensemble des trois couleurs
- "CMYK" couleurs primaires Cyan, Magenta, Yellow et Black (quadrichromie)
- "HSV" Hue, Saturation, Value
- "F" codage sur un «réel» de 32 bits
- "I" codage sur un entier de quatre octets
- "P" palette de 256 couleurs indexées
- "LAB" selon la théorie CIELAB
- (w, h) est un tuple comprenant la largeur et la hauteur de l’image, en pixels
- couleur (facultatif) le fond de l’image est noir par défaut ; il est possible de préciser une couleur de fond avec :
- un entier positif < 2 pour le mode "1" ; < 256 pour "L"
- un entier de quatre octets pour le mode "I"
- un réel de quatre octets pour le mode "F"
- un tuple pour plusieurs canaux (r, v, b, a) pour le mode "RGBA"
- une chaine représentant un nombre hexadécimal ("#rrggbbaa")
- une chaine représentant un nom de couleur HTML
img0 =Image.new("RGB", (1024, 756), "black") initialise une image de 1024×756 à fond noir
img0 =Image.new("RGBA", (540, 960), (0, 0, 0, 0)) initialise un fond transparent, susceptible de recevoir des collages ??? d(e partie d)’images contenant un canal alpha.
copy()
nv0 =img0.copy() copie en créant une nouvelle image. À utiliser en cas de stockage dans une liste de différentes étapes de l’évoltion d’une image : liste0.append(img0.copy()), sinon toutes les cellules contiendront finalement la dernière version.
crop() permet de créer un objet-image en sélectionnant une partie d’image.
canaux
img0.getbands() retourne un tuple composé des canaux (“bands„), ("R", "G", "B") pour une image "RGB"
(r, g, b, a) =img0.split() sépare les canaux d’une image (le tuple de réception doit être défini en fonction du mode de l’image)
img0 =Image.merge(mode, (c1, c2…)) intègre différents canaux pour former une image.
c =img0.getchannel(couche) isole une couche ("1", "L", "R", "G", "B", "A"…) d’une image
img0.getchannel(canal) crée une image de type L (256 niveaux) formée du seul canal spécifié : 1, L, R, G, B, A…
tupmult0 =img0.getextrema() renvoie un (ensemble de) tuples (min, max) pour chaque canal de l’image
tup0 =img0.getchannel("R").getextrema() retourne un tuple contenant les valeurs extrêmes pour la couche "R" (rouge)
1.2 Charger et sauvegarder une image
open() : ouvrir une image existante
Le module est capable de charger les images en format ARG, BMP, CUR, DCX, EPS (ghostscript), FLI, FPX, GBR, GD, GIF, ICO, IM, IMT, IPTC, JPEG, MCIDAS, MPEG, MSP, PCX, PDF, PhotoCD, PIXAR, PNG, PPM, PSD, SGI, SUN, TGA, TIFF, WMF, XBM et XPM.
objet =Image.open(chemin/fichier) charge une image pour la transformer en un objet susceptible d’être édité.
Les combinaisons entre images devant être de même format, il peut être nécessaire de convertir l’image dès le chargement :
img0 =Image.open(chemin/fichier).convert("RGBA")
save() : sauvegarder un objet-image
Le module sauvegarde les images sous les formats BMP, EPS (sans ghostscript, GIF (fixes ou animées), IM, JPEG, MSP, PDF, PNG, PPM, TIFF et XBM.
objet.save(chemin/fichier.ext, format=None, **params) sauvegarde un objet en un fichier image. Sans spécification de format, c’est l’extension du fichier qui le détermine.
À confirmer : **params signifie que les paramètres peuvent être passés par une série d’affectations en fin de parenthèse :
img0.save("mamie.png", Software="Python+PIL", comment="L’été 1993")
images animées
liste0[0].save(chemin/image.gif, save_all=True, append_images=liste0[1:], duration=durees, loop=n) convertit en GIF animée une liste d’images, en parallèle avec la liste de leur durée d’exposition.
- duration renvoie à un seul entier en 1000e de secondes, ou une liste contenant les durées pour chaque images (erreur si la liste des durées n’a pas le même nombre d’éléments que la liste des images)
- loop= détermine le nombre de répétition de l’animation ; 0 pour indéfiniment
1.3 Attributs d’une image
Pour l’objet img0,
w =img0.width permet de récupérer la largeur de l’image
h =img0.height permet de récupérer la hauteur de l’image
tup =img0.size renvoie un tuple contenant la largeur et la hauteur de l’image
w, h =img0.size permet de récupérer dans deux variables différentes la largeur et la hauteur de l’image
mode =img0.mode retourne une chaine représentant le mode (voir créer)
img0.info contient un dictionnaire sur différents attributs : la densité, la compression, l’orientation, la durée pour les animées… selon le type de l’image. img0.info[''] peut exprimer :
- 'background' tuple représentant le fond de l’image, par exemple (255, 255, 255, 255) pour le blanc tout à fait opaque
- 'comment' commentaire de l’image
- 'dpi' résolution de l’image, par exemple (72, 72), (100, 100), (300, 300)
- 'duration' exposition de l’image en millièmes de secondes (GIF animées ?)
- 'jfif' par exemple 257, qui doit correspondre à 'jfif_version' : (1, 1)
- 'jfif_density' : (1, 1), (100, 100), qui semble correspondre à 'dpi' : (100, 100)
- 'loop' nombre d’exposition (GIF animée ?)
- 'Software' origine de l’image, par exemple l’application de la copie d’écran
Autres «clés» rencontrées : 'Raw profile type exif', 'icc_profile', 'xmp', 'progressive', 'progression'. Il ne pas trop se fier à ce genre d’informations, pas toujours standard, qui contiennent parfois des données binaires ; PIL ne peut pas toujours les interpréter.
2. Transformations
2.1 Copier / coller
Pour ces «copier / coller», les images ne doivent pas être de même dimensions.
crop()
Pour créer un objet-image identique à un autre, utiliser copy().
rect0 =img0.crop((x0, y0, x1, y1)) crée un nouvel objet-image à partir de la copie d’une partie rectangulaire d’une image, dont les coordonnées sont rassemblées dans un tuple, commençant du point x0, y0 en haut à gauche au point x1, y1 en bas à droite.
paste()
.paste(rec0, coord, masque0) colle un rectangle d’image aux coordonnées (x, y)Cet objet est modifiéimg0
- rec0 recouvre img0 ; il peut s’agir d’un objet-image ou d’une couleur
- coord représente :
- (x, y), un point de coordonnée pour le point (0, 0) de l’image recouvrante
- (x0, y0, x1, y1), rectangle réservé au remplissage par rec0, adaptant les dimensions de l’image
- masque
.paste(rect0, (x1, y1, x2, y2)) colle un rectangle d’image aux coordonnées (x, y) en l’adaptant (resize) aux dimensions préciséesCet objet est modifiéimg0
.paste((0, 0, 0), (x1, y1, x2, y2)) teinte en noir (pour une image "RGBA" : (0,0,0,0) pour la transparence) un rectangle aux dimensions précisées.Cet objet est modifiéimg0
2.2 Assembler des images
Pour les assemblages, les images doivent être de même dimensions.
nv0 =Image.blend(image1, image2, t) superpose deux images selon la valeur du taux t, entre 0.0 (première image seulement) et 1.0 (seconde uniquement).
nv0 =Image.composite(image1, image2, masque0) superpose deux images, avec un taux variable défini par l’image masque. L’image masque doit avoir pour mode "1", "L" ou "RGBA". Pour un masque en 256 niveaux de gris (L, essai en PNG), le blanc conserve la première image et le noir impose la seconde.
nv0 =Image.alpha_composite(fond0, img0) permet le dépôt d’une image sur une image de fond, les deux ayant les mêmes dimensions et le même mode avec canal alpha.
.putalpha(alpha) ajoute un canal alpha à une image, ou le remplace. Un mode L ou RGB est converti en LA or RGBA. alpha doit être une image L or 1 de même taille, ou un entier de 0 (transparent) à 255 (opaque) pour un canal alpha uniforme.
Cet objet est modifiéimg0
2.3 ↑ Dimensions
| ↖ | ↘ |
| 0 | ![]() ![]() |
|---|---|
![]() ![]() | |
| 1 | ![]() ![]() |
![]() ![]() | |
| 2 | ![]() ![]() |
![]() ![]() | |
| 3 | ![]() ![]() |
![]() ![]() | |
| 4 | ![]() ![]() |
![]() ![]() | |
| 5 | ![]() ![]() |
![]() ![]() |
resize()


L’image utilisée pour les exemples est un PNG à 256 niveaux de gris de 82×82 réduite à 55×55 à gauche et élargie à 115×115. Afin de rendre les aberrations plus visibles, surtout visibles sur des surfaces très délimitées, l’image originale est dessinée en noir (niveau 0) et blanc (255). Survoler les images produites offre un mode loupe ×2.
nv0 =img0.resize((x, y), Image.MODE) renvoie une image redimensionnée, mais le résultat n’est proportionnel que dans la mesure où les nouvelles dimensions sont proportionnelles aux anciennes (x /w = y /h). Pour (w, h) =img0.size :
- x fixé : round(y =x *h /w)
- y fixé : round(x =y *w /h)
MODEs de redimensionnement :
- 0 ou Image.NEAREST : rapide, mais de qualité inférieure : ↖ perte de pixels et ↘ effets d’escaliers
- 1 ou Image.LANCZOS : réputé le meilleur pour les photos (pas trop contrastées), anciennement ANTIALIAS
- 2 ou Image.BILINEAR : qualité moyenne (interpolation quadratique)
- 3 ou Image.BICUBIC : meilleure qualité (mode par défaut)
- 4 ou Image.BOX : ↖ pas de pixel manquant mais gris ; ↘ comme NEAREST ; utilisable pour les agrandissements entiers : ×2, ×3, ×4…
- 5 ou Image.HAMMING : probablement le meilleur contraste pour les agrandissements non entiers
thumbnail()
.thumbnail((nw, nh), Image.MODE) rétrécit une image (“thumbnail„ signifie «miniature») en respectant les proportions de l’image et selon les modes de redimensionnement décrits à la méthode resize() ci-dessus. Les nouvelles dimensions limitent la largeur et la hauteur permises pour la nouvelle image :
Cet objet est modifiéimg0
.thumbnail((10000, 120)) réduit proportionnellement toute image de moins de 10 000px de largeur à la hauteur de 120px.
Cet objet est modifiéimg0
2.4 Transpositions
↑ transpose()
Les transpositions suivantes conservent la largeur et la hauteur de l’image produite :
nv0= img0.transpose(Image.FLIP_LEFT_RIGHT) inversion gauche-droite de l’image
nv0= img0.transpose(Image.FLIP_TOP_BOTTOM) inversion haut-bas de l’image
nv0= img0.transpose(Image.Transpose.ROTATE_180) symétrie centrale (composition des deux précédentes)
Les transpositions suivantes inversent la largeur et la hauteur de l’image produite :
nv0= img0.transpose(Image.Transpose.ROTATE_90) rotation d’un quart de tour dans le sens trigonométrique
nv0= img0.transpose(Image.Transpose.ROTATE_270) rotation d’un quart de tour dans le sens horaire
nv0= img0.transpose(Image.TRANSPOSE) rotation anti-horaire d’un quart de cercle et inversion haut-bas
nv0 =img.transpose(Image.TRANSVERSE) rotation horaire d’un quart de cercle et inversion haut-bas
↑ rotate()
img0.rotate(degres) tourne l’image avec précision. rotate() ne se préocuppe pas des dimensions de l’image produite : des parties seront coupées, sauf dans la rotation de 180° (symétrie centrale) ou dans les quarts de tour d’une image carrée.
Attention : PIL-Pillow compte les angles en degrés (dans le sens trigonométrique, possibilité d’une partie décimale), tandis que les fonctions trigonométriques du module math attendent des angles exprimés radian. Voici les formules de conversion :
- radian =degrés *math.pi /180
- degrés =radian *180 /math.pi
…traduites en fonctions :
import math def rad(d) : return d /180 *math.pi def deg(r) : return r *180 /math.pi print(math.cos(rad(45))) # 0.7071067811865476 print(deg(math.atan(2))) # 63.43494882292201 (degrés et partie décimale)
3. Filtres
effect_spread()
(nv0=?) img0.effect_spread(n) disperse les pixels de façon aléatoire, avec distance maximale de n pixels). Si la nouvelle paire x, y tombe en dehors de l’image, l’échange de pixels n’a pas lieu, ce qui veut dire que si n est très élevé, la méthode a peu d’effet sur l’image.
↑ Images animées
img0.is_animated contient un booléen True ou False selon que l’objet contient plus d’une image ("frame"), donc animée (GIF et MNG?), ou non
img0.n_frames contient le nombre d’images d’une image animée
img0.tell() retourne le frame actuel (0 par défaut pour le premier frame)
img0.seek(i) pointe le frame i d’une image animée, de 0 à n_frames -1
for i in range(img0.n_frames) :
seek(i) # {pas clair}
Et encore
↑ show()
img0.show("titre") fait apparaître l’image au format PNG dans une fenêtre d’application extérieure au titre aléatoire ; titre devrait s’appliquer à la fenêtre mais ne fonctionne pas nécessairement.
img0.getpixel((x, y)) retourne la couleur aux coordonnées (x, y), sous forme de tuple si l’image a plusieurs couches
img0.putpixel((x, y), couleur) impose une couleur aux coordonnées (x, y), la couleur doit être un tuple de valeurs si l’image a plusieurs couches























