Fri Jun 26 2026 20:00:00 GMT-0400 (北美东部夏令时间)

Comprimere Immagini in Python con Pillow, WebP e mozjpeg

Comprimi immagini JPEG, PNG e WebP in Python usando Pillow, cwebp e mozjpeg, con impostazioni di qualità, cicli di dimensione target e uno script batch veloce.

Comprimere Immagini in Python con Pillow, WebP e mozjpeg

Ultimo aggiornamento: June 27, 2026

Hai una cartella di JPEG dimensionati per fotocamere, un passaggio di build che li invia agli utenti e un budget di peso della pagina che continua a esplodere. Comprimere questi file manualmente in un editor di immagini non è scalabile. Questa guida mostra esattamente il Python di cui hai bisogno per ridurre i file JPEG, PNG e WebP su un programma, in un job CI o all'interno di un gestore di upload.

Risposta rapida: come si comprimono le immagini con Python?

Apri l'immagine con Pillow e poi salvala con i giusti flag di formato. Per le foto, salva come JPEG con quality=80, optimize=True e progressive=True. Per i file moderni più piccoli, salva come WebP con quality=80, method=6. Per grafiche piatte e screenshot, mantieni PNG e passa 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)

Quella funzione di quattro righe riduce già la maggior parte dei JPEG provenienti da telefoni e DSLR dal 40 al 70 percento. Il resto di questa guida aggiunge obiettivi di dimensione, WebP, mozjpeg e un runner batch in modo che tu possa puntarlo a una directory e allontanarti.

Cosa ti serve prima di iniziare?

Hai bisogno di Python 3.9 o successivo e Pillow, la forca mantenuta di PIL. Pillow gestisce JPEG, PNG e WebP direttamente su ogni piattaforma comune.

pip install Pillow

Per l'output più piccolo vorrai anche due encoder da riga di comando che Python può chiamare: cwebp da libwebp e cjpeg da mozjpeg.

brew install webp mozjpeg   # macOS; Linux: apt install webp, build mozjpeg

Controlla lo scopo di ogni componente prima di scrivere codice:

  • Pillow legge e scrive ogni formato ed esegue il ridimensionamento.
  • cwebp produce i file WebP più compatti e espone maggiori opzioni di tuning rispetto a Pillow.
  • mozjpeg ricodifica JPEG più piccoli dello standard libjpeg utilizzato da Pillow.
  • Un helper di reporting in modo che ogni esecuzione stampi quanti byte sono stati risparmiati.

Ecco l'helper utilizzato in tutta questa guida:

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}% più piccolo)")

Se hai solo bisogno di una compressione occasionale e non vuoi installare nulla, il compressore di immagini basato su browser fa lo stesso lavoro per un piccolo numero di file.

Come comprimere un JPEG con Pillow?

I tre flag che contano per JPEG sono quality, optimize e progressive. quality controlla quanta attenzione l'encoder scarta. optimize=True esegue un secondo passaggio per costruire una tabella Huffman più piccola. progressive=True riordina il file in modo che venga dipinto dall'alto verso il basso a bassa risoluzione prima, cosa che sembra più veloce su connessioni lente e di solito riduce il file un po' di più.

Laptop su un tavolo di legno che mostra codice sorgente aperto in un editor

Scegli un valore di qualità basandoti sul luogo in cui viene utilizzata l'immagine, non su un singolo numero globale:

Valore di qualità Utilizzo tipico Cosa aspettarsi
90-95 Immagini eroiche, prove stampa Vicino all'originale, file notevolmente più grandi
75-85 La maggior parte delle foto web Il default sicuro, grandi risparmi
60-70 Miniature e anteprime Ammorbidimento visibile nei dettagli fini
Sotto 50 Evitare per le foto Artefatti a blocchi sui bordi

Un errore comune fa inciampare quasi tutti: JPEG non ha un canale alfa. Se apri uno screenshot PNG con trasparenza e lo salvi direttamente in JPEG, Pillow solleva cannot write mode RGBA as JPEG. La chiamata convert("RGB") nella funzione precedente appiattisce la trasparenza su uno sfondo solido per prima cosa, motivo per cui viene eseguita prima di ogni salvataggio JPEG.

