Fri Jun 26 2026 20:00:00 GMT-0400 (北美东部夏令时间)
Comprimir Imagens em Python com Pillow, WebP e mozjpeg
Comprima imagens JPEG, PNG e WebP em Python usando Pillow, cwebp e mozjpeg. Inclua configurações de qualidade, loops de tamanho alvo e um script batch rápido.

Última atualização: June 27, 2026
Você tem uma pasta de JPEGs no tamanho de câmera, um passo de build que os envia aos usuários e um orçamento de peso da página que continua explodindo. Comprimir esses arquivos manualmente em um editor de imagem não escala. Este guia mostra o Python exato que você precisa para encolher arquivos JPEG, PNG e WebP em um cronograma, em um job CI ou dentro de um manipulador de upload.
Resposta rápida: como comprimir imagens em Python?
Abra a imagem com Pillow e depois salve-a com as flags de formato corretas. Para fotos, salve como JPEG com quality=80, optimize=True e progressive=True. Para os menores arquivos modernos, salve como WebP com quality=80, method=6. Para gráficos planos e capturas de tela, mantenha PNG e passe 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)
Essa função de quatro linhas já corta a maioria dos JPEGs de celular e DSLR em 40 a 70 por cento. O restante deste guia adiciona alvos de tamanho, WebP, mozjpeg e um batch runner para que você possa apontar para um diretório e ir embora.
O que você precisa antes de começar?
Você precisa do Python 3.9 ou mais recente e Pillow, o fork mantido do PIL. Pillow lida com JPEG, PNG e WebP nativamente em todas as plataformas comuns.
pip install Pillow
Para a menor saída, você também vai querer dois encoders de linha de comando que o Python possa chamar: cwebp do libwebp e cjpeg do mozjpeg.
brew install webp mozjpeg # macOS; Linux: apt install webp, build mozjpeg
Verifique para que serve cada peça antes de escrever código:
- Pillow lê e escreve todos os formatos e faz o redimensionamento.
- cwebp produz os arquivos WebP mais compactos e expõe mais ajustes do que Pillow.
- mozjpeg re-codifica JPEGs menores do que o padrão libjpeg usado pelo Pillow.
- Um helper de relatórios para que cada execução imprima quantos bytes você economizou.
Aqui está o helper usado em todo este guia:
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}% menor)")
Se você precisa apenas de uma compressão pontual e não quer instalar nada, o compressor de imagens baseado em navegador faz o mesmo trabalho para um punhado de arquivos.
Como comprimir um JPEG com Pillow?
As três flags que importam para JPEG são quality, optimize e progressive. quality controla quanto detalhe o encoder descarta. optimize=True executa uma segunda passagem para construir uma tabela Huffman menor. progressive=True reordena o arquivo para que ele pinte de cima para baixo em baixa resolução primeiro, o que parece mais rápido em conexões lentas e geralmente encolhe o arquivo um pouco mais.

