Fri Jun 26 2026 20:00:00 GMT-0400 (北美东部夏令时间)
Compresser des images en Python avec Pillow, WebP et mozjpeg
Compressez des images JPEG, PNG et WebP en Python grâce à Pillow, cwebp et mozjpeg. Gérez les paramètres de qualité, les boucles de taille cible et un script batch rapide.

Mis à jour le: June 27, 2026
Vous avez un dossier de JPEGs de taille photo, une étape de build qui les envoie aux utilisateurs et un budget de poids de page qui ne cesse d'exploser. Compresser ces fichiers manuellement dans un éditeur d'images n'est pas évolutif. Ce guide montre le Python exact dont vous avez besoin pour réduire la taille des fichiers JPEG, PNG et WebP selon un calendrier, dans un job CI ou à l'intérieur d'un gestionnaire de téléversement (upload handler).
Réponse rapide : comment compresser des images avec Python ?
Ouvrez l'image avec Pillow, puis enregistrez-la avec les bons drapeaux de format. Pour les photos, enregistrez en JPEG avec quality=80, optimize=True et progressive=True. Pour les fichiers modernes les plus petits, enregistrez en WebP avec quality=80, method=6. Pour les graphiques plats et les captures d'écran, conservez PNG et passez optimize=True.
from PIL import Image
def compress_jpeg(src, dst, quality=80):
img = Image.open(src)
if img.mode in ("RGBA", "P"):
img = img.convert("RGB")
img.save(dst, "JPEG", quality=quality, optimize=True, progressive=True)
Cette fonction de quatre lignes réduit déjà la plupart des JPEGs de téléphones et de DSLR de 40 à 70 pour cent. Le reste de ce guide ajoute les cibles de taille, WebP, mozjpeg et un exécuteur par lots (batch runner) afin que vous puissiez le pointer vers un répertoire et partir.
De quoi avez-vous besoin avant de commencer ?
Vous avez besoin de Python 3.9 ou plus récent et de Pillow, la fourche maintenue de PIL. Pillow gère JPEG, PNG et WebP nativement sur toutes les plateformes courantes.
pip install Pillow
Pour le résultat le plus petit, vous voudrez également deux encodeurs en ligne de commande que Python peut appeler : cwebp de libwebp et cjpeg de mozjpeg.
brew install webp mozjpeg # macOS; Linux: apt install webp, build mozjpeg
Vérifiez à quoi sert chaque composant avant d'écrire du code :
- Pillow lit et écrit tous les formats et effectue le redimensionnement.
- cwebp produit les fichiers WebP les plus serrés et expose plus de réglages que Pillow.
- mozjpeg réencode les JPEGs plus petits que le standard libjpeg utilisé par Pillow.
- Un aide au rapport pour que chaque exécution affiche combien d'octets vous avez économisés.
Voici l'aide utilisée tout au long de ce guide :
import os
def report(src, dst):
before, after = os.path.getsize(src), os.path.getsize(dst)
saved = (1 - after / before) * 100
print(f"{before/1024:.0f} KB -> {after/1024:.0f} KB ({saved:.0f}% plus petit)")
Si vous avez seulement besoin d'une compression ponctuelle et que vous ne voulez rien installer, le compresseur d'images basé sur navigateur fait le même travail pour une poignée de fichiers.
Comment compresser un JPEG avec Pillow ?
Les trois drapeaux qui comptent pour JPEG sont quality, optimize et progressive. quality contrôle la quantité de détails que l'encodeur abandonne. optimize=True exécute un second passage pour construire une table Huffman plus petite. progressive=True réordonne le fichier afin qu'il se peigne de haut en bas à faible résolution d'abord, ce qui semble plus rapide sur les connexions lentes et réduit généralement encore le fichier.