Comprimere PNG e convertire in WebP

PNG è lossless, quindi non puoi scambiare qualità con dimensione come fai con JPEG. Quello che puoi fare è eseguire l'ottimizzatore di Pillow e, per qualsiasi cosa sia realmente una foto, cambiare completamente formato.

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 dice all'encoder WebP di dedicare più tempo alla ricerca di un file più piccolo. È più lento per immagine ma ne vale la pena in un passaggio di build. Per una foto che è partita come PNG da 2 MB, WebP a qualità 80 atterra regolarmente sotto i 200 KB mantenendo un aspetto identico a dimensioni normali di visualizzazione. Le misurazioni di Google pongono WebP circa dal 25 al 35 percento più piccolo rispetto a JPEG comparabile, come documentato in WebP documentation.

Usa questa tabella per scegliere un formato invece di indovinare:

Contenuto sorgente Miglior formato Perché
Fotografia WebP o JPEG I gradienti lisci si comprimono bene in modo lossy
Logo, icona, UI piatta PNG o WebP lossless I bordi netti rimangono nitidi
Screenshot con testo PNG o WebP lossless Evita il testo sfocato dei passaggi lossy
Immagine che necessita di trasparenza WebP o PNG JPEG non può memorizzare un canale alfa

Se stai ancora decidendo tra formati per un intero sito, la ripartizione in WebP vs JPEG vs PNG copre il supporto del browser e i compromessi più approfonditamente.

Raggiungere una dimensione file target in un ciclo

"Rendilo inferiore a 200 KB" è un requisito comune da strumenti email, marketplace e limiti di upload CMS. Non puoi scegliere un numero di qualità che raggiunga un obiettivo di byte al primo tentativo, perché la stessa qualità produce dimensioni molto diverse per una foto complessa rispetto a una piatta. Cicla dal livello di qualità più alto fino a quando non rientri nel limite:

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'argomento floor interrompe il ciclo prima che la qualità scenda nel territorio della sfocatura. Se un'immagine non può raggiungere l'obiettivo sopra il limite, la funzione restituisce comunque in modo che tu possa registrarlo e ridimensionare l'immagine invece di comprimere più duramente. Per budget di byte fissi come 100 KB o 50 KB, lo stesso ciclo funziona; la guida passo passo in compress images without losing quality spiega quando il ridimensionamento batte abbassare la qualità.

Come ridurre le dimensioni dei JPEG con mozjpeg e cwebp?

Pillow salva i JPEG con lo standard encoder libjpeg. mozjpeg è un encoder plug-in da Mozilla che produce file più piccoli alla stessa qualità visiva, di solito un ulteriore 5-15 percento. Poiché Pillow non lo include, chiama il binario cjpeg tramite subprocess. cjpeg di mozjpeg legge PPM in modo affidabile, quindi appiattisci l'immagine con Pillow per prima:

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")

Per WebP, chiamare cwebp direttamente ti dà manopole che Pillow non espone, come -m 6 per lo sforzo massimo e -sharp_yuv per bordi colore più puliti:

def cwebp(src, dst, quality=82):
    subprocess.run(["cwebp", "-q", str(quality), "-m", "6",
                    "-sharp_yuv", src, "-o", dst], check=True)

Ecco come si confrontano le opzioni in modo che tu possa decidere cosa installare:

Strumento Ideale per Compromesso
Pillow Scripting generale, ogni formato Non è il JPEG più piccolo
mozjpeg Il JPEG progressivo più piccolo Binario extra, round-trip PPM
cwebp (libwebp) Controllo WebP più stretto Binario separato da installare
pillow-simd Ridimensionamento più veloce su server x86 Più difficile da costruire e vincolare

Il progetto mozjpeg documenta il suo encoder e i benchmark in mozjpeg repository, e l'elenco completo delle opzioni di salvataggio di Pillow si trova in Pillow image file formats reference.

Come comprimere una cartella velocemente?

Un singolo immagine è facile. Il vero compito è una directory di centinaia. Ridimensiona tutto più largo del necessario per il tuo layout, poi comprime ed esegui il lavoro attraverso i thread in modo che una cartella da 500 immagini finisca in secondi anziché minuti.