Escolha um valor de qualidade baseado onde a imagem será usada, não um único número global:
| Valor de qualidade | Uso típico | O que esperar |
|---|---|---|
| 90-95 | Imagens heroicas, provas de impressão | Próximo ao original, arquivos visivelmente maiores |
| 75-85 | A maioria das fotos da web | O padrão seguro, grandes economias |
| 60-70 | Miniaturas e prévias | Suavização visível em detalhes finos |
| Abaixo de 50 | Evitar para fotos | Artefatos blocados nas bordas |
Um erro comum pega quase todo mundo: JPEG não tem canal alfa. Se você abrir uma captura de tela PNG com transparência e salvá-la diretamente como JPEG, o Pillow levanta cannot write mode RGBA as JPEG. A chamada convert("RGB") na função anterior achata a transparência em um fundo sólido primeiro, razão pela qual ela é executada antes de cada salvamento JPEG.
Comprimindo PNG e convertendo para WebP
PNG é sem perdas (lossless), então você não pode trocar qualidade por tamanho como faz com o JPEG. O que você pode fazer é rodar o otimizador do Pillow e, para qualquer coisa que seja realmente uma foto, mudar completamente o 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 diz ao encoder WebP para gastar mais tempo procurando um arquivo menor. É mais lento por imagem, mas vale a pena em um passo de build. Para uma foto que começou como um PNG de 2 MB, o WebP com qualidade 80 geralmente fica abaixo de 200 KB enquanto parece idêntico no tamanho normal de visualização. As próprias medições do Google colocam o WebP cerca de 25 a 35 por cento menor que JPEG comparável, conforme a documentação WebP.
Use esta tabela para escolher um formato em vez de adivinhar:
| Conteúdo da fonte | Melhor formato | Por quê |
|---|---|---|
| Fotografia | WebP ou JPEG | Gradientes suaves comprimem bem com perdas (lossy) |
| Logo, ícone, UI plana | PNG ou WebP lossless | Bordas nítidas permanecem definidas |
| Captura de tela com texto | PNG ou WebP lossless | Evita texto embaçado de passes com perdas |
| Imagem precisando de transparência | WebP ou PNG | JPEG não pode armazenar um canal alfa |
Se você ainda está decidindo entre formatos para um site inteiro, o detalhamento em WebP vs JPEG vs PNG cobre suporte a navegadores e os trade-offs com mais profundidade.
Atingindo um tamanho de arquivo alvo em um loop
"Deixar abaixo de 200 KB" é um requisito comum de ferramentas de email, marketplaces e limites de upload de CMS. Você não pode escolher um número de qualidade que atinja um alvo de bytes na primeira tentativa, porque a mesma qualidade produz tamanhos muito diferentes para uma foto movimentada versus uma plana. Faça um loop descendo da alta qualidade até cair abaixo do 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
O argumento floor interrompe o loop antes que a qualidade caia para o território de borrão. Se uma imagem não conseguir atingir o alvo acima do limite, a função ainda retorna para que você possa registrá-lo e redimensionar a imagem em vez de comprimir mais. Para orçamentos fixos de bytes como 100 KB ou 50 KB, o mesmo loop funciona; o guia em comprimir imagens sem perder qualidade explica quando redimensionar supera diminuir a qualidade.
Como encolher JPEGs com mozjpeg e cwebp?
Pillow salva JPEGs com o encoder padrão libjpeg. mozjpeg é um encoder drop-in da Mozilla que produz arquivos menores na mesma qualidade visual, geralmente 5 a 15 por cento a mais. Como Pillow não empacota ele, chame o binário cjpeg através de subprocess. O cjpeg do mozjpeg lê PPM de forma confiável, então achate a imagem com Pillow primeiro:
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")
Para WebP, chamar cwebp diretamente dá a você controles que Pillow não expõe, como -m 6 para esforço máximo e -sharp_yuv para bordas de cor mais limpas:
def cwebp(src, dst, quality=82):
subprocess.run(["cwebp", "-q", str(quality), "-m", "6",
"-sharp_yuv", src, "-o", dst], check=True)
Veja como as opções se comparam para que você possa decidir o que instalar:
| Ferramenta | Melhor para | Trade-off |
|---|---|---|
| Pillow | Scripting geral, todos os formatos | Não é o menor JPEG |
| mozjpeg | Menor JPEG progressivo | Binário extra, ida e volta PPM |
| cwebp (libwebp) | Controle WebP mais apertado | Binário separado para instalar |
| pillow-simd | Redimensionamento mais rápido em servidores x86 | Mais difícil de construir e fixar |
O projeto mozjpeg documenta seu encoder e benchmarks no repositório mozjpeg, e a lista completa de opções de salvamento do Pillow está na referência de formatos de arquivo de imagem do Pillow.
Como comprimir uma pasta inteira rapidamente?
Uma única imagem é fácil. A tarefa real é um diretório com centenas. Redimensione qualquer coisa mais larga do que o necessário para seu layout, depois comprima e execute o trabalho através de threads para que uma pasta de 500 imagens termine em segundos em vez de minutos.

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)
Algumas notas práticas de rodar isso em produção:
- Redimensione antes de comprimir. Servir uma foto de 6000 px para uma coluna de 1200 px desperdiça bytes que nenhuma configuração de qualidade pode recuperar.
- Pillow libera o GIL durante a codificação, então as threads dão um aumento real na velocidade aqui; você não precisa de
multiprocessingpara a maioria das pastas. - Escreva em um diretório de saída separado para que uma execução ruim nunca sobrescreva seus originais.
- Use
Image.LANCZOSpara dimensionamento para baixo; ele mantém as bordas mais nítidas do que o filtro padrão. - Registre cada arquivo com o helper
reporte mantenha os originais até ter inspecionado uma amostra.
Se o seu trabalho é recorrente em vez de pontual, os padrões em processamento em lote de imagens cobrem filas, retries e convenções de nomenclatura. Para um rodar sem código sobre um zip de arquivos, o batch tool e o image converter lidam com mudanças de formato sem um script.
Qual abordagem você deve escolher?
Combine o método ao trabalho em vez de sempre recorrer à ferramenta mais pesada:
- Fotos da web em um passo de build: Pillow WebP com qualidade 80, ou cwebp com
-m 6quando você quer os últimos poucos por cento. - Um orçamento estrito de bytes: o loop
compress_to_target, voltando a redimensionar quando o limite é atingido. - Pipelines JPEG legados que você não pode mudar: re-codifique a saída com mozjpeg para economias gratuitas.
- Capturas de tela e diagramas: mantenha PNG com
optimize=True, ou WebP lossless se seus navegadores suportarem.
Para a teoria por trás do motivo pelo qual essas configurações funcionam, o guia de compressão de imagens explica perdas (lossy) versus sem perdas (lossless) e como as tabelas de quantização afetam o resultado.
Erros e correções comuns
Um punhado de exceções conta pela maioria das execuções falhas:
cannot write mode RGBA as JPEG— chameimg.convert("RGB")antes de salvar em JPEG.Image.DecompressionBombError— Pillow protege contra imagens enormes; aumente o limite apenas para arquivos que você confia comImage.MAX_IMAGE_PIXELS = 200_000_000.OSError: broken data stream— o arquivo de origem está truncado; definaImageFile.LOAD_TRUNCATED_IMAGES = Truepara salvá-lo, depois baixe novamente quando possível.- Saída maior que a entrada — você re-salvou um JPEG já comprimido; comprima do original, não de uma exportação anterior.
- Cores parecem lavadas — uma fonte CMYK foi salva sem conversão; chame
convert("RGB")primeiro.
from PIL import Image, ImageFile
Image.MAX_IMAGE_PIXELS = 200_000_000
ImageFile.LOAD_TRUNCATED_IMAGES = True