Choisissez une valeur de qualité en fonction de l'endroit où l'image est utilisée, pas un seul nombre global :
| Valeur de qualité | Utilisation typique | À quoi s'attendre |
|---|---|---|
| 90-95 | Images vedettes (Hero images), épreuves d'impression | Proche de l'original, fichiers visiblement plus gros |
| 75-85 | La plupart des photos web | Le défaut sûr, économies importantes |
| 60-70 | Vignettes et aperçus | Adoucissement visible sur les détails fins |
| Moins de 50 | À éviter pour les photos | Artefacts en blocs autour des bords |
Un piège qui embrouille presque tout le monde : JPEG n'a pas de canal alpha. Si vous ouvrez une capture d'écran PNG avec transparence et que vous l'enregistrez directement en JPEG, Pillow lève cannot write mode RGBA as JPEG. L'appel convert("RGB") dans la fonction précédente aplatit donc la transparence sur un fond solide au préalable, c'est pourquoi il s'exécute avant chaque enregistrement JPEG.
Compression de PNG et conversion en WebP
PNG est sans perte (lossless), vous ne pouvez donc pas échanger la qualité contre la taille comme vous le faites avec JPEG. Ce que vous pouvez faire, c'est exécuter l'optimiseur de Pillow et, pour tout ce qui est vraiment une photo, changer complètement de format.
def compress_png(src, dst):
Image.open(src).save(dst, "PNG", optimize=True, compress_level=9)
def to_webp(src, dst, quality=80):
img = Image.open(src)
img.save(dst, "WEBP", quality=quality, method=6)
method=6 indique à l'encodeur WebP de passer plus de temps à rechercher un fichier plus petit. Il est plus lent par image mais cela vaut le coup dans une étape de build. Pour une photo qui était initialement un PNG de 2 MB, WebP à qualité 80 atteint régulièrement moins de 200 KB tout en ayant l'air identique à la taille normale de visualisation. Les propres mesures de Google placent WebP environ 25 à 35 pour cent plus petit que le JPEG comparable, selon la documentation WebP.
Utilisez ce tableau pour choisir un format au lieu de deviner :
| Contenu source | Meilleur format | Pourquoi |
|---|---|---|
| Photographie | WebP ou JPEG | Les dégradés lisses se compressent bien en perte (lossy) |
| Logo, icône, UI plate | PNG ou WebP lossless | Les bords nets restent nets |
| Capture d'écran avec texte | PNG ou WebP lossless | Évite le texte flou des passages en perte |
| Image nécessitant de la transparence | WebP ou PNG | JPEG ne peut pas stocker un canal alpha |
Si vous hésitez encore entre formats pour tout un site, l'analyse dans WebP vs JPEG vs PNG couvre le support des navigateurs et les compromis plus en détail.
Atteindre une taille de fichier cible dans une boucle
« Le rendre inférieur à 200 KB » est une exigence courante provenant d'outils d'email, de marketplaces et de limites de téléversement CMS. Vous ne pouvez pas choisir un nombre de qualité qui atteigne une cible en octets du premier coup, car la même qualité produit des tailles très différentes pour une photo chargée par rapport à une image plate. Bouclez à partir d'une haute qualité jusqu'à ce que vous soyez sous le plafond :
def compress_to_target(src, dst, target_kb=200, q=90, floor=35):
img = Image.open(src).convert("RGB")
while q >= floor:
img.save(dst, "JPEG", quality=q, optimize=True, progressive=True)
if os.path.getsize(dst) <= target_kb * 1024:
return q
q -= 5
return q
L'argument floor arrête la boucle avant que la qualité ne tombe dans le territoire du flou (smear territory). Si une image ne peut pas atteindre la cible au-dessus du plancher, la fonction retourne quand même afin que vous puissiez l'enregistrer et redimensionner l'image plutôt que de compresser plus fort. Pour des budgets d'octets fixes comme 100 KB ou 50 KB, le même cycle fonctionne ; le guide dans compress images without losing quality explique quand le redimensionnement bat la baisse de qualité.
Comment réduire les JPEGs avec mozjpeg et cwebp ?
Pillow enregistre les JPEGs avec l'encodeur standard libjpeg. mozjpeg est un encodeur plug-in (drop-in) de Mozilla qui produit des fichiers plus petits à la même qualité visuelle, généralement 5 à 15 pour cent de plus. Étant donné que Pillow ne le regroupe pas, appelez le binaire cjpeg via subprocess. cjpeg de mozjpeg lit les PPM de manière fiable, alors aplatissez l'image avec Pillow d'abord :
import subprocess
def mozjpeg(src, dst, quality=80):
Image.open(src).convert("RGB").save("_tmp.ppm")
subprocess.run(["cjpeg", "-quality", str(quality), "-progressive",
"-optimize", "-outfile", dst, "_tmp.ppm"], check=True)
os.remove("_tmp.ppm")
Pour WebP, appeler cwebp directement vous donne des commandes que Pillow n'expose pas, comme -m 6 pour l'effort maximum et -sharp_yuv pour les bords de couleur plus nets :
def cwebp(src, dst, quality=82):
subprocess.run(["cwebp", "-q", str(quality), "-m", "6",
"-sharp_yuv", src, "-o", dst], check=True)
Voici comment les options se comparent pour que vous puissiez décider quoi installer :
| Outil | Idéal pour | Compromis |
|---|---|---|
| Pillow | Scripting général, tous formats | Pas le plus petit JPEG |
| mozjpeg | Le plus petit JPEG progressif | Binaire supplémentaire, aller-retour PPM |
| cwebp (libwebp) | Contrôle WebP le plus serré | Binaire séparé à installer |
| pillow-simd | Redimensionnement plus rapide sur serveurs x86 | Plus difficile à construire et à épingler |
Le projet mozjpeg documente son encodeur et ses benchmarks dans le répertoire mozjpeg, et la liste complète des options d'enregistrement de Pillow se trouve dans la référence des formats de fichiers image Pillow.
Comment compresser un dossier en lot rapidement ?
Une seule image est facile. La vraie tâche est un répertoire de centaines. Redimensionnez tout ce qui dépasse les besoins de votre mise en page, puis compressez, et exécutez le travail sur des threads pour qu'un dossier de 500 images se termine en secondes au lieu de minutes.

