Pillow
Pillow é o fork mantido do PIL - a biblioteca padrão para abrir, converter, redimensionar, cortar e salvar imagens em pipelines Python, manipuladores de upload web e pré-processamento de ML.
Receita
from PIL import Image
with Image.open("photo.jpg") as img:
img = ImageOps.exif_transpose(img)
img.thumbnail((800, 800))
img.save("preview.webp", format="WEBP", quality=85)Quando usar:
- Geração de avatar/thumbnail de usuário em aplicativos web
- Conversão em lote de PNG/JPEG/WEBP para CDNs
- Pré-processamento de imagens antes do treinamento PyTorch/torchvision
- Leitura de dimensões e metadados sem carregar a decodificação completa na UI
Exemplo de Trabalho
from __future__ import annotations
from io import BytesIO
from pathlib import Path
from PIL import Image, ImageOps, UnidentifiedImageError
MAX_BYTES = 5 * 1024 * 1024
ALLOWED = {"JPEG", "PNG", "WEBP"}
def make_thumbnail(data: bytes, max_edge: int = 256) -> bytes:
if len(data) > MAX_BYTES:
raise ValueError("arquivo muito grande")
try:
with Image.open(BytesIO(data)) as img:
if img.format not in ALLOWED:
raise ValueError(f"formato não suportado {img.format}")
img = ImageOps.exif_transpose(img)
img = img.convert("RGB")
img.thumbnail((max_edge, max_edge))
out = BytesIO()
img.save(out, format="WEBP", quality=80, method=6)
return out.getvalue()
except UnidentifiedImageError as exc:
raise ValueError("não é uma imagem") from exc
if __name__ == "__main__":
sample = Path("photo.jpg").read_bytes()
Path("thumb.webp").write_bytes(make_thumbnail(sample))O que isto demonstra:
- Limite de tamanho antes da decodificação mitiga bombas de descompressão
exif_transposecorrige fotos de celular rotacionadasconvert("RGB")normaliza os modos antes da exportação WEBP- Pipeline
BytesIOem memória para manipuladores de API - Lista explícita de formatos permitidos
Mergulho Profundo
Como Funciona
- Image.open - Carregamento preguiçoso; a decodificação ocorre no primeiro acesso ao pixel.
- Modos -
RGB,RGBA,L(escala de cinza),P(paleta) - converter antes de formatos que não suportam alfa. - Transformações -
resize,thumbnail,crop,rotate, módulofilterpara blur/sharpen. - Salvando - Formato pela extensão ou argumento
format=; configurações de qualidade variam por codec.
Operações Comuns
| Tarefa | API |
|---|---|
| Caixa delimitadora máxima | thumbnail((w, h)) |
| Dimensões exatas | resize((w, h), Image.Resampling.LANCZOS) |
| Remover EXIF | img.getexif().clear() ou salvar sem exif |
| Desenhar texto | ImageDraw.Draw(img).text(...) |
Notas Python
# Verificar dimensões sem decodificação completa (onde suportado)
with Image.open(path) as img:
width, height = img.sizeArmadilhas
- Bombas de descompressão - PNG minúsculo expande para gigapixel. Correção: verificação de bytes máximos + dimensão máxima pré-decodificação.
- Ignorando orientação EXIF - Thumbnails aparecem de lado. Correção:
ImageOps.exif_transpose. - RGBA para JPEG - Salvar falha ou descarta o alfa de forma estranha. Correção:
convert("RGB")em um fundo branco primeiro. - Não fechar arquivos no Windows - Bloqueio de arquivo na sobrescrita. Correção: gerenciadores de contexto.
- Confiar no Content-Type do cliente - Atacantes falsificam MIME. Correção: validar
img.formatapós abrir. - LANCZOS em imagens enormes - Picos de memória. Correção: primeiro
thumbnail, depoisresizeopcional.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
wand (ImageMagick) | Rasterização complexa de PDF/PSD/SVG | Dependências mais simples (binário ImageMagick necessário) |
opencv-python | Pipelines de CV, detecção de faces | Microserviço simples de thumbnail |
torchvision.transforms | Apenas aumentos em tempo de treinamento | Sanitização geral de upload |
| SaaS image CDN | Descarregar transformações na borda | Cargas de trabalho air-gapped ou sensíveis a custo |
FAQs
O Pillow lê fotos HEIC do iPhone?
Requer o plugin pillow-heif - caso contrário, converta no cliente ou rejeite com erro claro.
Como preservar a transparência em PNG?
Mantenha o modo RGBA; não converta para RGB antes de salvar.
O Pillow pode rodar no AWS Lambda?
Sim, com builds de camada slim - observe o tamanho do pacote e as dependências de bibliotecas nativas.
Como colocar marca d'água em imagens?
Use Image.alpha_composite com uma camada de marca d'água PNG transparente.
Qual filtro de reamostragem para fotos?
Image.Resampling.LANCZOS para downscale; NEAREST para pixel art.
Como ler EXIF de GPS com segurança?
Remova o EXIF de localização em uploads de usuários antes de publicar - requisito de privacidade.
O Pillow suporta AVIF?
Versões recentes do Pillow adicionam AVIF se libavif estiver presente - verifique na imagem de implantação de destino.
Como testar sem fixtures de imagem?
Gere um PNG de cor sólida 10x10 em testes via Image.new("RGB", (10, 10), "red").
Thread-safe?
Não compartilhe objetos Image mutáveis entre threads - abra por tarefa.
Integrar com FastAPI UploadFile?
data = await file.read() então passe os bytes para o pipeline BytesIO com limites de tamanho.
Relacionados
- Skill PyTorch / Deep Learning - pipelines de imagem para treinamento
- Validação de Entrada - segurança de upload
- FastAPI Basics - rotas de upload de arquivos
- Automação de Arquivos e Diretórios - processamento em lote
Versões de Stack: Esta página foi escrita para Python 3.14.0 (estável 3.14, manutenção 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, e uv 0.6+.