Sviluppatore su una workstation multi-monitor che esegue codice indossando cuffie

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)

Alcune note pratiche derivanti dall'esecuzione di questo in produzione:

  1. Ridimensiona prima di comprimere. Servire una foto da 6000 px per una colonna da 1200 px spreca byte che nessuna impostazione di qualità può recuperare.
  2. Pillow rilascia il GIL durante l'encoding, quindi i thread danno un vero aumento di velocità qui; non hai bisogno di multiprocessing per la maggior parte delle cartelle.
  3. Scrivi in una directory di output separata in modo che un fallimento non sovrascriva mai i tuoi originali.
  4. Usa Image.LANCZOS per il downscaling; mantiene i bordi più nitidi del filtro predefinito.
  5. Registra ogni file con l'helper report e conserva gli originali finché non hai esaminato un campione.

Se il tuo lavoro è ricorrente piuttosto che occasionale, i modelli in batch image processing coprono code, tentativi di ripristino e convenzioni di denominazione. Per un'esecuzione senza codice su uno zip di file, lo strumento batch e l'immagine converter gestiscono i cambiamenti di formato senza script.

Quale approccio dovresti scegliere?

Abbina il metodo al lavoro piuttosto che cercare sempre lo strumento più pesante:

  • Foto web in un passaggio di build: Pillow WebP a qualità 80, o cwebp con -m 6 quando vuoi l'ultimo paio di percento.
  • Un budget di byte rigoroso: il ciclo compress_to_target, che fa affidamento su un ridimensionamento quando viene raggiunto il limite.
  • Pipeline JPEG legacy che non puoi cambiare: ricodifica l'output con mozjpeg per risparmi gratuiti.
  • Screenshot e diagrammi: mantieni PNG con optimize=True, o WebP lossless se i tuoi browser lo supportano.

Per la teoria del perché queste impostazioni funzionino, image compression guide spiega lossy contro lossless e come le tabelle di quantizzazione influenzano il risultato.

Errori e correzioni comuni

Un piccolo numero di eccezioni account per la maggior parte dei fallimenti:

  • cannot write mode RGBA as JPEG — chiama img.convert("RGB") prima di salvare in JPEG.
  • Image.DecompressionBombError — Pillow protegge contro immagini enormi; alza il limite solo per file che ti fidi con Image.MAX_IMAGE_PIXELS = 200_000_000.
  • OSError: broken data stream — il file sorgente è troncato; imposta ImageFile.LOAD_TRUNCATED_IMAGES = True per salvarlo, quindi riscarica quando possibile.
  • Output più grande dell'input — hai risalvato un JPEG già compresso; comprime dall'originale, non da un precedente export.
  • I colori sembrano sbiaditi — una sorgente CMYK è stata salvata senza conversione; chiama convert("RGB") prima.
from PIL import Image, ImageFile
Image.MAX_IMAGE_PIXELS = 200_000_000
ImageFile.LOAD_TRUNCATED_IMAGES = True

Immagine ravvicinata dettagliata di un python su superficie perforata.

Punto chiave

Pillow gestisce il 90 percento della compressione di immagini in Python con tre flag JPEG e un salvataggio WebP. Rivolgiti a mozjpeg e cwebp quando hai bisogno dei file più piccoli possibili, racchiudi tutto nel ciclo target-size quando un budget di byte è fisso, ed esegui una cartella attraverso la funzione batch threadizzata quando il volume cresce. Conserva sempre gli originali, ridimensiona prima di comprimere e stampa i risparmi ad ogni esecuzione in modo da sapere sempre cosa sta facendo effettivamente il pipeline.

Usa gli strumenti gratuiti mentre segui la guida.

Immagine di copertina di PNG a WebP: Come Convertire e Ridurre le Immagini PNG

Tue Mar 17 2026 20:00:00 GMT-0400 (北美东部夏令时间)

PNG a WebP: Come Convertire e Ridurre le Immagini PNG

Converti PNG in WebP per ottenere file web più piccoli. Scopri quando WebP lossless è superiore al lossy, confronta dimensioni reali e usa i comandi cwebp/Pillow con fallback PNG.