from pathlib import Path
from concurrent.futures import ThreadPoolExecutor
def batch(in_dir, out_dir, quality=80, max_width=1920):
out = Path(out_dir); out.mkdir(parents=True, exist_ok=True)
files = [p for p in Path(in_dir).iterdir()
if p.suffix.lower() in {".jpg", ".jpeg", ".png"}]
def work(p):
img = Image.open(p)
if img.width > max_width:
h = round(img.height * max_width / img.width)
img = img.resize((max_width, h), Image.LANCZOS)
img.convert("RGB").save(out / f"{p.stem}.jpg", "JPEG",
quality=quality, optimize=True, progressive=True)
with ThreadPoolExecutor() as pool:
list(pool.map(work, files))
return len(files)
Quelques notes pratiques issues de l'exécution de ceci en production :
- Redimensionnez avant de compresser. Servir une photo de 6000 px pour une colonne de 1200 px gaspille des octets qu'aucun réglage de qualité ne peut récupérer.
- Pillow libère le GIL pendant l'encodage, donc les threads donnent un vrai gain de vitesse ici ; vous n'avez pas besoin de multiprocessing pour la plupart des dossiers.
- Écrivez vers un répertoire de sortie séparé afin qu'une mauvaise exécution n'écrase jamais vos originaux.
- Utilisez
Image.LANCZOSpour le sous-échantillonnage (downscaling) ; il garde les bords plus nets que le filtre par défaut. - Enregistrez chaque fichier avec l'aide
reportet conservez les originaux jusqu'à ce que vous ayez examiné un échantillon.
Si votre tâche est récurrente plutôt que ponctuelle, les modèles dans batch image processing couvrent les files d'attente (queues), les tentatives (retries) et les conventions de nommage. Pour une exécution sans code sur un zip de fichiers, le outil par lots et le convertisseur d'images gèrent les changements de format sans script.
Quelle approche devriez-vous choisir ?
Associez la méthode à la tâche plutôt que de toujours chercher l'outil le plus puissant :
- Photos web dans une étape de build : Pillow WebP à qualité 80, ou cwebp avec
-m 6lorsque vous voulez les derniers pour cent. - Un budget d'octets strict : la boucle
compress_to_target, qui revient au redimensionnement lorsque le plancher est atteint. - Pipelines JPEG hérités que vous ne pouvez pas changer : réencodez la sortie avec mozjpeg pour des économies gratuites.
- Captures d'écran et diagrammes : conservez PNG avec
optimize=True, ou WebP lossless si vos navigateurs le supportent.
Pour la théorie expliquant pourquoi ces réglages fonctionnent, le guide de compression d'images explique ce qui est en perte (lossy) versus sans perte (lossless) et comment les tables de quantification affectent le résultat.
Erreurs courantes et corrections
Une poignée d'exceptions sont responsables de la plupart des exécutions échouées :
cannot write mode RGBA as JPEG— appelezimg.convert("RGB")avant d'enregistrer en JPEG.Image.DecompressionBombError— Pillow protège contre les images énormes ; augmentez la limite uniquement pour les fichiers en lesquels vous avez confiance avecImage.MAX_IMAGE_PIXELS = 200_000_000.OSError: broken data stream— le fichier source est tronqué ; définissezImageFile.LOAD_TRUNCATED_IMAGES = Truepour le récupérer, puis retéléchargez lorsque c'est possible.- Sortie plus grande que l'entrée — vous avez réenregistré un JPEG déjà compressé ; compressez à partir de l'original, pas d'une exportation précédente.
- Les couleurs semblent délavées — une source CMYK a été enregistrée sans conversion ; appelez
convert("RGB")en premier.
from PIL import Image, ImageFile
Image.MAX_IMAGE_PIXELS = 200_000_000
ImageFile.LOAD_TRUNCATED_IMAGES = True