Conclusão principal
Pillow lida com 90 por cento da compressão de imagens em Python com três flags JPEG e um salvamento WebP. Recorra a mozjpeg e cwebp quando precisar dos arquivos menores possíveis, envolva tudo no loop de tamanho alvo quando um orçamento de bytes for fixo, e passe uma pasta pela função batch threaded quando o volume crescer. Mantenha seus originais, redimensione antes de comprimir e imprima as economias em cada execução para que você sempre saiba o que o pipeline está realmente fazendo.
Use as ferramentas gratuitas enquanto segue o guia.
Continue lendo

Wed Mar 18 2026 20:00:00 GMT-0400 (北美东部夏令时间)
Conversor WebP: Como Converter Imagens para WebP (Tamanhos Reais)
Converta imagens JPEG e PNG para WebP, criando arquivos web menores. Oferecemos tamanhos medidos em tempo real, o comando cwebp, métodos Python/navegador e uma estratégia de fallback JPEG/PNG.

Tue Mar 17 2026 20:00:00 GMT-0400 (北美东部夏令时间)
PNG para WebP: Como Converter e Reduzir Imagens PNG
Converta PNG para WebP para arquivos web menores. Quando o WebP sem perdas é melhor, quando o com perdas funciona, tamanhos reais medidos, e os comandos cwebp e Pillow com um fallback para PNG.

Tue Mar 10 2026 20:00:00 GMT-0400 (北美东部夏令时间)
Otimização de Imagem para SEO: Checklist Prático 2026
Checklist prático de SEO para imagens em 2026: alt text, nomes de arquivo, formatos, compressão, Core Web Vitals, dados estruturados e medição.