Conclusion clé
Pillow gère 90 pour cent de la compression d'images en Python avec trois drapeaux JPEG et un enregistrement WebP. Utilisez mozjpeg et cwebp lorsque vous avez besoin des fichiers les plus petits possibles, enveloppez tout dans la boucle de taille cible lorsqu'un budget d'octets est fixe, et faites passer un dossier par la fonction batch threadée lorsque le volume augmente. Conservez vos originaux, redimensionnez avant de compresser, et affichez les économies à chaque exécution afin que vous sachiez toujours ce que fait réellement le pipeline.
Utilisez nos outils gratuits en suivant le guide.
Continuer la lecture

Wed Mar 18 2026 20:00:00 GMT-0400 (北美东部夏令时间)
Convertisseur WebP : Comment convertir des images en WebP (avec des tailles réelles)
Convertissez des images JPEG et PNG en WebP pour des fichiers web plus légers. Tailles mesurées réelles, la commande cwebp, méthodes Python et navigateur, ainsi qu'une stratégie de secours JPEG/PNG.

Tue Mar 17 2026 20:00:00 GMT-0400 (北美东部夏令时间)
PNG vers WebP : Comment convertir et réduire la taille des images PNG
Convertir PNG en WebP pour des fichiers web plus légers. Découvrez quand le WebP sans perte est optimal, les tailles réelles mesurées, et l'utilisation des commandes cwebp et Pillow avec une option de secours PNG.

Tue Mar 10 2026 20:00:00 GMT-0400 (北美东部夏令时间)
Optimisation SEO des images : Checklist pratique 2026
Checklist SEO image pratique pour 2026 : alt text, noms de fichiers, formats, compression, Core Web Vitals, données structurées et mesure.